From d06546b84c619d1519d03311222b8aea823a65ab Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Fri, 23 Aug 2024 11:16:49 -0400 Subject: [PATCH 1/8] - Add in number string normalization. normalizeNumericString() - Use in Document new value normalization interface: Document.normalizeValueStrings() - Add in unit tests for each. --- source/MaterialXCore/Document.cpp | 28 +++++++++++ source/MaterialXCore/Document.h | 4 ++ source/MaterialXCore/Util.cpp | 42 +++++++++++++++++ source/MaterialXCore/Util.h | 4 ++ .../MaterialXTest/MaterialXCore/CoreUtil.cpp | 23 +++++++++ .../MaterialXTest/MaterialXCore/Document.cpp | 47 +++++++++++++++++++ .../PyMaterialXCore/PyDocument.cpp | 3 +- source/PyMaterialX/PyMaterialXCore/PyUtil.cpp | 1 + 8 files changed, 151 insertions(+), 1 deletion(-) diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index 7ebdab0aa7..7b15d84e24 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -4,6 +4,7 @@ // #include +#include #include @@ -401,6 +402,33 @@ void Document::invalidateCache() _cache->valid = false; } +void Document::normalizeValueStrings(unsigned int numericPrecision) +{ + // For now this will only normalize numeric strings + StringSet numericType = { "float", "vector2", "vector3", "vector4", "color3", "color4" }; + for (ElementPtr elem : traverseTree()) + { + ValueElementPtr valueElem = elem->asA(); + if (!valueElem || numericType.end() == numericType.find(valueElem->getType())) + { + continue; + } + + const string& originalString = valueElem->getValueString(); + if (originalString.empty()) + { + continue; + } + + string normalizeString = normalizeNumericString(originalString, numericPrecision); + if (normalizeString != originalString) + { + valueElem->setValueString(normalizeString); + } + } +} + + // // Deprecated methods // diff --git a/source/MaterialXCore/Document.h b/source/MaterialXCore/Document.h index a14a5edf7b..afeec7f336 100644 --- a/source/MaterialXCore/Document.h +++ b/source/MaterialXCore/Document.h @@ -663,6 +663,10 @@ class MX_CORE_API Document : public GraphElement /// Invalidate cached data for optimized lookups within the given document. void invalidateCache(); + /// Normalize value strings for all numeric values attributes + /// @param numericPrecision Precision to use for floating point numbers. Default is 6. + void normalizeValueStrings(unsigned int numericPrecision = 6); + /// @} // diff --git a/source/MaterialXCore/Util.cpp b/source/MaterialXCore/Util.cpp index 639b8f343c..b41316f64a 100644 --- a/source/MaterialXCore/Util.cpp +++ b/source/MaterialXCore/Util.cpp @@ -6,6 +6,8 @@ #include #include +#include +#include MATERIALX_NAMESPACE_BEGIN @@ -179,4 +181,44 @@ string parentNamePath(const string& namePath) return EMPTY_STRING; } +string normalizeNumericString(const string& str, unsigned int precision) +{ + std::stringstream ss(str); + std::stringstream result; + std::string token; + + while (std::getline(ss, token, ',')) { + // Remove leading and trailing spaces + token.erase(0, token.find_first_not_of(' ')); + token.erase(token.find_last_not_of(' ') + 1); + + // Convert the string to a double (automatically removes leading zeros) + double number = std::stod(token); + + // Format the number with the specified precision + result << std::fixed << std::setprecision(precision) << number; + + // Remove unnecessary trailing zeros + std::string formattedNumber = result.str(); + formattedNumber.erase(formattedNumber.find_last_not_of('0') + 1, std::string::npos); + if (formattedNumber.back() == '.') { + formattedNumber.pop_back(); // Remove the trailing dot if there's no decimal part left + } + + // Append the formatted number to the result + result.str(EMPTY_STRING); // Clear the stringstream for the next number + result.clear(); + result << formattedNumber << ","; + } + + std::string output = result.str(); + + // Remove the last comma + if (!output.empty()) { + output.pop_back(); + } + + return output; +} + MATERIALX_NAMESPACE_END diff --git a/source/MaterialXCore/Util.h b/source/MaterialXCore/Util.h index d6a834be05..ad4ff37479 100644 --- a/source/MaterialXCore/Util.h +++ b/source/MaterialXCore/Util.h @@ -69,6 +69,10 @@ MX_CORE_API string createNamePath(const StringVec& nameVec); /// Given a name path, return the parent name path MX_CORE_API string parentNamePath(const string& namePath); +/// Normalize a string containing a numeric value. This can +/// either be a single number or an array of comma seperated numbers. +MX_CORE_API string normalizeNumericString(const string& str, unsigned int precision = 6); + MATERIALX_NAMESPACE_END #endif diff --git a/source/MaterialXTest/MaterialXCore/CoreUtil.cpp b/source/MaterialXTest/MaterialXCore/CoreUtil.cpp index 11aa826d4f..d4ed712e43 100644 --- a/source/MaterialXTest/MaterialXCore/CoreUtil.cpp +++ b/source/MaterialXTest/MaterialXCore/CoreUtil.cpp @@ -7,6 +7,7 @@ #include #include +#include namespace mx = MaterialX; @@ -36,6 +37,28 @@ TEST_CASE("String utilities", "[coreutil]") REQUIRE(!mx::stringStartsWith("testName", "Name")); REQUIRE(mx::stringEndsWith("testName", "Name")); REQUIRE(!mx::stringEndsWith("testName", "test")); + + std::string inputScalar1 = " 00.1000 "; + std::string resultScalar1 = mx::normalizeNumericString(inputScalar1); + REQUIRE(resultScalar1 == "0.1"); + std::string inputScalar2 = "0.1234567890"; + std::string resultScalar2 = mx::normalizeNumericString(inputScalar2, 3); + REQUIRE(resultScalar2 == "0.123"); + std::string resultScalar3 = mx::normalizeNumericString(inputScalar2, 12); + REQUIRE(resultScalar3 == "0.123456789"); + std::string inputScalar3 = "0.12345678901234567890"; + std::string resultScalar4 = mx::normalizeNumericString(inputScalar3, 9); + REQUIRE(resultScalar4 == "0.123456789"); + + std::string inputVector1 = "1.0, 2.0, 0000.231"; + std::string inputVector2 = "0001.2000, 0000.00010"; + std::string resultVector1 = mx::normalizeNumericString(inputVector1); + REQUIRE(resultVector1 == "1,2,0.231"); + std::string resultVector2 = mx::normalizeNumericString(inputVector2); + REQUIRE(resultVector2 == "1.2,0.0001"); + std::string inputVector3 = "01.0, 2.0, 0000.2310"; + std::string resultVector3 = mx::normalizeNumericString(inputVector3); + REQUIRE(resultVector3 == resultVector1); } TEST_CASE("Print utilities", "[coreutil]") diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp index fb35e58ccb..8e18d5e706 100644 --- a/source/MaterialXTest/MaterialXCore/Document.cpp +++ b/source/MaterialXTest/MaterialXCore/Document.cpp @@ -10,6 +10,8 @@ #include #include +#include + namespace mx = MaterialX; TEST_CASE("Document", "[document]") @@ -116,3 +118,48 @@ TEST_CASE("Document", "[document]") // Validate the combined document. REQUIRE(doc->validate()); } + +TEST_CASE("Document equivalence", "[document2]") +{ + mx::DocumentPtr doc = mx::createDocument(); + std::multimap inputMap; + + inputMap.insert({ "color3", " 1.0, +2.0, 3.0 " }); + inputMap.insert({ "color4", "1.0, 2.00, 0.3000, -4" }); + inputMap.insert({ "float", " 00.1000 " }); + inputMap.insert({ "vector2", "1.0, 0.012345678" }); + inputMap.insert( {"vector3", " 1.0, +2.0, 3.0 " }); + inputMap.insert( {"vector4", "1.0, 2.00, 0.3000, -4" }); + + unsigned int index = 0; + for (auto it = inputMap.begin(); it != inputMap.end(); ++it) + { + mx::InputPtr input= doc->addInput("input" + std::to_string(index), (*it).first); + input->setValueString((*it).second); + index++; + } + + mx::DocumentPtr doc2 = mx::createDocument(); + std::multimap inputMap2; + inputMap2.insert({ "color3", "1,2,3" }); + inputMap2.insert({ "color4", "1,2,0.3,-4" }); + inputMap2.insert( {"float", "0.1" }); + inputMap2.insert( {"vector2", "1,0.0123456" }); + inputMap2.insert( {"vector3", "1,2,3" }); + inputMap2.insert( {"vector4", "1,2,0.3,-4" }); + + index = 0; + for (auto it = inputMap.begin(); it != inputMap.end(); ++it) + { + mx::InputPtr input = doc2->addInput("input" + std::to_string(index), (*it).first); + input->setValueString((*it).second); + index++; + } + + doc->normalizeValueStrings(); + doc2->normalizeValueStrings(); + + // Note: do not check doc2 == doc as that is a pointer comparison + bool equivalent = (*doc2 == *doc); + REQUIRE(equivalent); +} \ No newline at end of file diff --git a/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp b/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp index 3f4403c673..45a673da52 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp @@ -116,5 +116,6 @@ void bindPyDocument(py::module& mod) .def("getColorManagementSystem", &mx::Document::getColorManagementSystem) .def("setColorManagementConfig", &mx::Document::setColorManagementConfig) .def("hasColorManagementConfig", &mx::Document::hasColorManagementConfig) - .def("getColorManagementConfig", &mx::Document::getColorManagementConfig); + .def("getColorManagementConfig", &mx::Document::getColorManagementConfig) + .def("normalizeValueStrings", &mx::Document::normalizeValueStrings); } diff --git a/source/PyMaterialX/PyMaterialXCore/PyUtil.cpp b/source/PyMaterialX/PyMaterialXCore/PyUtil.cpp index 826c5adf84..c190066ffe 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyUtil.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyUtil.cpp @@ -28,4 +28,5 @@ void bindPyUtil(py::module& mod) mod.def("splitNamePath", &mx::splitNamePath); mod.def("createNamePath", &mx::createNamePath); mod.def("parentNamePath", &mx::parentNamePath); + mod.def("normalizeNumericString", &mx::normalizeNumericString); } From 5cc56c2b6a88de747d3241b34ed6bab455d73b51 Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Fri, 23 Aug 2024 09:02:24 -0700 Subject: [PATCH 2/8] Remove extra newline --- source/MaterialXCore/Document.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index 7b15d84e24..10002aedf3 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -428,7 +428,6 @@ void Document::normalizeValueStrings(unsigned int numericPrecision) } } - // // Deprecated methods // From 0f31beb3793cc98285a61e8401820a3076053d7a Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Fri, 23 Aug 2024 09:03:38 -0700 Subject: [PATCH 3/8] Code style updates --- source/MaterialXCore/Util.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/MaterialXCore/Util.cpp b/source/MaterialXCore/Util.cpp index b41316f64a..a6bdd686f0 100644 --- a/source/MaterialXCore/Util.cpp +++ b/source/MaterialXCore/Util.cpp @@ -187,7 +187,8 @@ string normalizeNumericString(const string& str, unsigned int precision) std::stringstream result; std::string token; - while (std::getline(ss, token, ',')) { + while (std::getline(ss, token, ',')) + { // Remove leading and trailing spaces token.erase(0, token.find_first_not_of(' ')); token.erase(token.find_last_not_of(' ') + 1); @@ -201,7 +202,8 @@ string normalizeNumericString(const string& str, unsigned int precision) // Remove unnecessary trailing zeros std::string formattedNumber = result.str(); formattedNumber.erase(formattedNumber.find_last_not_of('0') + 1, std::string::npos); - if (formattedNumber.back() == '.') { + if (formattedNumber.back() == '.') + { formattedNumber.pop_back(); // Remove the trailing dot if there's no decimal part left } @@ -214,7 +216,8 @@ string normalizeNumericString(const string& str, unsigned int precision) std::string output = result.str(); // Remove the last comma - if (!output.empty()) { + if (!output.empty()) + { output.pop_back(); } From 8a237a330fda67a5548183274d18064ba8b67e6d Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Fri, 23 Aug 2024 13:18:30 -0400 Subject: [PATCH 4/8] - Review changes: - Simplify logic. - Remove precision clamping. - Add JS wrapper. --- .../JsMaterialXCore/JsDocument.cpp | 1 + source/JsMaterialX/JsMaterialXCore/JsUtil.cpp | 2 + source/MaterialXCore/Document.cpp | 4 +- source/MaterialXCore/Document.h | 3 +- source/MaterialXCore/Util.cpp | 48 +++++++++---------- source/MaterialXCore/Util.h | 2 +- .../MaterialXTest/MaterialXCore/CoreUtil.cpp | 17 +++---- .../MaterialXTest/MaterialXCore/Document.cpp | 2 +- 8 files changed, 41 insertions(+), 38 deletions(-) diff --git a/source/JsMaterialX/JsMaterialXCore/JsDocument.cpp b/source/JsMaterialX/JsMaterialXCore/JsDocument.cpp index ec4881732d..3d584184e5 100644 --- a/source/JsMaterialX/JsMaterialXCore/JsDocument.cpp +++ b/source/JsMaterialX/JsMaterialXCore/JsDocument.cpp @@ -103,6 +103,7 @@ EMSCRIPTEN_BINDINGS(document) .function("hasColorManagementConfig", &mx::Document::hasColorManagementConfig) .function("getColorManagementConfig", &mx::Document::getColorManagementConfig) .function("invalidateCache", &mx::Document::invalidateCache) + .function("normalizeValueStrings", &mx::Document::normalizeValueStrings) .class_property("CATEGORY", &mx::Document::CATEGORY) .class_property("CMS_ATTRIBUTE", &mx::Document::CMS_ATTRIBUTE) .class_property("CMS_CONFIG_ATTRIBUTE", &mx::Document::CMS_CONFIG_ATTRIBUTE); diff --git a/source/JsMaterialX/JsMaterialXCore/JsUtil.cpp b/source/JsMaterialX/JsMaterialXCore/JsUtil.cpp index 1bc54ad1b8..da6b488337 100644 --- a/source/JsMaterialX/JsMaterialXCore/JsUtil.cpp +++ b/source/JsMaterialX/JsMaterialXCore/JsUtil.cpp @@ -47,4 +47,6 @@ EMSCRIPTEN_BINDINGS(util) ems::function("splitNamePath", &mx::splitNamePath); ems::function("createNamePath", &mx::createNamePath); ems::function("parentNamePath", &mx::parentNamePath); + + ems::function("normalizeNumericString", &mx::normalizeNumericString); } diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index 10002aedf3..780d20abc7 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -402,7 +402,7 @@ void Document::invalidateCache() _cache->valid = false; } -void Document::normalizeValueStrings(unsigned int numericPrecision) +void Document::normalizeValueStrings() { // For now this will only normalize numeric strings StringSet numericType = { "float", "vector2", "vector3", "vector4", "color3", "color4" }; @@ -420,7 +420,7 @@ void Document::normalizeValueStrings(unsigned int numericPrecision) continue; } - string normalizeString = normalizeNumericString(originalString, numericPrecision); + string normalizeString = normalizeNumericString(originalString); if (normalizeString != originalString) { valueElem->setValueString(normalizeString); diff --git a/source/MaterialXCore/Document.h b/source/MaterialXCore/Document.h index afeec7f336..c40b8b4856 100644 --- a/source/MaterialXCore/Document.h +++ b/source/MaterialXCore/Document.h @@ -664,8 +664,7 @@ class MX_CORE_API Document : public GraphElement void invalidateCache(); /// Normalize value strings for all numeric values attributes - /// @param numericPrecision Precision to use for floating point numbers. Default is 6. - void normalizeValueStrings(unsigned int numericPrecision = 6); + void normalizeValueStrings(); /// @} diff --git a/source/MaterialXCore/Util.cpp b/source/MaterialXCore/Util.cpp index a6bdd686f0..c2e982fc03 100644 --- a/source/MaterialXCore/Util.cpp +++ b/source/MaterialXCore/Util.cpp @@ -181,47 +181,47 @@ string parentNamePath(const string& namePath) return EMPTY_STRING; } -string normalizeNumericString(const string& str, unsigned int precision) +std::string normalizeNumericString(const std::string& str) { std::stringstream ss(str); - std::stringstream result; + std::string result; std::string token; - while (std::getline(ss, token, ',')) - { + while (std::getline(ss, token, ',')) { // Remove leading and trailing spaces token.erase(0, token.find_first_not_of(' ')); token.erase(token.find_last_not_of(' ') + 1); - // Convert the string to a double (automatically removes leading zeros) - double number = std::stod(token); + // Remove leading zeros + token.erase(0, token.find_first_not_of('0')); + + // Preserve 0 values + if (token.empty() || token[0] == '.') { + token = "0" + token; + } - // Format the number with the specified precision - result << std::fixed << std::setprecision(precision) << number; + // If the token contains a decimal point, remove trailing zeros + size_t decimalPos = token.find('.'); + if (decimalPos != std::string::npos) { + token.erase(token.find_last_not_of('0') + 1); - // Remove unnecessary trailing zeros - std::string formattedNumber = result.str(); - formattedNumber.erase(formattedNumber.find_last_not_of('0') + 1, std::string::npos); - if (formattedNumber.back() == '.') - { - formattedNumber.pop_back(); // Remove the trailing dot if there's no decimal part left + // If the token ends with a decimal point after removing trailing zeros, remove it + if (token.back() == '.') { + token.pop_back(); + } } - // Append the formatted number to the result - result.str(EMPTY_STRING); // Clear the stringstream for the next number - result.clear(); - result << formattedNumber << ","; + // Append the formatted token to the result with a comma + result += token + ","; } - std::string output = result.str(); - // Remove the last comma - if (!output.empty()) - { - output.pop_back(); + if (!result.empty()) { + result.pop_back(); } - return output; + return result; } + MATERIALX_NAMESPACE_END diff --git a/source/MaterialXCore/Util.h b/source/MaterialXCore/Util.h index ad4ff37479..da0a062cfd 100644 --- a/source/MaterialXCore/Util.h +++ b/source/MaterialXCore/Util.h @@ -71,7 +71,7 @@ MX_CORE_API string parentNamePath(const string& namePath); /// Normalize a string containing a numeric value. This can /// either be a single number or an array of comma seperated numbers. -MX_CORE_API string normalizeNumericString(const string& str, unsigned int precision = 6); +MX_CORE_API string normalizeNumericString(const string& str); MATERIALX_NAMESPACE_END diff --git a/source/MaterialXTest/MaterialXCore/CoreUtil.cpp b/source/MaterialXTest/MaterialXCore/CoreUtil.cpp index d4ed712e43..925f846677 100644 --- a/source/MaterialXTest/MaterialXCore/CoreUtil.cpp +++ b/source/MaterialXTest/MaterialXCore/CoreUtil.cpp @@ -41,14 +41,15 @@ TEST_CASE("String utilities", "[coreutil]") std::string inputScalar1 = " 00.1000 "; std::string resultScalar1 = mx::normalizeNumericString(inputScalar1); REQUIRE(resultScalar1 == "0.1"); - std::string inputScalar2 = "0.1234567890"; - std::string resultScalar2 = mx::normalizeNumericString(inputScalar2, 3); - REQUIRE(resultScalar2 == "0.123"); - std::string resultScalar3 = mx::normalizeNumericString(inputScalar2, 12); - REQUIRE(resultScalar3 == "0.123456789"); - std::string inputScalar3 = "0.12345678901234567890"; - std::string resultScalar4 = mx::normalizeNumericString(inputScalar3, 9); - REQUIRE(resultScalar4 == "0.123456789"); + std::string inputScalar2 = ".000000"; + std::string resultScalar2 = mx::normalizeNumericString(inputScalar2); + REQUIRE(resultScalar2 == "0"); + std::string inputScalar3 = "000."; + std::string resultScalar3 = mx::normalizeNumericString(inputScalar3); + REQUIRE(resultScalar3 == "0"); + std::string inputScalar4 = "000.01"; + std::string resultScalar4 = mx::normalizeNumericString(inputScalar4); + REQUIRE(resultScalar4 == "0.01"); std::string inputVector1 = "1.0, 2.0, 0000.231"; std::string inputVector2 = "0001.2000, 0000.00010"; diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp index 8e18d5e706..f8904fc9b9 100644 --- a/source/MaterialXTest/MaterialXCore/Document.cpp +++ b/source/MaterialXTest/MaterialXCore/Document.cpp @@ -119,7 +119,7 @@ TEST_CASE("Document", "[document]") REQUIRE(doc->validate()); } -TEST_CASE("Document equivalence", "[document2]") +TEST_CASE("Document equivalence", "[document]") { mx::DocumentPtr doc = mx::createDocument(); std::multimap inputMap; From 512e75718278719952dcd736da8cfdf124c7a667 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Fri, 23 Aug 2024 13:22:21 -0400 Subject: [PATCH 5/8] Formatting fixes. --- source/MaterialXCore/Util.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/source/MaterialXCore/Util.cpp b/source/MaterialXCore/Util.cpp index c2e982fc03..2e557b8df0 100644 --- a/source/MaterialXCore/Util.cpp +++ b/source/MaterialXCore/Util.cpp @@ -187,7 +187,8 @@ std::string normalizeNumericString(const std::string& str) std::string result; std::string token; - while (std::getline(ss, token, ',')) { + while (std::getline(ss, token, ',')) + { // Remove leading and trailing spaces token.erase(0, token.find_first_not_of(' ')); token.erase(token.find_last_not_of(' ') + 1); @@ -196,17 +197,20 @@ std::string normalizeNumericString(const std::string& str) token.erase(0, token.find_first_not_of('0')); // Preserve 0 values - if (token.empty() || token[0] == '.') { + if (token.empty() || token[0] == '.') + { token = "0" + token; } // If the token contains a decimal point, remove trailing zeros size_t decimalPos = token.find('.'); - if (decimalPos != std::string::npos) { + if (decimalPos != std::string::npos) + { token.erase(token.find_last_not_of('0') + 1); // If the token ends with a decimal point after removing trailing zeros, remove it - if (token.back() == '.') { + if (token.back() == '.') + { token.pop_back(); } } @@ -216,7 +220,8 @@ std::string normalizeNumericString(const std::string& str) } // Remove the last comma - if (!result.empty()) { + if (!result.empty()) + { result.pop_back(); } From b706c10f9e659ecd7eb3a28307cce467ea9cf076 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Fri, 23 Aug 2024 14:57:24 -0400 Subject: [PATCH 6/8] Review updates. - Add integer, matrix support - Move type into more generic method. - Update tests. --- source/JsMaterialX/JsMaterialXCore/JsUtil.cpp | 2 +- source/MaterialXCore/Document.cpp | 6 +- source/MaterialXCore/Util.cpp | 72 ++++++++++++------- source/MaterialXCore/Util.h | 6 +- .../MaterialXTest/MaterialXCore/CoreUtil.cpp | 47 +++++++++--- .../MaterialXTest/MaterialXCore/Document.cpp | 33 ++++++--- source/PyMaterialX/PyMaterialXCore/PyUtil.cpp | 2 +- 7 files changed, 114 insertions(+), 54 deletions(-) diff --git a/source/JsMaterialX/JsMaterialXCore/JsUtil.cpp b/source/JsMaterialX/JsMaterialXCore/JsUtil.cpp index da6b488337..dbfd650ed4 100644 --- a/source/JsMaterialX/JsMaterialXCore/JsUtil.cpp +++ b/source/JsMaterialX/JsMaterialXCore/JsUtil.cpp @@ -48,5 +48,5 @@ EMSCRIPTEN_BINDINGS(util) ems::function("createNamePath", &mx::createNamePath); ems::function("parentNamePath", &mx::parentNamePath); - ems::function("normalizeNumericString", &mx::normalizeNumericString); + ems::function("normalizeValueString", &mx::normalizeValueString); } diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index 780d20abc7..b035162360 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -404,12 +404,10 @@ void Document::invalidateCache() void Document::normalizeValueStrings() { - // For now this will only normalize numeric strings - StringSet numericType = { "float", "vector2", "vector3", "vector4", "color3", "color4" }; for (ElementPtr elem : traverseTree()) { ValueElementPtr valueElem = elem->asA(); - if (!valueElem || numericType.end() == numericType.find(valueElem->getType())) + if (!valueElem) { continue; } @@ -420,7 +418,7 @@ void Document::normalizeValueStrings() continue; } - string normalizeString = normalizeNumericString(originalString); + string normalizeString = normalizeValueString(originalString, valueElem->getType()); if (normalizeString != originalString) { valueElem->setValueString(normalizeString); diff --git a/source/MaterialXCore/Util.cpp b/source/MaterialXCore/Util.cpp index 2e557b8df0..f839df430d 100644 --- a/source/MaterialXCore/Util.cpp +++ b/source/MaterialXCore/Util.cpp @@ -181,48 +181,68 @@ string parentNamePath(const string& namePath) return EMPTY_STRING; } -std::string normalizeNumericString(const std::string& str) +std::string normalizeValueString(const std::string& str, const std::string valueType) { + // Currently supported value types. + StringSet supportedTypes = { "integer", "float", "vector2", "vector3", "vector4", "color3", "color4", "matrix33", "matrix44"}; + if (supportedTypes.end() == supportedTypes.find(valueType)) + { + return str; + } + std::stringstream ss(str); std::string result; std::string token; - while (std::getline(ss, token, ',')) + bool isInteger = (valueType == "integer"); + if (isInteger) { // Remove leading and trailing spaces + token = str; token.erase(0, token.find_first_not_of(' ')); token.erase(token.find_last_not_of(' ') + 1); - - // Remove leading zeros - token.erase(0, token.find_first_not_of('0')); - - // Preserve 0 values - if (token.empty() || token[0] == '.') + result = token; + } + else + { + while (std::getline(ss, token, ',')) { - token = "0" + token; - } + // Remove leading and trailing spaces + token.erase(0, token.find_first_not_of(' ')); + token.erase(token.find_last_not_of(' ') + 1); - // If the token contains a decimal point, remove trailing zeros - size_t decimalPos = token.find('.'); - if (decimalPos != std::string::npos) - { - token.erase(token.find_last_not_of('0') + 1); + // Remove leading zeros + token.erase(0, token.find_first_not_of('0')); - // If the token ends with a decimal point after removing trailing zeros, remove it - if (token.back() == '.') + // Preserve 0 values + if (token.empty() || token[0] == '.') { - token.pop_back(); + token = "0" + token; } - } - // Append the formatted token to the result with a comma - result += token + ","; - } + // If the token contains a decimal point, remove trailing zeros + size_t decimalPos = token.find('.'); + if (decimalPos != std::string::npos) + { + token.erase(token.find_last_not_of('0') + 1); - // Remove the last comma - if (!result.empty()) - { - result.pop_back(); + // If the token ends with a decimal point after removing trailing zeros, remove it + if (token.back() == '.') + { + token.pop_back(); + } + } + + // Append the formatted token to the result with a comma + result += token + ", "; + } + + // Remove the last comma + if (!result.empty()) + { + result.pop_back(); + result.pop_back(); + } } return result; diff --git a/source/MaterialXCore/Util.h b/source/MaterialXCore/Util.h index da0a062cfd..d792c2bbab 100644 --- a/source/MaterialXCore/Util.h +++ b/source/MaterialXCore/Util.h @@ -69,9 +69,9 @@ MX_CORE_API string createNamePath(const StringVec& nameVec); /// Given a name path, return the parent name path MX_CORE_API string parentNamePath(const string& namePath); -/// Normalize a string containing a numeric value. This can -/// either be a single number or an array of comma seperated numbers. -MX_CORE_API string normalizeNumericString(const string& str); +/// Normalize a string containing a value. +/// Currently single floating point numbers or an array of comma seperated numbers is supported. +MX_CORE_API string normalizeValueString(const string& str, const std::string valueType); MATERIALX_NAMESPACE_END diff --git a/source/MaterialXTest/MaterialXCore/CoreUtil.cpp b/source/MaterialXTest/MaterialXCore/CoreUtil.cpp index 925f846677..b51d92bfd2 100644 --- a/source/MaterialXTest/MaterialXCore/CoreUtil.cpp +++ b/source/MaterialXTest/MaterialXCore/CoreUtil.cpp @@ -38,28 +38,53 @@ TEST_CASE("String utilities", "[coreutil]") REQUIRE(mx::stringEndsWith("testName", "Name")); REQUIRE(!mx::stringEndsWith("testName", "test")); + std::string inputInteger = " 12 "; + std::string resultInteger = mx::normalizeValueString(inputInteger, "integer"); + REQUIRE(resultInteger == "12"); + std::string inputScalar1 = " 00.1000 "; - std::string resultScalar1 = mx::normalizeNumericString(inputScalar1); + std::string resultScalar1 = mx::normalizeValueString(inputScalar1, "float"); REQUIRE(resultScalar1 == "0.1"); std::string inputScalar2 = ".000000"; - std::string resultScalar2 = mx::normalizeNumericString(inputScalar2); + std::string resultScalar2 = mx::normalizeValueString(inputScalar2, "float"); REQUIRE(resultScalar2 == "0"); std::string inputScalar3 = "000."; - std::string resultScalar3 = mx::normalizeNumericString(inputScalar3); + std::string resultScalar3 = mx::normalizeValueString(inputScalar3, "float"); REQUIRE(resultScalar3 == "0"); std::string inputScalar4 = "000.01"; - std::string resultScalar4 = mx::normalizeNumericString(inputScalar4); + std::string resultScalar4 = mx::normalizeValueString(inputScalar4, "float"); REQUIRE(resultScalar4 == "0.01"); std::string inputVector1 = "1.0, 2.0, 0000.231"; + std::string resultVector1 = mx::normalizeValueString(inputVector1, "vector3"); + REQUIRE(resultVector1 == "1, 2, 0.231"); + resultVector1 = mx::normalizeValueString(inputVector1, "color3"); + REQUIRE(resultVector1 == "1, 2, 0.231"); + std::string inputVector2 = "0001.2000, 0000.00010"; - std::string resultVector1 = mx::normalizeNumericString(inputVector1); - REQUIRE(resultVector1 == "1,2,0.231"); - std::string resultVector2 = mx::normalizeNumericString(inputVector2); - REQUIRE(resultVector2 == "1.2,0.0001"); - std::string inputVector3 = "01.0, 2.0, 0000.2310"; - std::string resultVector3 = mx::normalizeNumericString(inputVector3); - REQUIRE(resultVector3 == resultVector1); + std::string resultVector2 = mx::normalizeValueString(inputVector2, "vector2"); + REQUIRE(resultVector2 == "1.2, 0.0001"); + + std::string inputVector3 = "01.0, 2.0, 0000.2310, 0.1"; + std::string resultVector3 = mx::normalizeValueString(inputVector3, "vector4"); + REQUIRE(resultVector3 == "1, 2, 0.231, 0.1"); + resultVector3 = mx::normalizeValueString(inputVector3, "color4"); + REQUIRE(resultVector3 == "1, 2, 0.231, 0.1"); + + std::string inputMatrix3 = "01.0, 2.0, 0000.2310, " + " 01.0, 2.0, 0000.2310, " + "01.0, 2.0, 0000.2310, " + " 01.0, 2.0, 0000.2310 "; + std::string resultMatrix3 = mx::normalizeValueString(inputMatrix3, "matrix33"); + std::string compareMatrix3 = "1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231"; + REQUIRE(resultMatrix3 == compareMatrix3); + std::string inputMatrix = "01.0, 2.0, 0000.2310, 0.100, " + "01.0, 2.0, 0000.2310, 0.100, " + "01.0, 2.0, 0000.2310, 0.100, " + "01.0, 2.0, 0000.2310, 0.100"; + std::string resultMatrix = mx::normalizeValueString(inputMatrix, "matrix44"); + std::string compareMatrix = "1, 2, 0.231, 0.1, 1, 2, 0.231, 0.1, 1, 2, 0.231, 0.1, 1, 2, 0.231, 0.1"; + REQUIRE(resultMatrix == compareMatrix); } TEST_CASE("Print utilities", "[coreutil]") diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp index f8904fc9b9..2747ea2437 100644 --- a/source/MaterialXTest/MaterialXCore/Document.cpp +++ b/source/MaterialXTest/MaterialXCore/Document.cpp @@ -127,9 +127,20 @@ TEST_CASE("Document equivalence", "[document]") inputMap.insert({ "color3", " 1.0, +2.0, 3.0 " }); inputMap.insert({ "color4", "1.0, 2.00, 0.3000, -4" }); inputMap.insert({ "float", " 00.1000 " }); + inputMap.insert({ "integer", " 12 " }); + inputMap.insert({ "matrix33", + "01.0, 2.0, 0000.2310, " + " 01.0, 2.0, 0000.2310, " + "01.0, 2.0, 0000.2310, " + " 01.0, 2.0, 0000.2310 " }); + inputMap.insert({ "matrix44", + "01.0, 2.0, 0000.2310, 0.100, " + "01.0, 2.0, 0000.2310, 0.100, " + "01.0, 2.0, 0000.2310, 0.100, " + "01.0, 2.0, 0000.2310, 0.100" }); inputMap.insert({ "vector2", "1.0, 0.012345678" }); - inputMap.insert( {"vector3", " 1.0, +2.0, 3.0 " }); - inputMap.insert( {"vector4", "1.0, 2.00, 0.3000, -4" }); + inputMap.insert({ "vector3", " 1.0, +2.0, 3.0 " }); + inputMap.insert({ "vector4", "1.0, 2.00, 0.3000, -4" }); unsigned int index = 0; for (auto it = inputMap.begin(); it != inputMap.end(); ++it) @@ -141,12 +152,15 @@ TEST_CASE("Document equivalence", "[document]") mx::DocumentPtr doc2 = mx::createDocument(); std::multimap inputMap2; - inputMap2.insert({ "color3", "1,2,3" }); - inputMap2.insert({ "color4", "1,2,0.3,-4" }); - inputMap2.insert( {"float", "0.1" }); - inputMap2.insert( {"vector2", "1,0.0123456" }); - inputMap2.insert( {"vector3", "1,2,3" }); - inputMap2.insert( {"vector4", "1,2,0.3,-4" }); + inputMap2.insert({ "color3", "1, 2, 3" }); + inputMap2.insert({ "color4", "1, 2, 0.3, -4" }); + inputMap2.insert({ "float", "0.1" }); + inputMap2.insert({ "integer", "12" }); + inputMap2.insert({ "matrix33", "1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231" }); + inputMap2.insert({ "matrix44", "1, 2, 0.231, 0.1, 1, 2, 0.231, 0.1, 1, 2, 0.231, 0.1, 1, 2, 0.231, 0.1" }); + inputMap2.insert({ "vector2", "1, 0.0123456" }); + inputMap2.insert({ "vector3", "1, 2, 3" }); + inputMap2.insert({ "vector4", "1, 2, 0.3, -4" }); index = 0; for (auto it = inputMap.begin(); it != inputMap.end(); ++it) @@ -159,6 +173,9 @@ TEST_CASE("Document equivalence", "[document]") doc->normalizeValueStrings(); doc2->normalizeValueStrings(); + mx::writeToXmlFile(doc, "doc.mtlx"); + mx::writeToXmlFile(doc2, "doc2.mtlx"); + // Note: do not check doc2 == doc as that is a pointer comparison bool equivalent = (*doc2 == *doc); REQUIRE(equivalent); diff --git a/source/PyMaterialX/PyMaterialXCore/PyUtil.cpp b/source/PyMaterialX/PyMaterialXCore/PyUtil.cpp index c190066ffe..d630296232 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyUtil.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyUtil.cpp @@ -28,5 +28,5 @@ void bindPyUtil(py::module& mod) mod.def("splitNamePath", &mx::splitNamePath); mod.def("createNamePath", &mx::createNamePath); mod.def("parentNamePath", &mx::parentNamePath); - mod.def("normalizeNumericString", &mx::normalizeNumericString); + mod.def("normalizeValueString", &mx::normalizeValueString); } From 57752b95455157b8cdac618e735da182b8afdce6 Mon Sep 17 00:00:00 2001 From: Bernard Kwok Date: Fri, 23 Aug 2024 15:28:27 -0400 Subject: [PATCH 7/8] Cleanup tests. --- source/MaterialXCore/Util.cpp | 9 +++--- .../MaterialXTest/MaterialXCore/CoreUtil.cpp | 15 ++++++---- .../MaterialXTest/MaterialXCore/Document.cpp | 28 +++++++++++++++---- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/source/MaterialXCore/Util.cpp b/source/MaterialXCore/Util.cpp index f839df430d..60efee05e1 100644 --- a/source/MaterialXCore/Util.cpp +++ b/source/MaterialXCore/Util.cpp @@ -190,7 +190,6 @@ std::string normalizeValueString(const std::string& str, const std::string value return str; } - std::stringstream ss(str); std::string result; std::string token; @@ -198,13 +197,13 @@ std::string normalizeValueString(const std::string& str, const std::string value if (isInteger) { // Remove leading and trailing spaces - token = str; - token.erase(0, token.find_first_not_of(' ')); - token.erase(token.find_last_not_of(' ') + 1); - result = token; + result = str; + result.erase(0, result.find_first_not_of(' ')); + result.erase(result.find_last_not_of(' ') + 1); } else { + std::stringstream ss(str); while (std::getline(ss, token, ',')) { // Remove leading and trailing spaces diff --git a/source/MaterialXTest/MaterialXCore/CoreUtil.cpp b/source/MaterialXTest/MaterialXCore/CoreUtil.cpp index b51d92bfd2..9f11f1de66 100644 --- a/source/MaterialXTest/MaterialXCore/CoreUtil.cpp +++ b/source/MaterialXTest/MaterialXCore/CoreUtil.cpp @@ -37,7 +37,10 @@ TEST_CASE("String utilities", "[coreutil]") REQUIRE(!mx::stringStartsWith("testName", "Name")); REQUIRE(mx::stringEndsWith("testName", "Name")); REQUIRE(!mx::stringEndsWith("testName", "test")); +} +TEST_CASE("Value normalization", "[coreutil]") +{ std::string inputInteger = " 12 "; std::string resultInteger = mx::normalizeValueString(inputInteger, "integer"); REQUIRE(resultInteger == "12"); @@ -73,14 +76,14 @@ TEST_CASE("String utilities", "[coreutil]") std::string inputMatrix3 = "01.0, 2.0, 0000.2310, " " 01.0, 2.0, 0000.2310, " - "01.0, 2.0, 0000.2310, " - " 01.0, 2.0, 0000.2310 "; + "01.0, 2.0, 0000.2310 "; std::string resultMatrix3 = mx::normalizeValueString(inputMatrix3, "matrix33"); - std::string compareMatrix3 = "1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231"; + std::string compareMatrix3 = "1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231"; REQUIRE(resultMatrix3 == compareMatrix3); - std::string inputMatrix = "01.0, 2.0, 0000.2310, 0.100, " - "01.0, 2.0, 0000.2310, 0.100, " - "01.0, 2.0, 0000.2310, 0.100, " + + std::string inputMatrix = "01.0, 2.0, 0000.2310, 0.100," + "01.0, 2.0, 0000.2310, 0.100," + "01.0, 2.0, 0000.2310, 0.100," "01.0, 2.0, 0000.2310, 0.100"; std::string resultMatrix = mx::normalizeValueString(inputMatrix, "matrix44"); std::string compareMatrix = "1, 2, 0.231, 0.1, 1, 2, 0.231, 0.1, 1, 2, 0.231, 0.1, 1, 2, 0.231, 0.1"; diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp index 2747ea2437..afb74ad971 100644 --- a/source/MaterialXTest/MaterialXCore/Document.cpp +++ b/source/MaterialXTest/MaterialXCore/Document.cpp @@ -119,6 +119,8 @@ TEST_CASE("Document", "[document]") REQUIRE(doc->validate()); } +#include + TEST_CASE("Document equivalence", "[document]") { mx::DocumentPtr doc = mx::createDocument(); @@ -131,8 +133,7 @@ TEST_CASE("Document equivalence", "[document]") inputMap.insert({ "matrix33", "01.0, 2.0, 0000.2310, " " 01.0, 2.0, 0000.2310, " - "01.0, 2.0, 0000.2310, " - " 01.0, 2.0, 0000.2310 " }); + "01.0, 2.0, 0000.2310 " }); inputMap.insert({ "matrix44", "01.0, 2.0, 0000.2310, 0.100, " "01.0, 2.0, 0000.2310, 0.100, " @@ -141,6 +142,9 @@ TEST_CASE("Document equivalence", "[document]") inputMap.insert({ "vector2", "1.0, 0.012345678" }); inputMap.insert({ "vector3", " 1.0, +2.0, 3.0 " }); inputMap.insert({ "vector4", "1.0, 2.00, 0.3000, -4" }); + inputMap.insert({ "string", "mystring" }); + inputMap.insert({ "boolean", "false" }); + inputMap.insert({ "filename", "filename1" }); unsigned int index = 0; for (auto it = inputMap.begin(); it != inputMap.end(); ++it) @@ -156,11 +160,14 @@ TEST_CASE("Document equivalence", "[document]") inputMap2.insert({ "color4", "1, 2, 0.3, -4" }); inputMap2.insert({ "float", "0.1" }); inputMap2.insert({ "integer", "12" }); - inputMap2.insert({ "matrix33", "1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231" }); + inputMap2.insert({ "matrix33", "1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231" }); inputMap2.insert({ "matrix44", "1, 2, 0.231, 0.1, 1, 2, 0.231, 0.1, 1, 2, 0.231, 0.1, 1, 2, 0.231, 0.1" }); inputMap2.insert({ "vector2", "1, 0.0123456" }); inputMap2.insert({ "vector3", "1, 2, 3" }); inputMap2.insert({ "vector4", "1, 2, 0.3, -4" }); + inputMap2.insert({ "string", "mystring" }); + inputMap2.insert({ "boolean", "false" }); + inputMap2.insert({ "filename", "filename1" }); index = 0; for (auto it = inputMap.begin(); it != inputMap.end(); ++it) @@ -170,11 +177,20 @@ TEST_CASE("Document equivalence", "[document]") index++; } + std::string status; doc->normalizeValueStrings(); - doc2->normalizeValueStrings(); + bool valid = doc->validate(&status); + { + std::cout << "input doc status: " << status << std::endl; + } + REQUIRE(valid); - mx::writeToXmlFile(doc, "doc.mtlx"); - mx::writeToXmlFile(doc2, "doc2.mtlx"); + doc2->normalizeValueStrings(); + valid = doc2->validate(&status); + { + std::cout << "input doc 2 status: " << status << std::endl; + } + REQUIRE(valid); // Note: do not check doc2 == doc as that is a pointer comparison bool equivalent = (*doc2 == *doc); From 43ea222e81887d2593f12a93213f4b4e70c83f51 Mon Sep 17 00:00:00 2001 From: kwokcb Date: Sun, 25 Aug 2024 05:09:52 -0400 Subject: [PATCH 8/8] Review Updates - Do not remove trailing 0s for scientific notation. This just checks for the 'e' character after stripping leading and trailing spaces and leading zeros. - Skip empty tokens, though this is invalid for MaterialX. --- source/MaterialXCore/Util.cpp | 56 ++++++++++++------- .../MaterialXTest/MaterialXCore/CoreUtil.cpp | 13 ++++- .../MaterialXTest/MaterialXCore/Document.cpp | 7 +++ 3 files changed, 54 insertions(+), 22 deletions(-) diff --git a/source/MaterialXCore/Util.cpp b/source/MaterialXCore/Util.cpp index 60efee05e1..ce9de1132e 100644 --- a/source/MaterialXCore/Util.cpp +++ b/source/MaterialXCore/Util.cpp @@ -181,6 +181,7 @@ string parentNamePath(const string& namePath) return EMPTY_STRING; } + std::string normalizeValueString(const std::string& str, const std::string valueType) { // Currently supported value types. @@ -190,6 +191,8 @@ std::string normalizeValueString(const std::string& str, const std::string value return str; } + const string TOKEN_SEPARATOR = ", "; + std::string result; std::string token; @@ -210,37 +213,52 @@ std::string normalizeValueString(const std::string& str, const std::string value token.erase(0, token.find_first_not_of(' ')); token.erase(token.find_last_not_of(' ') + 1); - // Remove leading zeros - token.erase(0, token.find_first_not_of('0')); - - // Preserve 0 values - if (token.empty() || token[0] == '.') + // Skip if the token is empty. Note that this is + // invalid in MaterialX but can still be stored this way. + if (!token.empty()) { - token = "0" + token; - } + // Remove leading zeros + token.erase(0, token.find_first_not_of('0')); - // If the token contains a decimal point, remove trailing zeros - size_t decimalPos = token.find('.'); - if (decimalPos != std::string::npos) - { - token.erase(token.find_last_not_of('0') + 1); + // Preserve 0 values + if (token.empty() || token[0] == '.') + { + token = "0" + token; + } - // If the token ends with a decimal point after removing trailing zeros, remove it - if (token.back() == '.') + // Check if string token has a 'e' character + // implying it is a floating point number in scientific notation. + // If it does not have an 'e' character, remove trailing zeros. + // + size_t ePos = token.find('e'); + if (ePos == std::string::npos) { - token.pop_back(); + // If the token contains a decimal point, remove trailing zeros + size_t decimalPos = token.find('.'); + if (decimalPos != std::string::npos) + { + token.erase(token.find_last_not_of('0') + 1); + + // If the token ends with a decimal point after removing trailing zeros, remove it + if (token.back() == '.') + { + token.pop_back(); + } + } } } // Append the formatted token to the result with a comma - result += token + ", "; + result += token + TOKEN_SEPARATOR; } - // Remove the last comma + // Remove the last separator if (!result.empty()) { - result.pop_back(); - result.pop_back(); + for (size_t i = 0; i < TOKEN_SEPARATOR.size(); i++) + { + result.pop_back(); + } } } diff --git a/source/MaterialXTest/MaterialXCore/CoreUtil.cpp b/source/MaterialXTest/MaterialXCore/CoreUtil.cpp index 9f11f1de66..809ccf9996 100644 --- a/source/MaterialXTest/MaterialXCore/CoreUtil.cpp +++ b/source/MaterialXTest/MaterialXCore/CoreUtil.cpp @@ -45,6 +45,9 @@ TEST_CASE("Value normalization", "[coreutil]") std::string resultInteger = mx::normalizeValueString(inputInteger, "integer"); REQUIRE(resultInteger == "12"); + std::string inputScalar = " 1.2e-10 "; + std::string resultScalar = mx::normalizeValueString(inputScalar, "float"); + REQUIRE(resultScalar == "1.2e-10"); std::string inputScalar1 = " 00.1000 "; std::string resultScalar1 = mx::normalizeValueString(inputScalar1, "float"); REQUIRE(resultScalar1 == "0.1"); @@ -68,11 +71,15 @@ TEST_CASE("Value normalization", "[coreutil]") std::string resultVector2 = mx::normalizeValueString(inputVector2, "vector2"); REQUIRE(resultVector2 == "1.2, 0.0001"); - std::string inputVector3 = "01.0, 2.0, 0000.2310, 0.1"; + std::string inputVector3 = "01.0, 1.2e-10 , 0000.2310, 0.1"; std::string resultVector3 = mx::normalizeValueString(inputVector3, "vector4"); - REQUIRE(resultVector3 == "1, 2, 0.231, 0.1"); + REQUIRE(resultVector3 == "1, 1.2e-10, 0.231, 0.1"); resultVector3 = mx::normalizeValueString(inputVector3, "color4"); - REQUIRE(resultVector3 == "1, 2, 0.231, 0.1"); + REQUIRE(resultVector3 == "1, 1.2e-10, 0.231, 0.1"); + + std::string inputVector4 = "01.0, , 0000.2310, 0.1"; + std::string resultVector4 = mx::normalizeValueString(inputVector4, "vector4"); + REQUIRE(resultVector4 == "1, , 0.231, 0.1"); std::string inputMatrix3 = "01.0, 2.0, 0000.2310, " " 01.0, 2.0, 0000.2310, " diff --git a/source/MaterialXTest/MaterialXCore/Document.cpp b/source/MaterialXTest/MaterialXCore/Document.cpp index afb74ad971..5719bc7cab 100644 --- a/source/MaterialXTest/MaterialXCore/Document.cpp +++ b/source/MaterialXTest/MaterialXCore/Document.cpp @@ -128,6 +128,7 @@ TEST_CASE("Document equivalence", "[document]") inputMap.insert({ "color3", " 1.0, +2.0, 3.0 " }); inputMap.insert({ "color4", "1.0, 2.00, 0.3000, -4" }); + inputMap.insert({ "float", " 1.2e-10 " }); inputMap.insert({ "float", " 00.1000 " }); inputMap.insert({ "integer", " 12 " }); inputMap.insert({ "matrix33", @@ -158,6 +159,7 @@ TEST_CASE("Document equivalence", "[document]") std::multimap inputMap2; inputMap2.insert({ "color3", "1, 2, 3" }); inputMap2.insert({ "color4", "1, 2, 0.3, -4" }); + inputMap2.insert({ "float", "1.2e-10" }); inputMap2.insert({ "float", "0.1" }); inputMap2.insert({ "integer", "12" }); inputMap2.insert({ "matrix33", "1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231, 1, 2, 0.231" }); @@ -194,5 +196,10 @@ TEST_CASE("Document equivalence", "[document]") // Note: do not check doc2 == doc as that is a pointer comparison bool equivalent = (*doc2 == *doc); + if (!equivalent) + { + std::cout << "doc 1: " << mx::prettyPrint(doc) << std::endl; + std::cout << "doc 2: " << mx::prettyPrint(doc2) << std::endl; + } REQUIRE(equivalent); } \ No newline at end of file