[ox/std] Rework itoa
This commit is contained in:
parent
4061b8314e
commit
20ff0f89fe
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
@ -124,6 +124,7 @@ install(
|
|||||||
stringliteral.hpp
|
stringliteral.hpp
|
||||||
stringview.hpp
|
stringview.hpp
|
||||||
strongint.hpp
|
strongint.hpp
|
||||||
|
strconv.hpp
|
||||||
strops.hpp
|
strops.hpp
|
||||||
trace.hpp
|
trace.hpp
|
||||||
typeinfo.hpp
|
typeinfo.hpp
|
||||||
|
34
deps/ox/src/ox/std/cstrops.hpp
vendored
34
deps/ox/src/ox/std/cstrops.hpp
vendored
@ -112,38 +112,4 @@ constexpr int lastIndexOf(const auto &str, int character, std::size_t maxLen = 0
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Integer, typename T>
|
|
||||||
constexpr T 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
11
deps/ox/src/ox/std/fmt.hpp
vendored
11
deps/ox/src/ox/std/fmt.hpp
vendored
@ -75,14 +75,17 @@ constexpr StringView toStringView(const auto&) noexcept requires(force) {
|
|||||||
class FmtArg {
|
class FmtArg {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char dataStr[10] = {};
|
static constexpr auto DataSz = 23;
|
||||||
|
char dataStr[DataSz] = {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr StringView sv(const T &v, char *dataStr) noexcept {
|
constexpr StringView sv(const T &v, char *dataStr) noexcept {
|
||||||
if constexpr(is_bool_v<T>) {
|
if constexpr(is_bool_v<T>) {
|
||||||
return v ? "true" : "false";
|
return v ? "true" : "false";
|
||||||
} else if constexpr(is_integer_v<T>) {
|
} else if constexpr(is_integer_v<T>) {
|
||||||
return ox::itoa(v, dataStr);
|
ox::CharBuffWriter w(dataStr, DataSz);
|
||||||
|
std::ignore = ox::writeItoa(v, w);
|
||||||
|
return dataStr;
|
||||||
} else {
|
} else {
|
||||||
return toStringView(v);
|
return toStringView(v);
|
||||||
}
|
}
|
||||||
@ -197,13 +200,13 @@ constexpr StringType sfmt(StringView fmt, Args&&... args) noexcept {
|
|||||||
for (size_t i = 0; i < fmtSegments.size - 1; ++i) {
|
for (size_t i = 0; i < fmtSegments.size - 1; ++i) {
|
||||||
std::ignore = out.append(elements[i].out);
|
std::ignore = out.append(elements[i].out);
|
||||||
const auto &s = fmtSegments.segments[i + 1];
|
const auto &s = fmtSegments.segments[i + 1];
|
||||||
std::ignore = out.append(s.str);
|
std::ignore = out.append(s.str, s.length);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = String>
|
template<typename T = String>
|
||||||
constexpr Result<T> join(auto d, const auto &list) {
|
constexpr Result<T> join(auto const&d, auto const&list) {
|
||||||
if (!list.size()) {
|
if (!list.size()) {
|
||||||
return T("");
|
return T("");
|
||||||
}
|
}
|
||||||
|
55
deps/ox/src/ox/std/istring.hpp
vendored
55
deps/ox/src/ox/std/istring.hpp
vendored
@ -9,10 +9,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "array.hpp"
|
#include "array.hpp"
|
||||||
|
#include "concepts.hpp"
|
||||||
|
#include "cstrops.hpp"
|
||||||
#include "memops.hpp"
|
#include "memops.hpp"
|
||||||
#include "ox/std/error.hpp"
|
#include "error.hpp"
|
||||||
|
#include "buffer.hpp"
|
||||||
|
#include "ignore.hpp"
|
||||||
#include "stringview.hpp"
|
#include "stringview.hpp"
|
||||||
#include "typetraits.hpp"
|
#include "typetraits.hpp"
|
||||||
|
#include "strconv.hpp"
|
||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
@ -20,8 +25,8 @@ namespace ox {
|
|||||||
template<std::size_t StrCap>
|
template<std::size_t StrCap>
|
||||||
class IString {
|
class IString {
|
||||||
private:
|
private:
|
||||||
ox::Array<char, StrCap + 1> m_buff;
|
|
||||||
size_t m_size{};
|
size_t m_size{};
|
||||||
|
ox::Array<char, StrCap + 1> m_buff;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr IString() noexcept;
|
constexpr IString() noexcept;
|
||||||
@ -34,8 +39,6 @@ class IString {
|
|||||||
|
|
||||||
constexpr IString &operator=(const char *str) noexcept;
|
constexpr IString &operator=(const char *str) noexcept;
|
||||||
|
|
||||||
constexpr IString &operator=(char *str) noexcept;
|
|
||||||
|
|
||||||
constexpr IString &operator=(Integer_c auto i) noexcept;
|
constexpr IString &operator=(Integer_c auto i) noexcept;
|
||||||
|
|
||||||
|
|
||||||
@ -101,9 +104,11 @@ constexpr IString<size>::IString(const char *str) noexcept: m_buff{{0}} {
|
|||||||
|
|
||||||
template<std::size_t size>
|
template<std::size_t size>
|
||||||
constexpr IString<size> &IString<size>::operator=(Integer_c auto i) noexcept {
|
constexpr IString<size> &IString<size>::operator=(Integer_c auto i) noexcept {
|
||||||
ox::Array<char, 65> str{};
|
ox::Array<char, 22> s;
|
||||||
ox::itoa(i, str.data());
|
ox::CharBuffWriter w(s);
|
||||||
return this->operator=(str.data());
|
std::ignore = ox::writeItoa(i, w);
|
||||||
|
this->operator=({s.data(), w.tellp()});
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::size_t size>
|
template<std::size_t size>
|
||||||
@ -132,11 +137,6 @@ constexpr IString<size> &IString<size>::operator=(const char *str) noexcept {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::size_t size>
|
|
||||||
constexpr IString<size> &IString<size>::operator=(char *str) noexcept {
|
|
||||||
return *this = static_cast<const char*>(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t StrCap>
|
template<std::size_t StrCap>
|
||||||
constexpr bool IString<StrCap>::operator==(const char *other) const noexcept {
|
constexpr bool IString<StrCap>::operator==(const char *other) const noexcept {
|
||||||
return ox::StringView(*this) == other;
|
return ox::StringView(*this) == other;
|
||||||
@ -239,9 +239,12 @@ constexpr std::size_t IString<StrCap>::bytes() const noexcept {
|
|||||||
|
|
||||||
template<std::size_t StrCap>
|
template<std::size_t StrCap>
|
||||||
constexpr ox::Error IString<StrCap>::resize(size_t sz) noexcept {
|
constexpr ox::Error IString<StrCap>::resize(size_t sz) noexcept {
|
||||||
if (sz > StrCap) {
|
if (sz > StrCap) [[unlikely]] {
|
||||||
return OxError(1, "Trying to extend IString beyond its cap");
|
return OxError(1, "Trying to extend IString beyond its cap");
|
||||||
}
|
}
|
||||||
|
for (auto i = m_size; i < sz; ++i) {
|
||||||
|
m_buff[i] = 0;
|
||||||
|
}
|
||||||
m_size = sz;
|
m_size = sz;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -256,4 +259,30 @@ struct MaybeView<ox::IString<sz>> {
|
|||||||
using type = ox::StringView;
|
using type = ox::StringView;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<Integer_c Integer>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr auto itoa(Integer v) noexcept {
|
||||||
|
constexpr auto Cap = [] {
|
||||||
|
auto out = 0;
|
||||||
|
switch (sizeof(Integer)) {
|
||||||
|
case 1:
|
||||||
|
out = 3;
|
||||||
|
case 2:
|
||||||
|
out = 5;
|
||||||
|
case 4:
|
||||||
|
out = 10;
|
||||||
|
case 8:
|
||||||
|
out = 21;
|
||||||
|
}
|
||||||
|
return out + ox::is_signed_v<Integer>;
|
||||||
|
}();
|
||||||
|
ox::IString<Cap> out;
|
||||||
|
std::ignore = out.resize(out.cap());
|
||||||
|
ox::CharBuffWriter w(out.data(), out.cap());
|
||||||
|
std::ignore = writeItoa(v, w);
|
||||||
|
std::ignore = out.resize(w.tellp());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
44
deps/ox/src/ox/std/strconv.hpp
vendored
Normal file
44
deps/ox/src/ox/std/strconv.hpp
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "error.hpp"
|
||||||
|
#include "types.hpp"
|
||||||
|
#include "writer.hpp"
|
||||||
|
|
||||||
|
namespace ox {
|
||||||
|
|
||||||
|
template<Integer_c Integer>
|
||||||
|
constexpr ox::Error writeItoa(Integer v, ox::Writer_c auto &writer) 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) {
|
||||||
|
oxReturnError(writer.put('-'));
|
||||||
|
++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;
|
||||||
|
}
|
||||||
|
oxReturnError(writer.put(static_cast<char>(start + digit)));
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 0 is a special case
|
||||||
|
oxReturnError(writer.put('0'));
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "istring.hpp"
|
20
deps/ox/src/ox/std/string.hpp
vendored
20
deps/ox/src/ox/std/string.hpp
vendored
@ -16,6 +16,7 @@
|
|||||||
#include "ignore.hpp"
|
#include "ignore.hpp"
|
||||||
#include "memops.hpp"
|
#include "memops.hpp"
|
||||||
#include "serialize.hpp"
|
#include "serialize.hpp"
|
||||||
|
#include "strconv.hpp"
|
||||||
#include "stringliteral.hpp"
|
#include "stringliteral.hpp"
|
||||||
#include "stringview.hpp"
|
#include "stringview.hpp"
|
||||||
#include "strops.hpp"
|
#include "strops.hpp"
|
||||||
@ -23,6 +24,9 @@
|
|||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
|
template<typename Integer>
|
||||||
|
constexpr ox::IString<21> itoa(Integer v) noexcept;
|
||||||
|
|
||||||
template<std::size_t SmallStringSize_v>
|
template<std::size_t SmallStringSize_v>
|
||||||
class BasicString {
|
class BasicString {
|
||||||
private:
|
private:
|
||||||
@ -327,17 +331,13 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat
|
|||||||
|
|
||||||
template<std::size_t SmallStringSize_v>
|
template<std::size_t SmallStringSize_v>
|
||||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(int64_t i) noexcept {
|
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(int64_t i) noexcept {
|
||||||
ox::Array<char, 65> str{};
|
set(ox::itoa(i));
|
||||||
ox::itoa(i, str.data());
|
|
||||||
set(str.data());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::size_t SmallStringSize_v>
|
template<std::size_t SmallStringSize_v>
|
||||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(uint64_t i) noexcept {
|
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(uint64_t i) noexcept {
|
||||||
ox::Array<char, 65> str{};
|
set(ox::itoa(i));
|
||||||
ox::itoa(i, str.data());
|
|
||||||
set(str.data());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,9 +383,8 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat
|
|||||||
|
|
||||||
template<std::size_t SmallStringSize_v>
|
template<std::size_t SmallStringSize_v>
|
||||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(Integer_c auto i) noexcept {
|
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(Integer_c auto i) noexcept {
|
||||||
char str[65] = {};
|
auto const str = ox::itoa(i);
|
||||||
ox::itoa(i, str);
|
return this->operator+=(str.c_str());
|
||||||
return this->operator+=(str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::size_t SmallStringSize_v>
|
template<std::size_t SmallStringSize_v>
|
||||||
@ -427,8 +426,7 @@ constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operato
|
|||||||
|
|
||||||
template<std::size_t SmallStringSize_v>
|
template<std::size_t SmallStringSize_v>
|
||||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(Integer_c auto i) const noexcept {
|
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(Integer_c auto i) const noexcept {
|
||||||
char str[65] = {};
|
auto const str = ox::itoa(i);
|
||||||
ox::itoa(i, str);
|
|
||||||
return *this + str;
|
return *this + str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
deps/ox/src/ox/std/strops.hpp
vendored
32
deps/ox/src/ox/std/strops.hpp
vendored
@ -33,38 +33,6 @@ constexpr ox::StringView substr(ox::StringView const&str, std::size_t start, std
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Integer>
|
|
||||||
constexpr ox::Error writeItoa(Integer v, ox::Writer_c auto &writer) 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) {
|
|
||||||
oxReturnError(writer.put('-'));
|
|
||||||
++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;
|
|
||||||
}
|
|
||||||
oxReturnError(writer.put(static_cast<char>(start + digit)));
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 0 is a special case
|
|
||||||
oxReturnError(writer.put('0'));
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept {
|
constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept {
|
||||||
const auto beginningLen = ox::min(beginning.len(), base.len());
|
const auto beginningLen = ox::min(beginning.len(), base.len());
|
||||||
|
11
deps/ox/src/ox/std/vector.hpp
vendored
11
deps/ox/src/ox/std/vector.hpp
vendored
@ -30,7 +30,6 @@ struct VectorAllocator {
|
|||||||
static_assert(alignof(AllocAlias<T>) == alignof(T));
|
static_assert(alignof(AllocAlias<T>) == alignof(T));
|
||||||
private:
|
private:
|
||||||
ox::Array<AllocAlias<T>, Size> m_data = {};
|
ox::Array<AllocAlias<T>, Size> m_data = {};
|
||||||
Allocator m_allocator;
|
|
||||||
protected:
|
protected:
|
||||||
constexpr VectorAllocator() noexcept = default;
|
constexpr VectorAllocator() noexcept = default;
|
||||||
constexpr VectorAllocator(const VectorAllocator&) noexcept = default;
|
constexpr VectorAllocator(const VectorAllocator&) noexcept = default;
|
||||||
@ -39,7 +38,7 @@ struct VectorAllocator {
|
|||||||
constexpr void allocate(T **items, std::size_t cap) noexcept {
|
constexpr void allocate(T **items, std::size_t cap) noexcept {
|
||||||
// small vector optimization cannot be done it constexpr, but it doesn't really matter in constexpr
|
// small vector optimization cannot be done it constexpr, but it doesn't really matter in constexpr
|
||||||
if (std::is_constant_evaluated() || cap > Size) {
|
if (std::is_constant_evaluated() || cap > Size) {
|
||||||
*items = m_allocator.allocate(cap);
|
*items = Allocator{}.allocate(cap);
|
||||||
} else {
|
} else {
|
||||||
*items = reinterpret_cast<T*>(m_data.data());
|
*items = reinterpret_cast<T*>(m_data.data());
|
||||||
}
|
}
|
||||||
@ -87,7 +86,7 @@ struct VectorAllocator {
|
|||||||
// small vector optimization cannot be done it constexpr, but it doesn't really matter in constexpr
|
// small vector optimization cannot be done it constexpr, but it doesn't really matter in constexpr
|
||||||
if (std::is_constant_evaluated()) {
|
if (std::is_constant_evaluated()) {
|
||||||
if (items && static_cast<void*>(items) != static_cast<void*>(m_data.data())) {
|
if (items && static_cast<void*>(items) != static_cast<void*>(m_data.data())) {
|
||||||
m_allocator.deallocate(items, cap);
|
Allocator{}.deallocate(items, cap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,15 +95,13 @@ struct VectorAllocator {
|
|||||||
|
|
||||||
template<typename T, typename Allocator>
|
template<typename T, typename Allocator>
|
||||||
struct VectorAllocator<T, Allocator, 0> {
|
struct VectorAllocator<T, Allocator, 0> {
|
||||||
private:
|
|
||||||
Allocator m_allocator;
|
|
||||||
protected:
|
protected:
|
||||||
constexpr VectorAllocator() noexcept = default;
|
constexpr VectorAllocator() noexcept = default;
|
||||||
constexpr VectorAllocator(const VectorAllocator&) noexcept = default;
|
constexpr VectorAllocator(const VectorAllocator&) noexcept = default;
|
||||||
constexpr VectorAllocator(VectorAllocator&&) noexcept = default;
|
constexpr VectorAllocator(VectorAllocator&&) noexcept = default;
|
||||||
|
|
||||||
constexpr void allocate(T **items, std::size_t cap) noexcept {
|
constexpr void allocate(T **items, std::size_t cap) noexcept {
|
||||||
*items = m_allocator.allocate(cap);
|
*items = Allocator{}.allocate(cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]]
|
[[maybe_unused]]
|
||||||
@ -121,7 +118,7 @@ struct VectorAllocator<T, Allocator, 0> {
|
|||||||
|
|
||||||
constexpr void deallocate(T *items, std::size_t cap) noexcept {
|
constexpr void deallocate(T *items, std::size_t cap) noexcept {
|
||||||
if (items) {
|
if (items) {
|
||||||
m_allocator.deallocate(items, cap);
|
Allocator{}.deallocate(items, cap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user