From 795a93e47a7f7970512c7a369b72e1134fe90e2d Mon Sep 17 00:00:00 2001 From: Will Sobel Date: Mon, 7 Jul 2025 20:35:04 +0200 Subject: [PATCH 1/6] fixed pascalize method to handle multiple underscores ('__') --- src/mtconnect/utilities.hpp | 49 +++++++++++++++++---------------- test_package/data_item_test.cpp | 5 ++++ 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/mtconnect/utilities.hpp b/src/mtconnect/utilities.hpp index 230f7a660..222c29a05 100644 --- a/src/mtconnect/utilities.hpp +++ b/src/mtconnect/utilities.hpp @@ -685,25 +685,27 @@ namespace mtconnect { /// /// @param[in,out] start starting iterator /// @param[in,out] end ending iterator - inline void capitalize(std::string::iterator start, std::string::iterator end) + inline void capitalize(std::ostringstream &camel, std::string::const_iterator start, + std::string::const_iterator end) { using namespace std; - + // Exceptions to the rule - const static std::unordered_map exceptions = { - {"AC", "AC"}, {"DC", "DC"}, {"PH", "PH"}, - {"IP", "IP"}, {"URI", "URI"}, {"MTCONNECT", "MTConnect"}}; - - const auto &w = exceptions.find(std::string(start, end)); + const static std::unordered_map exceptions = { + {"AC", "AC"}, {"DC", "DC"}, {"PH", "PH"}, + {"IP", "IP"}, {"URI", "URI"}, {"MTCONNECT", "MTConnect"}}; + + std::string_view s(&*start, distance(start, end)); + const auto &w = exceptions.find(s); + ostream_iterator out(camel); if (w != exceptions.end()) { - copy(w->second.begin(), w->second.end(), start); + copy(w->second.begin(), w->second.end(), out); } else { - *start = ::toupper(*start); - start++; - transform(start, end, start, ::tolower); + camel << static_cast(::toupper(*start)); + transform(start + 1, end, out, ::tolower); } } @@ -721,34 +723,33 @@ namespace mtconnect { if (type.empty()) return ""; - string camel; + ostringstream camel; + + auto start = type.begin(); + decltype(start) end; + auto colon = type.find(':'); if (colon != string::npos) { prefix = type.substr(0ul, colon); - camel = type.substr(colon + 1ul); + start += colon + 1; } - else - camel = type; - - auto start = camel.begin(); - decltype(start) end; bool done; do { - end = find(start, camel.end(), '_'); - capitalize(start, end); - done = end == camel.end(); + end = find(start, type.end(), '_'); + if (start != end) + capitalize(camel, start, end); + done = end == type.end(); if (!done) { - camel.erase(end); - start = end; + start = end + 1; } } while (!done); - return camel; + return camel.str(); } /// @brief parse a string timestamp to a `Timestamp` diff --git a/test_package/data_item_test.cpp b/test_package/data_item_test.cpp index 5e88dc6f1..11eab8f4d 100644 --- a/test_package/data_item_test.cpp +++ b/test_package/data_item_test.cpp @@ -163,9 +163,14 @@ TEST_F(DataItemTest, GetCamel) ASSERT_EQ((string) "CamelCase", pascalize("CAMEL_CASE", prefix)); ASSERT_EQ((string) "ABCc", pascalize("A_B_CC", prefix)); + ASSERT_EQ((string) "ThreeHumpCamelCase", pascalize("THREE_HUMP_CAMEL_CASE", prefix)); + prefix.reset(); ASSERT_EQ((string) "CamelCase", pascalize("x:CAMEL_CASE", prefix)); ASSERT_EQ((string) "x", *prefix); + prefix.reset(); + ASSERT_EQ((string) "MySillyTag", pascalize("y:MY__SILLY_TAG", prefix)); + ASSERT_EQ((string) "y", *prefix); } TEST_F(DataItemTest, Condition) { ASSERT_EQ(DataItem::CONDITION, m_dataItemC->getCategory()); } From 494e918224ee1d9f28e247df3372d8a0a071f269 Mon Sep 17 00:00:00 2001 From: Will Sobel Date: Mon, 7 Jul 2025 21:11:00 +0200 Subject: [PATCH 2/6] Fixed empty version 1 stream. It is now an empty array --- src/mtconnect/printer/json_printer.cpp | 5 +++- test_package/json_printer_stream_test.cpp | 29 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/mtconnect/printer/json_printer.cpp b/src/mtconnect/printer/json_printer.cpp index 3aa2ea39b..cfb5635f3 100644 --- a/src/mtconnect/printer/json_printer.cpp +++ b/src/mtconnect/printer/json_printer.cpp @@ -439,7 +439,10 @@ namespace mtconnect::printer { } else { - AutoJsonObject streams(writer, "Streams"); + if (m_jsonVersion == 1) + AutoJsonArray streams(writer, "Streams"); + else + AutoJsonObject streams(writer, "Streams"); } } }); diff --git a/test_package/json_printer_stream_test.cpp b/test_package/json_printer_stream_test.cpp index 03b1fd8e2..64d9a7063 100644 --- a/test_package/json_printer_stream_test.cpp +++ b/test_package/json_printer_stream_test.cpp @@ -173,6 +173,35 @@ TEST_F(JsonPrinterStreamTest, DeviceStream) stream.at("/uuid"_json_pointer).get()); } +TEST_F(JsonPrinterStreamTest, should_use_array_for_empty_version_1_stream) +{ + Checkpoint checkpoint; + ObservationList list; + checkpoint.getObservations(list); + auto doc = m_printer->printSample(123, 131072, 10254805, 10123733, 10123800, list); + + auto jdoc = json::parse(doc); + json stream = jdoc.at("/MTConnectStreams/Streams"_json_pointer); + ASSERT_TRUE(stream.is_array()); + ASSERT_EQ(0, stream.size()); +} + +TEST_F(JsonPrinterStreamTest, should_use_object_for_empty_version_2_stream) +{ + m_printer = std::make_unique(2, true); + + Checkpoint checkpoint; + ObservationList list; + checkpoint.getObservations(list); + auto doc = m_printer->printSample(123, 131072, 10254805, 10123733, 10123800, list); + + auto jdoc = json::parse(doc); + json stream = jdoc.at("/MTConnectStreams/Streams"_json_pointer); + ASSERT_TRUE(stream.is_object()); + ASSERT_EQ(0, stream.size()); +} + + TEST_F(JsonPrinterStreamTest, DeviceStream_version_2_one_device) { m_printer = std::make_unique(2, true); From 08423783fd0bbc4ae76f99107bf604b10e314af0 Mon Sep 17 00:00:00 2001 From: Will Sobel Date: Mon, 7 Jul 2025 21:32:27 +0200 Subject: [PATCH 3/6] Changed validation transform order --- CMakeLists.txt | 2 +- src/mtconnect/source/adapter/adapter_pipeline.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cb3527f2..4914f4024 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ set(AGENT_VERSION_MAJOR 2) set(AGENT_VERSION_MINOR 5) set(AGENT_VERSION_PATCH 0) -set(AGENT_VERSION_BUILD 10) +set(AGENT_VERSION_BUILD 11) set(AGENT_VERSION_RC "") # This minimum version is to support Visual Studio 2019 and C++ feature checking and FetchContent diff --git a/src/mtconnect/source/adapter/adapter_pipeline.cpp b/src/mtconnect/source/adapter/adapter_pipeline.cpp index cfde83adb..8c4b34baa 100644 --- a/src/mtconnect/source/adapter/adapter_pipeline.cpp +++ b/src/mtconnect/source/adapter/adapter_pipeline.cpp @@ -144,15 +144,15 @@ namespace mtconnect { if (IsOptionSet(m_options, configuration::CorrectTimestamps)) next = next->bind(make_shared(m_context)); - // Validate Values - if (IsOptionSet(m_options, configuration::Validation)) - next = next->bind(make_shared(m_context)); - // Filter dups, by delta, and by period next = next->bind(make_shared(m_context)); next = next->bind(make_shared(m_context)); next = next->bind(make_shared(m_context, m_strand)); + // Validate Values + if (IsOptionSet(m_options, configuration::Validation)) + next = next->bind(make_shared(m_context)); + // Deliver std::optional obsMetrics; obsMetrics = m_identity + "_observation_update_rate"; From 671069e1353e489ac3fe341bdf5c0a477b94a88b Mon Sep 17 00:00:00 2001 From: Will Sobel Date: Mon, 7 Jul 2025 21:33:12 +0200 Subject: [PATCH 4/6] Formatted with clangformat --- src/mtconnect/entity/data_set.hpp | 6 +++--- src/mtconnect/source/adapter/adapter_pipeline.cpp | 2 +- src/mtconnect/utilities.hpp | 12 ++++++------ test_package/data_item_test.cpp | 2 +- test_package/json_printer_stream_test.cpp | 5 ++--- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/mtconnect/entity/data_set.hpp b/src/mtconnect/entity/data_set.hpp index 55e35631c..b566160d7 100644 --- a/src/mtconnect/entity/data_set.hpp +++ b/src/mtconnect/entity/data_set.hpp @@ -48,7 +48,7 @@ namespace mtconnect::entity { { return std::holds_alternative(v1) && std::get(v1) == v2; } - + /// @brief One entry in a data set. Has necessary interface to be work with maps. /// @tparam T The type of the underlying variant data template @@ -109,8 +109,8 @@ namespace mtconnect::entity { /// @param other the other value to compare against `m_value` /// @returns `true` if the values are the same /// - /// Compares using the `SameValue` free function in the `data_set` namespace. It must be overloaded - /// for any special types required by the variant type T. + /// Compares using the `SameValue` free function in the `data_set` namespace. It must be + /// overloaded for any special types required by the variant type T. bool sameValue(const Entry &other) const { const auto &ov = other.m_value; diff --git a/src/mtconnect/source/adapter/adapter_pipeline.cpp b/src/mtconnect/source/adapter/adapter_pipeline.cpp index 8c4b34baa..0c0a8ada4 100644 --- a/src/mtconnect/source/adapter/adapter_pipeline.cpp +++ b/src/mtconnect/source/adapter/adapter_pipeline.cpp @@ -152,7 +152,7 @@ namespace mtconnect { // Validate Values if (IsOptionSet(m_options, configuration::Validation)) next = next->bind(make_shared(m_context)); - + // Deliver std::optional obsMetrics; obsMetrics = m_identity + "_observation_update_rate"; diff --git a/src/mtconnect/utilities.hpp b/src/mtconnect/utilities.hpp index 222c29a05..da603aa7b 100644 --- a/src/mtconnect/utilities.hpp +++ b/src/mtconnect/utilities.hpp @@ -689,12 +689,12 @@ namespace mtconnect { std::string::const_iterator end) { using namespace std; - + // Exceptions to the rule const static std::unordered_map exceptions = { - {"AC", "AC"}, {"DC", "DC"}, {"PH", "PH"}, - {"IP", "IP"}, {"URI", "URI"}, {"MTCONNECT", "MTConnect"}}; - + {"AC", "AC"}, {"DC", "DC"}, {"PH", "PH"}, + {"IP", "IP"}, {"URI", "URI"}, {"MTCONNECT", "MTConnect"}}; + std::string_view s(&*start, distance(start, end)); const auto &w = exceptions.find(s); ostream_iterator out(camel); @@ -724,10 +724,10 @@ namespace mtconnect { return ""; ostringstream camel; - + auto start = type.begin(); decltype(start) end; - + auto colon = type.find(':'); if (colon != string::npos) diff --git a/test_package/data_item_test.cpp b/test_package/data_item_test.cpp index 11eab8f4d..0b7385024 100644 --- a/test_package/data_item_test.cpp +++ b/test_package/data_item_test.cpp @@ -164,7 +164,7 @@ TEST_F(DataItemTest, GetCamel) ASSERT_EQ((string) "ABCc", pascalize("A_B_CC", prefix)); ASSERT_EQ((string) "ThreeHumpCamelCase", pascalize("THREE_HUMP_CAMEL_CASE", prefix)); - + prefix.reset(); ASSERT_EQ((string) "CamelCase", pascalize("x:CAMEL_CASE", prefix)); ASSERT_EQ((string) "x", *prefix); diff --git a/test_package/json_printer_stream_test.cpp b/test_package/json_printer_stream_test.cpp index 64d9a7063..40e85c5bf 100644 --- a/test_package/json_printer_stream_test.cpp +++ b/test_package/json_printer_stream_test.cpp @@ -179,7 +179,7 @@ TEST_F(JsonPrinterStreamTest, should_use_array_for_empty_version_1_stream) ObservationList list; checkpoint.getObservations(list); auto doc = m_printer->printSample(123, 131072, 10254805, 10123733, 10123800, list); - + auto jdoc = json::parse(doc); json stream = jdoc.at("/MTConnectStreams/Streams"_json_pointer); ASSERT_TRUE(stream.is_array()); @@ -194,14 +194,13 @@ TEST_F(JsonPrinterStreamTest, should_use_object_for_empty_version_2_stream) ObservationList list; checkpoint.getObservations(list); auto doc = m_printer->printSample(123, 131072, 10254805, 10123733, 10123800, list); - + auto jdoc = json::parse(doc); json stream = jdoc.at("/MTConnectStreams/Streams"_json_pointer); ASSERT_TRUE(stream.is_object()); ASSERT_EQ(0, stream.size()); } - TEST_F(JsonPrinterStreamTest, DeviceStream_version_2_one_device) { m_printer = std::make_unique(2, true); From f722ee922a124781fb2ef0cbca04606d4c960ff5 Mon Sep 17 00:00:00 2001 From: Will Sobel Date: Tue, 8 Jul 2025 11:47:19 +0200 Subject: [PATCH 5/6] Fixed conanfile for mruby due to changes in conan version 2.18 --- conan/mruby/conanfile.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/conan/mruby/conanfile.py b/conan/mruby/conanfile.py index 0a62fa874..bfe2bef0a 100644 --- a/conan/mruby/conanfile.py +++ b/conan/mruby/conanfile.py @@ -195,9 +195,10 @@ def package_info(self): buf = io.StringIO() self.run("{} --cflags".format(ruby), stdout=buf, shell=True) - self.cpp_info.defines = [d[2:] for d in buf.getvalue().split(' ') if d.startswith('/D') or d.startswith('-D')] - self.conf_info.define('mruby', 'ON') + defines = [d[2:] for d in buf.getvalue().split(' ') if d.startswith('/D') or d.startswith('-D')] + defines.append('mruby=ON') + self.cpp_info.defines = defines self.cpp_info.bindirs = ["bin"] if self.settings.os == 'Windows': From 7bef848aca23bc8500f065c2a180a62c973ebbf3 Mon Sep 17 00:00:00 2001 From: Will Sobel Date: Tue, 8 Jul 2025 12:02:41 +0200 Subject: [PATCH 6/6] Removed unused define in mruby conanfile. --- conan/mruby/conanfile.py | 1 - 1 file changed, 1 deletion(-) diff --git a/conan/mruby/conanfile.py b/conan/mruby/conanfile.py index bfe2bef0a..e74fdedbb 100644 --- a/conan/mruby/conanfile.py +++ b/conan/mruby/conanfile.py @@ -197,7 +197,6 @@ def package_info(self): self.run("{} --cflags".format(ruby), stdout=buf, shell=True) defines = [d[2:] for d in buf.getvalue().split(' ') if d.startswith('/D') or d.startswith('-D')] - defines.append('mruby=ON') self.cpp_info.defines = defines self.cpp_info.bindirs = ["bin"]