#pragma once #if !defined(MIJIN_UTIL_STRING_HPP_INCLUDED) #define MIJIN_UTIL_STRING_HPP_INCLUDED 1 #include #include #include #include #include #include #include "./iterators.hpp" namespace mijin { // // public defines // // // public constants // // // public types // // // public functions // template [[nodiscard]] std::string join(const TRange& elements, const char* const delimiter) { std::ostringstream oss; auto first = std::begin(elements); auto last = std::end(elements); if (first != last) { std::copy(first, std::prev(last), std::ostream_iterator(oss, delimiter)); first = std::prev(last); } if (first != last) { oss << *first; } return oss.str(); } namespace detail { template std::vector> splitImpl(std::basic_string_view stringView, std::basic_string_view seperator) { return std::views::split(stringView, seperator) | std::views::transform([](auto val) { return std::string_view(val); }) | std::ranges::to(); } template bool equalsIgnoreCaseImpl(std::basic_string_view stringA, std::basic_string_view stringB) noexcept { if (stringA.size() != stringB.size()) { return false; } for (const auto [charA, charB] : zip(stringA, stringB)) { if (std::tolower(charA) != std::tolower(charB)) { return false; } } return true; } template static const TChar SPACE = TChar(' '); } template [[nodiscard]] auto split(TLeft&& left, TRight&& right) { return detail::splitImpl(std::basic_string_view(std::forward(left)), std::basic_string_view(std::forward(right))); } template std::basic_string_view trimPrefix(std::basic_string_view stringView, std::basic_string_view charsToTrim = {&detail::SPACE, &detail::SPACE + 1}) { stringView.remove_prefix(std::min(stringView.find_first_not_of(charsToTrim), stringView.size())); return stringView; } template std::basic_string_view trimSuffix(std::basic_string_view stringView, std::basic_string_view charsToTrim = {&detail::SPACE, &detail::SPACE + 1}) { stringView.remove_suffix(stringView.size() - std::min(stringView.find_last_not_of(charsToTrim) + 1, stringView.size())); return stringView; } template std::basic_string_view trim(std::basic_string_view stringView, std::basic_string_view charsToTrim = {&detail::SPACE, &detail::SPACE + 1}) { return trimPrefix(trimSuffix(stringView, charsToTrim), charsToTrim); } template [[nodiscard]] bool equalsIgnoreCase(TLeft&& left, TRight&& right) noexcept { return detail::equalsIgnoreCaseImpl(std::string_view(left), std::string_view(right)); } namespace pipe { struct Join { const char* delimiter; explicit Join(const char* delimiter_) noexcept : delimiter(delimiter_) {} }; template auto operator|(TIterable&& iterable, const Join& joiner) { return join(std::forward(iterable), joiner.delimiter); } } } // namespace mijin #endif // !defined(MIJIN_UTIL_STRING_HPP_INCLUDED)