131 lines
3.5 KiB
C++
131 lines
3.5 KiB
C++
/*
|
|
* Copyright 2015 - 2025 gary@drinkingtea.net
|
|
*
|
|
* 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
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "cstrops.hpp"
|
|
#include "def.hpp"
|
|
#include "error.hpp"
|
|
#include "math.hpp"
|
|
#include "stringview.hpp"
|
|
#include "types.hpp"
|
|
#include "vector.hpp"
|
|
|
|
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
|
|
|
|
namespace ox {
|
|
|
|
[[nodiscard]]
|
|
constexpr StringView substr(StringViewCR str, std::size_t const pos) noexcept {
|
|
if (str.size() >= pos) {
|
|
return {&str[pos], str.size() - pos};
|
|
}
|
|
return {};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr StringView substr(StringViewCR str, std::size_t const start, std::size_t const end) noexcept {
|
|
if (str.size() >= start && end >= start) {
|
|
return {&str[start], end - start};
|
|
}
|
|
return {};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr bool beginsWith(StringViewCR base, char const beginning) noexcept {
|
|
return base.size() && base[0] == beginning;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr bool endsWith(StringViewCR base, char const ending) noexcept {
|
|
return base.size() && base[base.size() - 1] == ending;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr bool beginsWith(StringViewCR base, StringViewCR beginning) noexcept {
|
|
const auto beginningLen = ox::min(beginning.size(), base.size());
|
|
return base.size() >= beginning.size() && ox::strncmp(base.data(), beginning, beginningLen) == 0;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr bool endsWith(StringViewCR base, StringViewCR ending) noexcept {
|
|
const auto endingLen = ending.size();
|
|
return base.size() >= endingLen && ox::strcmp(base.data() + (base.size() - endingLen), ending) == 0;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr std::size_t find(StringViewCR str, char const search) noexcept {
|
|
std::size_t i = 0;
|
|
for (; i < str.size(); ++i) {
|
|
if (str[i] == search) {
|
|
break;
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr std::size_t find(StringViewCR str, StringViewCR search) noexcept {
|
|
std::size_t i = 0;
|
|
for (; i < str.size(); ++i) {
|
|
if (beginsWith(substr(str, i), search)) {
|
|
break;
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
|
|
template<std::size_t smallSz = 0>
|
|
[[nodiscard]]
|
|
constexpr ox::Vector<ox::StringView, smallSz> split(StringViewCR str, char const del) noexcept {
|
|
ox::Vector<ox::StringView, smallSz> out;
|
|
constexpr auto nextSeg = [](StringViewCR current, char del) {
|
|
return substr(current, find(current, del) + 1);
|
|
};
|
|
for (auto current = str; current.size(); current = nextSeg(current, del)) {
|
|
const auto next = find(current, del);
|
|
if (const auto s = substr(current, 0, next); s.size()) {
|
|
out.emplace_back(s);
|
|
}
|
|
current = substr(current, next);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
template<std::size_t smallSz = 0>
|
|
[[nodiscard]]
|
|
constexpr ox::Vector<ox::StringView, smallSz> split(StringViewCR str, StringViewCR del) noexcept {
|
|
ox::Vector<ox::StringView, smallSz> out;
|
|
constexpr auto nextSeg = [](StringViewCR current, StringViewCR del) {
|
|
return substr(current, find(current, del) + del.size());
|
|
};
|
|
for (auto current = str; current.size(); current = nextSeg(current, del)) {
|
|
const auto next = find(current, del);
|
|
if (const auto s = substr(current, 0, next); s.size()) {
|
|
out.emplace_back(s);
|
|
}
|
|
current = substr(current, next);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr ox::Result<std::size_t> lastIndexOf(ox::StringViewCR str, int const character) noexcept {
|
|
ox::Result<std::size_t> retval = ox::Error(1, "Character not found");
|
|
for (auto i = static_cast<int>(str.bytes() - 1); i >= 0; --i) {
|
|
if (str[static_cast<std::size_t>(i)] == character) {
|
|
retval = static_cast<std::size_t>(i);
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
}
|
|
|
|
OX_CLANG_NOWARN_END
|