IceShard 1
A personal game engine project, with development focused on 2D/2.5D games.
Loading...
Searching...
No Matches
string_utils.hxx
Go to the documentation of this file.
1
3
4#pragma once
5#include <ice/string.hxx>
7#include <ice/heap_string.hxx>
9#include <ice/expected.hxx>
10#include <ice/math.hxx>
11#include <charconv>
12#include <numeric>
13
14namespace ice
15{
16
17 namespace string
18 {
19
20 template<typename Fn>
21 constexpr auto for_each_split(
22 ice::String contents,
23 ice::String separators,
24 Fn&& fn
25 ) noexcept -> ice::u32;
26
27 } // namespace string
28
29 enum class CaseSensitive : bool { No, Yes };
30 enum class CompareResult : ice::i8 { Smaller = -1, Equal = 0, Larger = 1 };
33
37
41
42 template<typename StrType>
44 {
46 StrType remaining;
47
48 constexpr operator bool() const noexcept
49 {
50 return ec;
51 }
52 };
53
54 template<typename T>
55 requires (std::is_integral_v<T> || std::is_floating_point_v<T>)
56 auto from_chars(ice::String str, T& out_value) noexcept -> ice::FromCharsResult<ice::String>
57 {
59 std::from_chars_result fc_res;
60 if constexpr (std::is_integral_v<T>)
61 {
62 fc_res = std::from_chars(
63 str.begin(),
64 str.end(),
65 out_value
66 );
67 }
68 else
69 {
70#if ISP_COMPILER_CLANG < 20 || ISP_WEBAPP || ISP_ANDROID
71 // Because Libc++ did not support from_chars for floats up until clang.20 we need to use the old C style approach...
72 // We don't try to handle errors in this version.
73 fc_res.ec = std::errc{};
74 char* ptr_end = nullptr; // Why the hell is this a char ptr?
75 out_value = strtof(str.begin(), &ptr_end);
76 ICE_ASSERT_CORE(ice::ptr_distance(str.begin(), ptr_end).value <= str.size());
77 fc_res.ptr = ptr_end;
78#else
79 fc_res = std::from_chars(
80 str.begin(),
81 str.end(),
82 out_value,
83 std::chars_format::general
84 );
85#endif
86 }
87
88 if (fc_res.ec == std::errc::result_out_of_range)
89 {
91 }
92 else if (fc_res.ec == std::errc::invalid_argument)
93 {
95 }
96
97 return {
98 .ec = res,
99 .remaining = ice::String{ fc_res.ptr, str.end() }
100 };
101 }
102
103 template<typename T>
104 requires (std::is_integral_v<T> || std::is_floating_point_v<T>)
105 auto from_chars(char const* str_beg, char const* str_end, T& out_value) noexcept -> ice::FromCharsResult<char const*>
106 {
108 std::from_chars_result fc_res;
109 if constexpr (std::is_integral_v<T>)
110 {
111 fc_res = std::from_chars(str_beg, str_end, out_value);
112 }
113 else
114 {
115#if ISP_COMPILER_CLANG < 20 || ISP_WEBAPP || ISP_ANDROID
116 // Because Libc++ did not support from_chars for floats up until clang.20 we need to use the old C style approach...
117 // We don't try to handle errors in this version.
118 fc_res.ec = std::errc{};
119 char* ptr_end = nullptr; // Why the hell is this a char ptr?
120 out_value = strtof(str_beg, &ptr_end);
121 ICE_ASSERT_CORE(ice::ptr_distance(str_beg, ptr_end) <= ice::ptr_distance(str_beg, str_end));
122 fc_res.ptr = ptr_end;
123#else
124 fc_res = std::from_chars(str_beg, str_end, out_value, std::chars_format::general);
125#endif
126 }
127
128 if (fc_res.ec == std::errc::result_out_of_range)
129 {
130 res = ice::E_OutOfRange;
131 }
132 else if (fc_res.ec == std::errc::invalid_argument)
133 {
135 }
136
137 return {
138 .ec = res,
139 .remaining = fc_res.ptr
140 };
141 }
142
143 template<typename T>
144 requires (std::is_integral_v<T> || std::is_floating_point_v<T>)
145 auto from_chars(ice::String str, ice::String& out_str, T& out_value) noexcept -> ice::ErrorCode
146 {
147 ice::FromCharsResult<ice::String> const result = ice::from_chars(str, out_value);
148 out_str = result.remaining;
149 return result.ec;
150 }
151
152 inline auto from_chars(ice::String str, bool& out_value) noexcept -> ice::FromCharsResult<ice::String>
153 {
154 int temp_out = 0;
155 ice::FromCharsResult<ice::String> const result = from_chars(str, temp_out);
156 if (result.ec == ice::S_Ok)
157 {
158 out_value = bool(temp_out);
159 }
160 return result;
161 }
162
163 inline auto from_chars(ice::String str, ice::String& out_str, bool& out_value) noexcept -> ice::ErrorCode
164 {
165 ice::FromCharsResult<ice::String> const result = ice::from_chars(str, out_value);
166 out_str = result.remaining;
167 return result.ec;
168 }
169
170 namespace string
171 {
172
173 template<typename Fn>
174 constexpr auto for_each_split(ice::String contents, ice::String separator, Fn&& fn) noexcept -> ice::u32
175 {
176 ice::u32 count = 0;
177 while(contents.not_empty())
178 {
179 count += 1;
180 ice::nindex const separator_pos = contents.find_first_of(separator);
181 ice::String const line = contents.substr(0, separator_pos);
182 if (ice::forward<Fn>(fn)(line) == false)
183 {
184 break;
185 }
186 contents = contents.substr(separator_pos + 1);
187 }
188 return count;
189 }
190
191 } // namespace string
192
193} // namespace ice
#define ICE_ASSERT_CORE(expression)
Definition assert_core.hxx:43
Definition path_utils.hxx:10
Definition editable_operations.hxx:9
constexpr auto for_each_split(ice::String contents, ice::String separators, Fn &&fn) noexcept -> ice::u32
Definition string_utils.hxx:174
SPDX-License-Identifier: MIT.
Definition array.hxx:12
ice::BasicString< char > String
Definition string.hxx:82
auto wide_to_utf8_size(ice::WString path) noexcept -> ice::u32
static constexpr ice::ErrorCode E_InvalidArgument
Definition error_codes.hxx:16
std::int8_t i8
Definition types.hxx:19
auto alloc(ice::usize size) noexcept -> ice::AllocResult
std::uint64_t u64
Definition types.hxx:27
ice::BasicString< wchar_t > WString
Definition string.hxx:83
auto ptr_distance(void const *ptr_from, void const *ptr_to) noexcept -> ice::usize
Definition mem_arithmetic.hxx:54
auto utf8_to_wide_size(ice::String path) noexcept -> ice::u32
constexpr auto count(T const (&)[Size]) noexcept -> ice::u32
Definition base.hxx:43
auto utf8_to_wide(ice::Allocator &alloc, ice::String path) noexcept -> ice::HeapString< ice::wchar >
CaseSensitive
Definition string_utils.hxx:29
@ Yes
Definition string_utils.hxx:29
@ No
Definition string_utils.hxx:29
std::uint32_t u32
Definition types.hxx:26
static constexpr ice::ErrorCode E_OutOfRange
Definition error_codes.hxx:17
bool utf8_to_wide_append(ice::String path, ice::HeapString< ice::wchar > &out_str) noexcept
CompareResult
Definition string_utils.hxx:30
@ Smaller
Definition string_utils.hxx:30
@ Larger
Definition string_utils.hxx:30
@ Equal
Definition string_utils.hxx:30
ice::AllocatorBase< ice::build::is_debug||ice::build::is_develop > Allocator
Definition mem_types.hxx:25
bool wide_to_utf8_append(ice::WString path, ice::HeapString<> &out_str) noexcept
static constexpr ice::ErrorCodeSuccess S_Ok
Definition error_codes.hxx:10
auto from_chars(ice::String str, T &out_value) noexcept -> ice::FromCharsResult< ice::String >
Definition string_utils.hxx:56
auto wide_to_utf8(ice::Allocator &alloc, ice::WString path) noexcept -> ice::HeapString<>
auto compare(ice::String left, ice::String right, ice::CaseSensitive=CaseSensitive::No) noexcept -> ice::CompareResult
constexpr auto size() const noexcept -> SizeType
Definition string.hxx:57
Definition error.hxx:19
Definition string_utils.hxx:44
StrType remaining
Definition string_utils.hxx:46
ice::ErrorCode ec
Definition string_utils.hxx:45
Definition heap_string.hxx:15
Definition nindex.hxx:13
constexpr auto end(this Self const &self) noexcept -> typename Self::ConstIterator
Definition readonly_operations.hxx:279
constexpr auto begin(this Self const &self) noexcept -> typename Self::ConstIterator
Definition readonly_operations.hxx:273