[ox/std] Rework itoa
This commit is contained in:
		
							
								
								
									
										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 | ||||
| 		stringview.hpp | ||||
| 		strongint.hpp | ||||
| 		strconv.hpp | ||||
| 		strops.hpp | ||||
| 		trace.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; | ||||
| } | ||||
|  | ||||
| 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 { | ||||
|  | ||||
| 	private: | ||||
| 		char dataStr[10] = {}; | ||||
| 		static constexpr auto DataSz = 23; | ||||
| 		char dataStr[DataSz] = {}; | ||||
|  | ||||
| 		template<typename T> | ||||
| 		constexpr StringView sv(const T &v, char *dataStr) noexcept { | ||||
| 			if constexpr(is_bool_v<T>) { | ||||
| 				return v ? "true" : "false"; | ||||
| 			} 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 { | ||||
| 				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) { | ||||
| 		std::ignore = out.append(elements[i].out); | ||||
| 		const auto &s = fmtSegments.segments[i + 1]; | ||||
| 		std::ignore = out.append(s.str); | ||||
| 		std::ignore = out.append(s.str, s.length); | ||||
| 	} | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| 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()) { | ||||
| 		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 | ||||
|  | ||||
| #include "array.hpp" | ||||
| #include "concepts.hpp" | ||||
| #include "cstrops.hpp" | ||||
| #include "memops.hpp" | ||||
| #include "ox/std/error.hpp" | ||||
| #include "error.hpp" | ||||
| #include "buffer.hpp" | ||||
| #include "ignore.hpp" | ||||
| #include "stringview.hpp" | ||||
| #include "typetraits.hpp" | ||||
| #include "strconv.hpp" | ||||
|  | ||||
| namespace ox { | ||||
|  | ||||
| @@ -20,8 +25,8 @@ namespace ox { | ||||
| template<std::size_t StrCap> | ||||
| class IString { | ||||
| 	private: | ||||
| 		ox::Array<char, StrCap + 1> m_buff; | ||||
| 		size_t m_size{}; | ||||
| 		ox::Array<char, StrCap + 1> m_buff; | ||||
|  | ||||
| 	public: | ||||
| 		constexpr IString() noexcept; | ||||
| @@ -34,8 +39,6 @@ class IString { | ||||
|  | ||||
| 		constexpr IString &operator=(const char *str) noexcept; | ||||
|  | ||||
| 		constexpr IString &operator=(char *str) 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> | ||||
| constexpr IString<size> &IString<size>::operator=(Integer_c auto i) noexcept { | ||||
| 	ox::Array<char, 65> str{}; | ||||
| 	ox::itoa(i, str.data()); | ||||
| 	return this->operator=(str.data()); | ||||
| 	ox::Array<char, 22> s; | ||||
| 	ox::CharBuffWriter w(s); | ||||
| 	std::ignore = ox::writeItoa(i, w); | ||||
| 	this->operator=({s.data(), w.tellp()}); | ||||
| 	return *this; | ||||
| } | ||||
|  | ||||
| template<std::size_t size> | ||||
| @@ -132,11 +137,6 @@ constexpr IString<size> &IString<size>::operator=(const char *str) noexcept { | ||||
| 	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> | ||||
| constexpr bool IString<StrCap>::operator==(const char *other) const noexcept { | ||||
| 	return ox::StringView(*this) == other; | ||||
| @@ -239,9 +239,12 @@ constexpr std::size_t IString<StrCap>::bytes() const noexcept { | ||||
|  | ||||
| template<std::size_t StrCap> | ||||
| 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"); | ||||
| 	} | ||||
| 	for (auto i = m_size; i < sz; ++i) { | ||||
| 		m_buff[i] = 0; | ||||
| 	} | ||||
| 	m_size = sz; | ||||
| 	return {}; | ||||
| } | ||||
| @@ -256,4 +259,30 @@ struct MaybeView<ox::IString<sz>> { | ||||
| 	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 "memops.hpp" | ||||
| #include "serialize.hpp" | ||||
| #include "strconv.hpp" | ||||
| #include "stringliteral.hpp" | ||||
| #include "stringview.hpp" | ||||
| #include "strops.hpp" | ||||
| @@ -23,6 +24,9 @@ | ||||
|  | ||||
| namespace ox { | ||||
|  | ||||
| template<typename Integer> | ||||
| constexpr ox::IString<21> itoa(Integer v) noexcept; | ||||
|  | ||||
| template<std::size_t SmallStringSize_v> | ||||
| class BasicString { | ||||
| 	private: | ||||
| @@ -327,17 +331,13 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat | ||||
|  | ||||
| template<std::size_t SmallStringSize_v> | ||||
| constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(int64_t i) noexcept { | ||||
| 	ox::Array<char, 65> str{}; | ||||
| 	ox::itoa(i, str.data()); | ||||
| 	set(str.data()); | ||||
| 	set(ox::itoa(i)); | ||||
| 	return *this; | ||||
| } | ||||
|  | ||||
| template<std::size_t SmallStringSize_v> | ||||
| constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(uint64_t i) noexcept { | ||||
| 	ox::Array<char, 65> str{}; | ||||
| 	ox::itoa(i, str.data()); | ||||
| 	set(str.data()); | ||||
| 	set(ox::itoa(i)); | ||||
| 	return *this; | ||||
| } | ||||
|  | ||||
| @@ -383,9 +383,8 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat | ||||
|  | ||||
| template<std::size_t SmallStringSize_v> | ||||
| constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(Integer_c auto i) noexcept { | ||||
| 	char str[65] = {}; | ||||
| 	ox::itoa(i, str); | ||||
| 	return this->operator+=(str); | ||||
| 	auto const str = ox::itoa(i); | ||||
| 	return this->operator+=(str.c_str()); | ||||
| } | ||||
|  | ||||
| template<std::size_t SmallStringSize_v> | ||||
| @@ -427,8 +426,7 @@ constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operato | ||||
|  | ||||
| template<std::size_t SmallStringSize_v> | ||||
| constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(Integer_c auto i) const noexcept { | ||||
| 	char str[65] = {}; | ||||
| 	ox::itoa(i, str); | ||||
| 	auto const str = ox::itoa(i); | ||||
| 	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 {}; | ||||
| } | ||||
|  | ||||
| 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]] | ||||
| constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept { | ||||
| 	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)); | ||||
| 	private: | ||||
| 		ox::Array<AllocAlias<T>, Size> m_data = {}; | ||||
| 		Allocator m_allocator; | ||||
| 	protected: | ||||
| 		constexpr 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 { | ||||
| 			// small vector optimization cannot be done it constexpr, but it doesn't really matter in constexpr | ||||
| 			if (std::is_constant_evaluated() || cap > Size) { | ||||
| 				*items = m_allocator.allocate(cap); | ||||
| 				*items = Allocator{}.allocate(cap); | ||||
| 			} else { | ||||
| 				*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 | ||||
| 			if (std::is_constant_evaluated()) { | ||||
| 				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> | ||||
| struct VectorAllocator<T, Allocator, 0> { | ||||
| 	private: | ||||
| 		Allocator m_allocator; | ||||
| 	protected: | ||||
| 		constexpr VectorAllocator() noexcept = default; | ||||
| 		constexpr VectorAllocator(const VectorAllocator&) noexcept = default; | ||||
| 		constexpr VectorAllocator(VectorAllocator&&) noexcept = default; | ||||
|  | ||||
| 		constexpr void allocate(T **items, std::size_t cap) noexcept { | ||||
| 			*items = m_allocator.allocate(cap); | ||||
| 			*items = Allocator{}.allocate(cap); | ||||
| 		} | ||||
|  | ||||
| 		[[maybe_unused]] | ||||
| @@ -121,7 +118,7 @@ struct VectorAllocator<T, Allocator, 0> { | ||||
|  | ||||
| 		constexpr void deallocate(T *items, std::size_t cap) noexcept { | ||||
| 			if (items) { | ||||
| 				m_allocator.deallocate(items, cap); | ||||
| 				Allocator{}.deallocate(items, cap); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user