[ox/std] Add StringView split and find functions

This commit is contained in:
Gary Talent 2023-02-04 22:59:44 -06:00
parent 4b9b70a90e
commit 3c9e6d10ea
3 changed files with 136 additions and 4 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2022 gary@drinkingtea.net * Copyright 2015 - 2023 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -12,10 +12,11 @@
#include <string_view> #include <string_view>
#endif #endif
#include "bit.hpp"
#include "iterator.hpp" #include "iterator.hpp"
#include "strops.hpp" #include "strops.hpp"
#include "types.hpp" #include "types.hpp"
#include "bit.hpp" #include "vector.hpp"
namespace ox { namespace ox {
@ -223,8 +224,19 @@ class StringView {
[[nodiscard]] [[nodiscard]]
constexpr auto substr(std::size_t pos) const noexcept { constexpr auto substr(std::size_t pos) const noexcept {
if (m_len >= pos) {
return StringView(m_str + pos, m_len - pos); return StringView(m_str + pos, m_len - pos);
} }
return StringView();
}
[[nodiscard]]
constexpr auto substr(std::size_t start, std::size_t end) const noexcept {
if (m_len >= start && end >= start) {
return StringView(m_str + start, end - start);
}
return StringView();
}
constexpr auto operator[](std::size_t i) const noexcept { constexpr auto operator[](std::size_t i) const noexcept {
return m_str[i]; return m_str[i];
@ -276,6 +288,58 @@ constexpr bool endsWith(CRStringView base, CRStringView ending) noexcept {
return base.len() >= endingLen && ox_strcmp(base.data() + (base.len() - endingLen), ending) == 0; return base.len() >= endingLen && ox_strcmp(base.data() + (base.len() - endingLen), ending) == 0;
} }
constexpr std::size_t find(CRStringView str, char search) noexcept {
std::size_t i = 0;
for (; i < str.len(); ++i) {
if (str[i] == search) {
break;
}
}
return i;
}
constexpr std::size_t find(CRStringView str, CRStringView search) noexcept {
std::size_t i = 0;
for (; i < str.len(); ++i) {
if (beginsWith(str.substr(i), search)) {
break;
}
}
return i;
}
template<std::size_t smallSz = 0>
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, char del) noexcept {
ox::Vector<ox::StringView, smallSz> out;
constexpr auto nextSeg = [](CRStringView current, char del) {
return current.substr(find(current, del) + 1);
};
for (auto current = str; current.len(); current = nextSeg(current, del)) {
const auto next = find(current, del);
if (const auto s = current.substr(0, next); s.len()) {
out.emplace_back(s);
}
current = current.substr(next);
}
return out;
}
template<std::size_t smallSz = 0>
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, CRStringView del) noexcept {
ox::Vector<ox::StringView, smallSz> out;
constexpr auto nextSeg = [](CRStringView current, CRStringView del) {
return current.substr(find(current, del) + del.len());
};
for (auto current = str; current.len(); current = nextSeg(current, del)) {
const auto next = find(current, del);
if (const auto s = current.substr(0, next); s.len()) {
out.emplace_back(s);
}
current = current.substr(next);
}
return out;
}
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
constexpr auto toStdStringView(CRStringView sv) noexcept { constexpr auto toStdStringView(CRStringView sv) noexcept {
return std::string_view(sv.data(), sv.bytes()); return std::string_view(sv.data(), sv.bytes());

View File

@ -18,3 +18,4 @@ add_test("[ox/std] HashMap" StdTest "HashMap")
add_test("[ox/std] HeapMgr" StdTest malloc) add_test("[ox/std] HeapMgr" StdTest malloc)
add_test("[ox/std] Serialize-Int" StdTest "Serialize-Int") add_test("[ox/std] Serialize-Int" StdTest "Serialize-Int")
add_test("[ox/std] BufferWriter" StdTest "BufferWriter") add_test("[ox/std] BufferWriter" StdTest "BufferWriter")
add_test("[ox/std] StringSplit" StdTest "StringSplit")

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 - 2022 gary@drinkingtea.net * Copyright 2015 - 2023 gary@drinkingtea.net
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -155,6 +155,73 @@ static std::map<ox::String, ox::Error(*)()> tests = {
return OxError(0); return OxError(0);
} }
}, },
{
"StringSplit",
[] {
ox::StringView sv = "ab.cd";
auto list = ox::split(sv, ".");
oxExpect(list.size(), 2u);
oxExpect(list[0], "ab");
oxExpect(list[1], "cd");
sv = "ab.cd.fg";
list = ox::split(sv, ".");
oxExpect(list.size(), 3u);
oxExpect(list[0], "ab");
oxExpect(list[1], "cd");
oxExpect(list[2], "fg");
sv = "ab.cd.";
list = ox::split(sv, ".");
oxExpect(list.size(), 2u);
oxExpect(list[0], "ab");
oxExpect(list[1], "cd");
sv = ".ab.cd.";
list = ox::split(sv, ".");
oxExpect(list.size(), 2u);
oxExpect(list[0], "ab");
oxExpect(list[1], "cd");
sv = ".";
list = ox::split(sv, ".");
oxExpect(list.size(), 0u);
sv = ".";
list = ox::split(sv, ".");
oxExpect(list.size(), 0u);
sv = "";
list = ox::split(sv, ".");
oxExpect(list.size(), 0u);
// split by single char
sv = "ab.cd";
list = ox::split(sv, '.');
oxExpect(list.size(), 2u);
oxExpect(list[0], "ab");
oxExpect(list[1], "cd");
sv = "ab.cd.fg";
list = ox::split(sv, '.');
oxExpect(list.size(), 3u);
oxExpect(list[0], "ab");
oxExpect(list[1], "cd");
oxExpect(list[2], "fg");
sv = "ab.cd.";
list = ox::split(sv, '.');
oxExpect(list.size(), 2u);
oxExpect(list[0], "ab");
oxExpect(list[1], "cd");
sv = ".ab.cd.";
list = ox::split(sv, '.');
oxExpect(list.size(), 2u);
oxExpect(list[0], "ab");
oxExpect(list[1], "cd");
sv = ".";
list = ox::split(sv, '.');
oxExpect(list.size(), 0u);
sv = ".";
list = ox::split(sv, '.');
oxExpect(list.size(), 0u);
sv = "";
list = ox::split(sv, '.');
oxExpect(list.size(), 0u);
return OxError(0);
}
},
}; };
int main(int argc, const char **args) { int main(int argc, const char **args) {