diff --git a/CMakeLists.txt b/CMakeLists.txt index f269d28..87ca1e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ endif() target_sources( ${PROJECT_NAME} PRIVATE 3party/mongoose/mongoose.c + src/ulib/utils/utils.cpp src/ulib/base/location.h src/ulib/base/location.cpp src/ulib/status.h diff --git a/src/ulib/utils/utils.cpp b/src/ulib/utils/utils.cpp new file mode 100644 index 0000000..3805fd7 --- /dev/null +++ b/src/ulib/utils/utils.cpp @@ -0,0 +1,29 @@ +#include "utils.h" +#include + +namespace ulib { +std::string +StrJoin(std::vector &vec, + nonstd::string_view delimiter, + bool ignore_empty_str) +{ + if (vec.empty()) { return ""; } + + auto iter = vec.cbegin(); + if (ignore_empty_str) { + // find first non-empty string + while (iter != vec.cend() && iter->empty()) { ++iter; } + } + + if (iter == vec.cend()) { return ""; } + std::stringstream ss; + ss << *iter; + for (++iter; iter != vec.cend(); ++iter) { + if (ignore_empty_str && iter->empty()) { continue; } + ss << delimiter << *iter; + } + + return std::move(ss.str()); +} + +}// namespace ulib diff --git a/src/ulib/utils/utils.h b/src/ulib/utils/utils.h index 0d5ff4e..cdcf16c 100644 --- a/src/ulib/utils/utils.h +++ b/src/ulib/utils/utils.h @@ -2,8 +2,18 @@ #define ULIB_SRC_ULIB_UTILS_UTILS_H_ #include +#include +#include +#include namespace ulib { +template +const T & +Clamp(const T &value, const T &low, const T &high, Comp comp) +{ + return comp(value, low) ? low : (comp(high, value) ? high : value); +} + template const T & Clamp(const T &value, const T &low, const T &high) @@ -11,12 +21,9 @@ Clamp(const T &value, const T &low, const T &high) return Clamp(value, low, high, std::less{}); } -template -const T & -Clamp(const T &value, const T &low, const T &high, Comp comp) -{ - return comp(value, low) ? low : (comp(high, value) ? high : value); -} +std::string StrJoin(std::vector &vec, + nonstd::string_view delimiter = ",", + bool ignore_empty_str = true); }// namespace ulib #endif// ULIB_SRC_ULIB_UTILS_UTILS_H_ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6bb2763..59260d1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -17,6 +17,7 @@ add_executable( 3party/optional/optional_unittest.cpp 3party/sqlpp11/sqlpp11_unittest.cpp ulib/utils/defer_unittest.cpp + ulib/utils/utils_unittest.cpp ulib/status_or_unittest.cpp) target_link_libraries(ulib_test PRIVATE ulib gtest gtest_main) diff --git a/tests/ulib/utils/utils_unittest.cpp b/tests/ulib/utils/utils_unittest.cpp new file mode 100644 index 0000000..a54d7a5 --- /dev/null +++ b/tests/ulib/utils/utils_unittest.cpp @@ -0,0 +1,34 @@ +#include +#include + +TEST(Utils, Clamp) +{ + EXPECT_EQ(ulib::Clamp(1, 2, 3), 2); + EXPECT_EQ(ulib::Clamp(2, 2, 3), 2); + EXPECT_EQ(ulib::Clamp(3, 2, 3), 3); + EXPECT_EQ(ulib::Clamp(4, 2, 3), 3); +} + +TEST(Utils, StrJoin) +{ + std::vector vec{"a", "b", "c"}; + EXPECT_EQ(ulib::StrJoin(vec, ","), "a,b,c"); + EXPECT_EQ(ulib::StrJoin(vec, ",", false), "a,b,c"); + EXPECT_EQ(ulib::StrJoin(vec, ",", true), "a,b,c"); + vec = {"a", "", "c"}; + EXPECT_EQ(ulib::StrJoin(vec, ","), "a,c"); + EXPECT_EQ(ulib::StrJoin(vec, ",", false), "a,,c"); + EXPECT_EQ(ulib::StrJoin(vec, ",", true), "a,c"); + vec = {"", "", ""}; + EXPECT_EQ(ulib::StrJoin(vec, ","), ""); + EXPECT_EQ(ulib::StrJoin(vec, ",", false), ",,"); + EXPECT_EQ(ulib::StrJoin(vec, ",", true), ""); + vec = {"a", "b", ""}; + EXPECT_EQ(ulib::StrJoin(vec, ","), "a,b"); + EXPECT_EQ(ulib::StrJoin(vec, ",", false), "a,b,"); + EXPECT_EQ(ulib::StrJoin(vec, ",", true), "a,b"); + vec = {"", "b", "c"}; + EXPECT_EQ(ulib::StrJoin(vec, ","), "b,c"); + EXPECT_EQ(ulib::StrJoin(vec, ",", false), ",b,c"); + EXPECT_EQ(ulib::StrJoin(vec, ",", true), "b,c"); +}