[ox/std] Add missing file, add more string types
This commit is contained in:
parent
d0f19fd51d
commit
d635a954fa
217
deps/ox/src/ox/std/basestringview.hpp
vendored
Normal file
217
deps/ox/src/ox/std/basestringview.hpp
vendored
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright 2015 - 2023 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 "bit.hpp"
|
||||
#include "cstrops.hpp"
|
||||
#include "iterator.hpp"
|
||||
|
||||
namespace ox::detail {
|
||||
|
||||
class BaseStringView {
|
||||
public:
|
||||
template<typename RefType = char&, typename PtrType = char*, bool reverse = false>
|
||||
struct iterator: public Iterator<std::bidirectional_iterator_tag, char> {
|
||||
private:
|
||||
PtrType m_t = nullptr;
|
||||
std::size_t m_offset = 0;
|
||||
std::size_t m_max = 0;
|
||||
|
||||
public:
|
||||
constexpr iterator() noexcept = default;
|
||||
|
||||
constexpr iterator(PtrType t, std::size_t offset, std::size_t max) noexcept {
|
||||
m_t = t;
|
||||
m_offset = offset;
|
||||
m_max = max;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto offset() const noexcept {
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
constexpr iterator operator+(std::size_t s) const noexcept {
|
||||
if constexpr(reverse) {
|
||||
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
|
||||
} else {
|
||||
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr auto operator-(const iterator &other) const noexcept {
|
||||
if constexpr(reverse) {
|
||||
return m_offset + other.m_offset;
|
||||
} else {
|
||||
return m_offset - other.m_offset;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr iterator operator-(std::size_t s) const noexcept {
|
||||
if constexpr(reverse) {
|
||||
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
|
||||
} else {
|
||||
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr iterator &operator+=(std::size_t s) noexcept {
|
||||
if constexpr(reverse) {
|
||||
m_offset = max<std::size_t>(m_offset - s, 0);
|
||||
} else {
|
||||
m_offset = min(m_offset + s, m_max);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr iterator &operator-=(std::size_t s) noexcept {
|
||||
if constexpr(reverse) {
|
||||
m_offset = min(m_offset + s, m_max);
|
||||
} else {
|
||||
m_offset = max<std::size_t>(m_offset - s, 0);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr iterator &operator++() noexcept {
|
||||
return operator+=(1);
|
||||
}
|
||||
|
||||
constexpr iterator &operator--() noexcept {
|
||||
return operator-=(1);
|
||||
}
|
||||
|
||||
constexpr RefType operator*() const noexcept {
|
||||
return m_t[m_offset];
|
||||
}
|
||||
|
||||
constexpr RefType operator[](std::size_t s) const noexcept {
|
||||
return m_t[s];
|
||||
}
|
||||
|
||||
constexpr bool operator<(const iterator &other) const noexcept {
|
||||
return m_offset < other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator>(const iterator &other) const noexcept {
|
||||
return m_offset > other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator<=(const iterator &other) const noexcept {
|
||||
return m_offset <= other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator>=(const iterator &other) const noexcept {
|
||||
return m_offset >= other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const iterator &other) const noexcept {
|
||||
return m_t == other.m_t && m_offset == other.m_offset && m_max == other.m_max;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const iterator &other) const noexcept {
|
||||
return m_t != other.m_t || m_offset != other.m_offset || m_max != other.m_max;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
const char *m_str = nullptr;
|
||||
std::size_t m_len = 0;
|
||||
protected:
|
||||
constexpr BaseStringView() noexcept = default;
|
||||
|
||||
constexpr BaseStringView(BaseStringView const&sv) noexcept = default;
|
||||
|
||||
constexpr explicit BaseStringView(std::nullptr_t) noexcept {}
|
||||
|
||||
constexpr explicit BaseStringView(const char *str) noexcept: m_str(str), m_len(str ? ox_strlen(str) : 0) {}
|
||||
|
||||
constexpr explicit BaseStringView(const char *str, std::size_t len) noexcept: m_str(str), m_len(len) {}
|
||||
|
||||
public:
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> begin() const noexcept {
|
||||
return {m_str, 0, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> end() const noexcept {
|
||||
return {m_str, m_len, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> cbegin() const noexcept {
|
||||
return {m_str, 0, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> cend() const noexcept {
|
||||
return {m_str, m_len, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> crbegin() const noexcept {
|
||||
return {m_str, m_len - 1, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> crend() const noexcept {
|
||||
return {m_str, MaxValue<std::size_t>, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> rbegin() const noexcept {
|
||||
return {m_str, m_len - 1, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> rend() const noexcept {
|
||||
return {m_str, MaxValue<std::size_t>, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto bytes() const noexcept {
|
||||
return m_len;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto len() const noexcept {
|
||||
return m_len;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto *data() const noexcept {
|
||||
return &m_str[0];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto &front() const noexcept {
|
||||
return m_str[0];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto &back() const noexcept {
|
||||
return m_str[m_len - 1];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto operator[](std::size_t i) const noexcept {
|
||||
return m_str[i];
|
||||
}
|
||||
|
||||
protected:
|
||||
constexpr void set(const char *str, std::size_t len) noexcept {
|
||||
m_str = str;
|
||||
m_len = len;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
54
deps/ox/src/ox/std/cstringview.hpp
vendored
Normal file
54
deps/ox/src/ox/std/cstringview.hpp
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2015 - 2023 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
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
#include "basestringview.hpp"
|
||||
#include "bstring.hpp"
|
||||
#include "string.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
class CStringView: public detail::BaseStringView {
|
||||
public:
|
||||
constexpr CStringView() noexcept = default;
|
||||
|
||||
constexpr CStringView(CStringView const&sv) noexcept = default;
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
constexpr CStringView(BasicString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
constexpr CStringView(BString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
|
||||
constexpr CStringView(std::nullptr_t) noexcept {}
|
||||
|
||||
constexpr CStringView(const char *str) noexcept: BaseStringView(str) {}
|
||||
|
||||
constexpr CStringView(const char *str, std::size_t len) noexcept: BaseStringView(str, len) {}
|
||||
|
||||
constexpr auto &operator=(CStringView const&other) noexcept {
|
||||
if (&other != this) {
|
||||
set(other.data(), other.len());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *c_str() const noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
158
deps/ox/src/ox/std/cstrops.hpp
vendored
Normal file
158
deps/ox/src/ox/std/cstrops.hpp
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2015 - 2023 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 "types.hpp"
|
||||
#include "typetraits.hpp"
|
||||
|
||||
template<typename T1, typename T2>
|
||||
constexpr T1 ox_strcpy(T1 dest, T2 src) noexcept {
|
||||
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
|
||||
std::size_t i = 0;
|
||||
while (src[i]) {
|
||||
dest[i] = static_cast<T1Type>(src[i]);
|
||||
++i;
|
||||
}
|
||||
// set null terminator
|
||||
dest[i] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
constexpr T1 ox_strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept {
|
||||
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
|
||||
std::size_t i = 0;
|
||||
while (i < maxLen && src[i]) {
|
||||
dest[i] = static_cast<T1Type>(src[i]);
|
||||
++i;
|
||||
}
|
||||
// set null terminator
|
||||
dest[i] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto ox_strnlen(const char *str1, std::size_t maxLen) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; len < maxLen && str1[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr auto ox_strlen(T str1) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; str1[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strcmp(const T1 &str1, const T2 &str2) noexcept {
|
||||
auto retval = 0;
|
||||
auto i = 0u;
|
||||
while (str1[i] || str2[i]) {
|
||||
if (str1[i] < str2[i]) {
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (str1[i] > str2[i]) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strncmp(T1 str1, T2 str2, const std::size_t maxLen) noexcept {
|
||||
auto retval = 0;
|
||||
std::size_t i = 0;
|
||||
while (i < maxLen && (str1[i] || str2[i])) {
|
||||
if (str1[i] < str2[i]) {
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (str1[i] > str2[i]) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *ox_strchr(const char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
for (std::size_t i = 0; i <= maxLen; i++) {
|
||||
if (str[i] == character) {
|
||||
return &str[i];
|
||||
} else if (str[i] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr char *ox_strchr(char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
for (std::size_t i = 0; i < maxLen; i++) {
|
||||
if (str[i] == character) {
|
||||
return &str[i];
|
||||
} else if (str[i] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int ox_lastIndexOf(const auto &str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
int retval = -1;
|
||||
for (std::size_t i = 0; i < maxLen && str[i]; i++) {
|
||||
if (str[i] == character) {
|
||||
retval = static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename Integer, typename T>
|
||||
constexpr T ox_itoa(Integer v, T str) noexcept {
|
||||
if (v) {
|
||||
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
|
||||
ox::ResizedInt_t<Integer, 64> val = v;
|
||||
constexpr auto base = 10;
|
||||
auto it = 0;
|
||||
if (val < 0) {
|
||||
str[static_cast<std::size_t>(it)] = '-';
|
||||
it++;
|
||||
}
|
||||
while (mod) {
|
||||
auto digit = val / mod;
|
||||
val %= mod;
|
||||
mod /= base;
|
||||
if (it || digit) {
|
||||
ox::ResizedInt_t<Integer, 64> start = '0';
|
||||
if (digit >= 10) {
|
||||
start = 'a';
|
||||
digit -= 10;
|
||||
}
|
||||
str[static_cast<std::size_t>(it)] = static_cast<typename ox::remove_reference<decltype(str[0])>::type>(start + digit);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
str[static_cast<std::size_t>(it)] = 0;
|
||||
} else {
|
||||
// 0 is a special case
|
||||
str[0] = '0';
|
||||
str[1] = 0;
|
||||
}
|
||||
return str;
|
||||
}
|
41
deps/ox/src/ox/std/hashmap.hpp
vendored
41
deps/ox/src/ox/std/hashmap.hpp
vendored
@ -18,25 +18,11 @@ namespace ox {
|
||||
template<typename K, typename T>
|
||||
class HashMap {
|
||||
|
||||
using key_t = K;
|
||||
using value_t = T;
|
||||
public:
|
||||
using key_t = K;
|
||||
using value_t = T;
|
||||
|
||||
private:
|
||||
// Maybe StringView. If K (or KK for MaybeSV) is a string type,
|
||||
// MaybeSV::type/MaybeSV_t is a StringView.
|
||||
// This avoids creating unnecessary Strings when taking a StringView or C
|
||||
// string in lookups.
|
||||
template<typename KK, bool isStr = isOxString_v<KK>>
|
||||
struct MaybeSV {
|
||||
using type = KK;
|
||||
};
|
||||
template<typename KK>
|
||||
struct MaybeSV<KK, true> {
|
||||
using type = ox::StringView;
|
||||
};
|
||||
template<typename KK>
|
||||
using MaybeSV_t = MaybeSV<KK>::type;
|
||||
|
||||
struct Pair {
|
||||
K key = {};
|
||||
T value{};
|
||||
@ -85,15 +71,9 @@ class HashMap {
|
||||
|
||||
constexpr static uint64_t hash(StringView const&) noexcept;
|
||||
|
||||
/**
|
||||
* K is assumed to be a null terminated string.
|
||||
*/
|
||||
template<typename KK>
|
||||
constexpr Pair *const&access(Vector<Pair*> const&pairs, KK const&key) const;
|
||||
|
||||
/**
|
||||
* K is assumed to be a null terminated string.
|
||||
*/
|
||||
template<typename KK>
|
||||
constexpr Pair *&access(Vector<Pair*> &pairs, KK const&key);
|
||||
|
||||
@ -124,7 +104,7 @@ constexpr bool HashMap<K, T>::operator==(HashMap const&other) const {
|
||||
if (m_keys != other.m_keys) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < m_keys.size(); i++) {
|
||||
for (int i = 0; i < m_keys.size(); ++i) {
|
||||
auto &k = m_keys[i];
|
||||
if (at(k) != other.at(k)) {
|
||||
return false;
|
||||
@ -194,7 +174,7 @@ constexpr void HashMap<K, T>::erase(MaybeSV_t<K> const&k) {
|
||||
auto h = hash(k) % m_pairs.size();
|
||||
while (true) {
|
||||
const auto &p = m_pairs[h];
|
||||
if (p == nullptr || ox_strcmp(p->key, k) == 0) {
|
||||
if (p == nullptr || p->key == k) {
|
||||
oxIgnoreError(m_pairs.erase(h));
|
||||
break;
|
||||
} else {
|
||||
@ -264,7 +244,7 @@ constexpr typename HashMap<K, T>::Pair *const&HashMap<K, T>::access(Vector<Pair*
|
||||
auto h = static_cast<std::size_t>(hash(k) % pairs.size());
|
||||
while (true) {
|
||||
const auto &p = pairs[h];
|
||||
if (p == nullptr || ox_strcmp(p->key, k) == 0) {
|
||||
if (p == nullptr || p->key == k) {
|
||||
return p;
|
||||
} else {
|
||||
h = (h + 1) % pairs.size();
|
||||
@ -278,14 +258,7 @@ constexpr typename HashMap<K, T>::Pair *&HashMap<K, T>::access(Vector<Pair*> &pa
|
||||
auto h = static_cast<std::size_t>(hash(k) % pairs.size());
|
||||
while (true) {
|
||||
auto &p = pairs[h];
|
||||
bool matches = [&] {
|
||||
if constexpr (is_integral_v<KK>) {
|
||||
return p == nullptr || k == p->key;
|
||||
} else {
|
||||
return p == nullptr || ox_strcmp(p->key, k) == 0;
|
||||
}
|
||||
}();
|
||||
if (matches) {
|
||||
if (p == nullptr || p->key == k) {
|
||||
return p;
|
||||
} else {
|
||||
h = (h + 1) % pairs.size();
|
||||
|
3
deps/ox/src/ox/std/std.hpp
vendored
3
deps/ox/src/ox/std/std.hpp
vendored
@ -15,6 +15,8 @@
|
||||
#include "bstring.hpp"
|
||||
#include "byteswap.hpp"
|
||||
#include "concepts.hpp"
|
||||
#include "cstringview.hpp"
|
||||
#include "cstrops.hpp"
|
||||
#include "def.hpp"
|
||||
#include "defer.hpp"
|
||||
#include "defines.hpp"
|
||||
@ -37,6 +39,7 @@
|
||||
#include "stacktrace.hpp"
|
||||
#include "stddef.hpp"
|
||||
#include "string.hpp"
|
||||
#include "stringliteral.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "strongint.hpp"
|
||||
#include "strops.hpp"
|
||||
|
7
deps/ox/src/ox/std/string.hpp
vendored
7
deps/ox/src/ox/std/string.hpp
vendored
@ -581,6 +581,13 @@ extern template class BasicString<8>;
|
||||
using String = BasicString<8>;
|
||||
using CRString = String const&;
|
||||
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::String toString(ox::CRStringView sv) noexcept {
|
||||
return ox::String(sv);
|
||||
}
|
||||
|
||||
|
||||
template<typename PlatSpec, std::size_t SmallStringSize_v>
|
||||
[[nodiscard]]
|
||||
constexpr auto sizeOf(const ox::BasicString<SmallStringSize_v>*) noexcept {
|
||||
|
89
deps/ox/src/ox/std/stringview.hpp
vendored
89
deps/ox/src/ox/std/stringview.hpp
vendored
@ -12,12 +12,9 @@
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
#include "bit.hpp"
|
||||
#include "concepts.hpp"
|
||||
#include "iterator.hpp"
|
||||
#include "stringliteral.hpp"
|
||||
#include "strops.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "basestringview.hpp"
|
||||
#include "cstrops.hpp"
|
||||
#include "writer.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
@ -89,70 +86,6 @@ constexpr auto operator<=>(CRStringView s1, CRStringView s2) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept {
|
||||
const auto beginningLen = ox::min(beginning.len(), base.len());
|
||||
return base.len() >= beginning.len() && ox_strncmp(base.data(), beginning, beginningLen) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool endsWith(CRStringView base, CRStringView ending) noexcept {
|
||||
const auto endingLen = ending.len();
|
||||
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(substr(str, 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 substr(current, find(current, del) + 1);
|
||||
};
|
||||
for (auto current = str; current.len(); current = nextSeg(current, del)) {
|
||||
const auto next = find(current, del);
|
||||
if (const auto s = substr(current, 0, next); s.len()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, 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 substr(current, 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 = substr(current, 0, next); s.len()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, next);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
constexpr auto write(Writer_c auto &writer, ox::CRStringView sv) noexcept {
|
||||
return writer.write(sv.data(), sv.bytes());
|
||||
}
|
||||
@ -163,6 +96,22 @@ constexpr auto toStdStringView(CRStringView sv) noexcept {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Maybe StringView. If T is a string type, MaybeType::type/MaybeSV_t is a
|
||||
// StringView. This avoids creating unnecessary Strings when taking a
|
||||
// StringView or C string as a function argument.
|
||||
template<typename T, bool isStr = isOxString_v<T>>
|
||||
struct MaybeSV {
|
||||
using type = T;
|
||||
};
|
||||
template<typename T>
|
||||
struct MaybeSV<T, true> {
|
||||
using type = ox::StringView;
|
||||
};
|
||||
template<typename KK>
|
||||
using MaybeSV_t = MaybeSV<KK>::type;
|
||||
|
||||
|
||||
}
|
||||
|
||||
constexpr ox::Result<int> ox_atoi(ox::CRStringView str) noexcept {
|
||||
|
211
deps/ox/src/ox/std/strops.hpp
vendored
211
deps/ox/src/ox/std/strops.hpp
vendored
@ -8,125 +8,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "concepts.hpp"
|
||||
#include "cstrops.hpp"
|
||||
#include "error.hpp"
|
||||
#include "math.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "types.hpp"
|
||||
#include "typetraits.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "writer.hpp"
|
||||
|
||||
template<typename T1, typename T2>
|
||||
constexpr T1 ox_strcpy(T1 dest, T2 src) noexcept {
|
||||
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
|
||||
std::size_t i = 0;
|
||||
while (src[i]) {
|
||||
dest[i] = static_cast<T1Type>(src[i]);
|
||||
++i;
|
||||
}
|
||||
// set null terminator
|
||||
dest[i] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
constexpr T1 ox_strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept {
|
||||
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
|
||||
std::size_t i = 0;
|
||||
while (i < maxLen && src[i]) {
|
||||
dest[i] = static_cast<T1Type>(src[i]);
|
||||
++i;
|
||||
}
|
||||
// set null terminator
|
||||
dest[i] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto ox_strnlen(const char *str1, std::size_t maxLen) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; len < maxLen && str1[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr auto ox_strlen(T str1) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; str1[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strcmp(const T1 &str1, const T2 &str2) noexcept {
|
||||
auto retval = 0;
|
||||
auto i = 0u;
|
||||
while (str1[i] || str2[i]) {
|
||||
if (str1[i] < str2[i]) {
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (str1[i] > str2[i]) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strncmp(T1 str1, T2 str2, const std::size_t maxLen) noexcept {
|
||||
auto retval = 0;
|
||||
std::size_t i = 0;
|
||||
while (i < maxLen && (str1[i] || str2[i])) {
|
||||
if (str1[i] < str2[i]) {
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (str1[i] > str2[i]) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *ox_strchr(const char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
for (std::size_t i = 0; i <= maxLen; i++) {
|
||||
if (str[i] == character) {
|
||||
return &str[i];
|
||||
} else if (str[i] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr char *ox_strchr(char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
for (std::size_t i = 0; i < maxLen; i++) {
|
||||
if (str[i] == character) {
|
||||
return &str[i];
|
||||
} else if (str[i] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int ox_lastIndexOf(const auto &str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
int retval = -1;
|
||||
for (std::size_t i = 0; i < maxLen && str[i]; i++) {
|
||||
if (str[i] == character) {
|
||||
retval = static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<OxString_c Str>
|
||||
@ -179,38 +68,68 @@ constexpr ox::Error itoa(Integer v, ox::Writer_c auto &writer) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept {
|
||||
const auto beginningLen = ox::min(beginning.len(), base.len());
|
||||
return base.len() >= beginning.len() && ox_strncmp(base.data(), beginning, beginningLen) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool endsWith(CRStringView base, CRStringView ending) noexcept {
|
||||
const auto endingLen = ending.len();
|
||||
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(substr(str, 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 substr(current, find(current, del) + 1);
|
||||
};
|
||||
for (auto current = str; current.len(); current = nextSeg(current, del)) {
|
||||
const auto next = find(current, del);
|
||||
if (const auto s = substr(current, 0, next); s.len()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, 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 substr(current, 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 = substr(current, 0, next); s.len()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, next);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename Integer, typename T>
|
||||
constexpr T ox_itoa(Integer v, T str) noexcept {
|
||||
if (v) {
|
||||
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
|
||||
ox::ResizedInt_t<Integer, 64> val = v;
|
||||
constexpr auto base = 10;
|
||||
auto it = 0;
|
||||
if (val < 0) {
|
||||
str[static_cast<std::size_t>(it)] = '-';
|
||||
it++;
|
||||
}
|
||||
while (mod) {
|
||||
auto digit = val / mod;
|
||||
val %= mod;
|
||||
mod /= base;
|
||||
if (it || digit) {
|
||||
ox::ResizedInt_t<Integer, 64> start = '0';
|
||||
if (digit >= 10) {
|
||||
start = 'a';
|
||||
digit -= 10;
|
||||
}
|
||||
str[static_cast<std::size_t>(it)] = static_cast<typename ox::remove_reference<decltype(str[0])>::type>(start + digit);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
str[static_cast<std::size_t>(it)] = 0;
|
||||
} else {
|
||||
// 0 is a special case
|
||||
str[0] = '0';
|
||||
str[1] = 0;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user