From f549285fde282e082d1f2a054c99b016fdd55b7b Mon Sep 17 00:00:00 2001 From: Martchus Date: Sun, 9 May 2021 18:36:51 +0200 Subject: [PATCH] Fix splitString()/splitStringSimple() for case of empty trailing part --- CMakeLists.txt | 2 +- conversion/stringconversion.h | 20 ++++++++++++++++++-- tests/conversiontests.cpp | 5 +++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da33ec8..ce61ee2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,7 @@ set(META_APP_DESCRIPTION "Useful C++ classes and routines such as argument parse set(META_FEATURES_FOR_COMPILER_DETECTION_HEADER cxx_thread_local) set(META_VERSION_MAJOR 5) set(META_VERSION_MINOR 10) -set(META_VERSION_PATCH 2) +set(META_VERSION_PATCH 3) # find required 3rd party libraries include(3rdParty) diff --git a/conversion/stringconversion.h b/conversion/stringconversion.h index 568e409..7de8585 100644 --- a/conversion/stringconversion.h +++ b/conversion/stringconversion.h @@ -161,7 +161,8 @@ Container splitString(Detail::StringParamForContainer string, Detail: Container res; typename Container::value_type *last = nullptr; bool merge = false; - for (typename Container::value_type::size_type i = 0, end = string.size(), delimPos; i < end; i = delimPos + delimiter.size()) { + typename Container::value_type::size_type i = 0, end = string.size(); + for (typename Container::value_type::size_type delimPos; i < end; i = delimPos + delimiter.size()) { delimPos = string.find(delimiter, i); if (!merge && maxParts >= 0 && res.size() == static_cast(maxParts)) { if (delimPos == i && emptyPartsRole == EmptyPartsTreat::Merge) { @@ -189,6 +190,9 @@ Container splitString(Detail::StringParamForContainer string, Detail: } } } + if (i == end && emptyPartsRole == EmptyPartsTreat::Keep) { + res.emplace_back(); + } return res; } @@ -207,7 +211,8 @@ Container splitStringSimple( { --maxParts; Container res; - for (typename Container::value_type::size_type i = 0, end = string.size(), delimPos; i < end; i = delimPos + delimiter.size()) { + typename Container::value_type::size_type i = 0, end = string.size(); + for (typename Container::value_type::size_type delimPos; i < end; i = delimPos + delimiter.size()) { delimPos = string.find(delimiter, i); if (maxParts >= 0 && res.size() == static_cast(maxParts)) { delimPos = Container::value_type::npos; @@ -223,6 +228,17 @@ Container splitStringSimple( } else { res.emplace(string.data() + i, delimPos - i); } +#endif + } + if (i == end) { +#if __cplusplus >= 201709 + if constexpr (requires { res.emplace_back(); }) { +#endif + res.emplace_back(); +#if __cplusplus >= 201709 + } else { + res.emplace(); + } #endif } return res; diff --git a/tests/conversiontests.cpp b/tests/conversiontests.cpp index 2c82cba..b4d7701 100644 --- a/tests/conversiontests.cpp +++ b/tests/conversiontests.cpp @@ -295,6 +295,11 @@ void ConversionTests::testStringConversions() CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual); splitTestActual = splitStringSimple>("1,2,3"s, ","s, 2); CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual); + splitTestExpected = { "12", "34", "56", "" }; + splitTestActual = splitString>("12,34,56,"s, ","s); + CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual); + splitTestActual = splitStringSimple>("12,34,56,"s, ","s); + CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual); splitTestExpected = { "1", "2,3", "4,,5" }; splitTestActual = splitString>("1,2,,3,4,,5"s, ","s, EmptyPartsTreat::Merge, 3); CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);