diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cb3527f..4914f402 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/conan/mruby/conanfile.py b/conan/mruby/conanfile.py index 0a62fa87..e74fdedb 100644 --- a/conan/mruby/conanfile.py +++ b/conan/mruby/conanfile.py @@ -195,9 +195,9 @@ 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')] + self.cpp_info.defines = defines self.cpp_info.bindirs = ["bin"] if self.settings.os == 'Windows': diff --git a/src/mtconnect/entity/data_set.hpp b/src/mtconnect/entity/data_set.hpp index 55e35631..b566160d 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/printer/json_printer.cpp b/src/mtconnect/printer/json_printer.cpp index 3aa2ea39..cfb5635f 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/src/mtconnect/source/adapter/adapter_pipeline.cpp b/src/mtconnect/source/adapter/adapter_pipeline.cpp index cfde83ad..0c0a8ada 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"; diff --git a/src/mtconnect/utilities.hpp b/src/mtconnect/utilities.hpp index 230f7a66..da603aa7 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 = { + 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)); + 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 5e88dc6f..0b738502 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()); } diff --git a/test_package/json_printer_stream_test.cpp b/test_package/json_printer_stream_test.cpp index 03b1fd8e..40e85c5b 100644 --- a/test_package/json_printer_stream_test.cpp +++ b/test_package/json_printer_stream_test.cpp @@ -173,6 +173,34 @@ 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);