11#pragma once
22
3- #include < algorithm>
4- #include < cctype>
53#include < charconv>
6- #include < cstddef >
4+ #include < climits >
75#include < cstdint>
8- #include < cstring>
96#include < iterator>
10- #include < string>
117#include < string_view>
12- #include < type_traits>
13- #include < utility>
148
15- #include < tsl/ordered_map.h>
16-
17- #include < range/v3/range/conversion.hpp>
18- #include < range/v3/view/join.hpp>
19- #include < range/v3/view/transform.hpp>
20-
21- #include " openvic-simulation/utility/Containers.hpp"
22-
23- namespace OpenVic ::StringUtils {
9+ namespace OpenVic {
2410 template <typename T>
2511 [[nodiscard]] inline constexpr std::from_chars_result from_chars ( //
2612 char const * const first, char const * const last, T& raw_value, const int base = 10
@@ -61,29 +47,29 @@ namespace OpenVic::StringUtils {
6147 }
6248 }
6349
64- using unsigned_t = std::make_unsigned_t <T>;
50+ using unsigned_type = std::make_unsigned_t <T>;
6551
66- [[maybe_unused]] constexpr unsigned_t uint_max = static_cast <unsigned_t >(-1 );
67- [[maybe_unused]] constexpr unsigned_t int_max = static_cast <unsigned_t >(uint_max >> 1 );
68- [[maybe_unused]] constexpr unsigned_t abs_int_min = static_cast <unsigned_t >(int_max + 1 );
52+ [[maybe_unused]] constexpr unsigned_type uint_max = static_cast <unsigned_type >(-1 );
53+ [[maybe_unused]] constexpr unsigned_type int_max = static_cast <unsigned_type >(uint_max >> 1 );
54+ [[maybe_unused]] constexpr unsigned_type abs_int_min = static_cast <unsigned_type >(int_max + 1 );
6955
70- unsigned_t risky_val;
71- unsigned_t max_digit;
56+ unsigned_type risky_val;
57+ unsigned_type max_digit;
7258
7359 if constexpr (std::is_signed_v<T>) {
7460 if (minus_sign) {
75- risky_val = static_cast <unsigned_t >(abs_int_min / base);
76- max_digit = static_cast <unsigned_t >(abs_int_min % base);
61+ risky_val = static_cast <unsigned_type >(abs_int_min / base);
62+ max_digit = static_cast <unsigned_type >(abs_int_min % base);
7763 } else {
78- risky_val = static_cast <unsigned_t >(int_max / base);
79- max_digit = static_cast <unsigned_t >(int_max % base);
64+ risky_val = static_cast <unsigned_type >(int_max / base);
65+ max_digit = static_cast <unsigned_type >(int_max % base);
8066 }
8167 } else {
82- risky_val = static_cast <unsigned_t >(uint_max / base);
83- max_digit = static_cast <unsigned_t >(uint_max % base);
68+ risky_val = static_cast <unsigned_type >(uint_max / base);
69+ max_digit = static_cast <unsigned_type >(uint_max % base);
8470 }
8571
86- unsigned_t value = 0 ;
72+ unsigned_type value = 0 ;
8773
8874 bool overflowed = false ;
8975
@@ -96,7 +82,7 @@ namespace OpenVic::StringUtils {
9682
9783 if (value < risky_val // never overflows
9884 || (value == risky_val && digit <= max_digit)) { // overflows for certain digits
99- value = static_cast <unsigned_t >(value * base + digit);
85+ value = static_cast <unsigned_type >(value * base + digit);
10086 } else { // value > risky_val always overflows
10187 overflowed = true ; // keep going, next still needs to be updated, value is now irrelevant
10288 }
@@ -112,7 +98,7 @@ namespace OpenVic::StringUtils {
11298
11399 if constexpr (std::is_signed_v<T>) {
114100 if (minus_sign) {
115- value = static_cast <unsigned_t >(0 - value);
101+ value = static_cast <unsigned_type >(0 - value);
116102 }
117103 }
118104
@@ -136,9 +122,9 @@ namespace OpenVic::StringUtils {
136122 };
137123 static_assert (std::size (digits) == 36 );
138124
139- using _unsigned = std::make_unsigned_t <T>;
125+ using unsigned_type = std::make_unsigned_t <T>;
140126
141- _unsigned value = static_cast <_unsigned >(raw_value);
127+ unsigned_type value = static_cast <unsigned_type >(raw_value);
142128
143129 if constexpr (std::is_signed_v<T>) {
144130 if (raw_value < 0 ) {
@@ -148,26 +134,26 @@ namespace OpenVic::StringUtils {
148134
149135 *first++ = ' -' ;
150136
151- value = static_cast <_unsigned >(0 - value);
137+ value = static_cast <unsigned_type >(0 - value);
152138 }
153139 }
154140
155- constexpr std::size_t buffer_size = sizeof (_unsigned ) * CHAR_BIT; // enough for base 2
141+ constexpr std::size_t buffer_size = sizeof (unsigned_type ) * CHAR_BIT; // enough for base 2
156142 char buffer[buffer_size];
157143 char * const buffer_end = buffer + buffer_size;
158144 char * r_next = buffer_end;
159145
160146 switch (base) {
161147 case 10 : { // Derived from _UIntegral_to_buff()
162148 // Performance note: Ryu's digit table should be faster here.
163- constexpr bool use_chunks = sizeof (_unsigned ) > sizeof (size_t );
149+ constexpr bool use_chunks = sizeof (unsigned_type ) > sizeof (size_t );
164150
165151 if constexpr (use_chunks) { // For 64-bit numbers on 32-bit platforms, work in chunks to avoid 64-bit
166- // divisions.
152+ // divisions.
167153 while (value > 0xFFFF'FFFFU ) {
168154 // Performance note: Ryu's division workaround would be faster here.
169155 unsigned long chunk = static_cast <unsigned long >(value % 1'000'000'000 );
170- value = static_cast <_unsigned >(value / 1'000'000'000 );
156+ value = static_cast <unsigned_type >(value / 1'000'000'000 );
171157
172158 for (int _Idx = 0 ; _Idx != 9 ; ++_Idx) {
173159 *--r_next = static_cast <char >(' 0' + chunk % 10 );
@@ -176,9 +162,9 @@ namespace OpenVic::StringUtils {
176162 }
177163 }
178164
179- using Truncated = std::conditional_t <use_chunks, unsigned long , _unsigned >;
165+ using truncated_type = std::conditional_t <use_chunks, unsigned long , unsigned_type >;
180166
181- Truncated trunc = static_cast <Truncated >(value);
167+ truncated_type trunc = static_cast <truncated_type >(value);
182168
183169 do {
184170 *--r_next = static_cast <char >(' 0' + trunc % 10 );
@@ -225,7 +211,7 @@ namespace OpenVic::StringUtils {
225211 default :
226212 do {
227213 *--r_next = digits[value % base];
228- value = static_cast <_unsigned >(value / base);
214+ value = static_cast <unsigned_type >(value / base);
229215 } while (value != 0 );
230216 break ;
231217 }
@@ -250,11 +236,12 @@ namespace OpenVic::StringUtils {
250236 };
251237 // [neargye] constexpr copy chars. P1944 fix this?
252238 trivial_copy (first, r_next, static_cast <size_t >(digits_written));
253-
239+
254240
255241 return { first + digits_written, std::errc {} };
256242 }
257243
244+
258245 /* The constexpr function 'string_to_uint64' will convert a string into a uint64_t integer value.
259246 * The function takes four parameters: the input string (as a pair of pointers marking the start and
260247 * end of the string), the value reference to assign, and the base for numerical conversion.
@@ -263,7 +250,8 @@ namespace OpenVic::StringUtils {
263250 * still starts with "0", otherwise 10. The std::from_chars_result return value is used to report whether
264251 * or not conversion was successful.
265252 */
266- [[nodiscard]] inline constexpr std::from_chars_result string_to_uint64 (char const * str, char const * const end, uint64_t & value, int base = 10 ) {
253+ [[nodiscard]] inline constexpr std::from_chars_result
254+ string_to_uint64 (char const * str, char const * const end, uint64_t & value, int base = 10 ) {
267255 // If base is zero, base is determined by the string prefix.
268256 if (base == 0 ) {
269257 if (str && *str == ' 0' ) {
@@ -286,11 +274,15 @@ namespace OpenVic::StringUtils {
286274 return from_chars (str, end, value, base);
287275 }
288276
289- [[nodiscard]] inline constexpr std::from_chars_result string_to_uint64 (char const * const str, size_t length, uint64_t & value, int base = 10 ) {
277+ [[nodiscard]] inline constexpr std::from_chars_result string_to_uint64 ( //
278+ char const * const str, size_t length, std::uint64_t & value, int base = 10
279+ ) {
290280 return string_to_uint64 (str, str + length, value, base);
291281 }
292282
293- [[nodiscard]] inline constexpr std::from_chars_result string_to_uint64 (std::string_view str, uint64_t & value, int base = 10 ) {
283+ [[nodiscard]] inline constexpr std::from_chars_result string_to_uint64 ( //
284+ std::string_view str, std::uint64_t & value, int base = 10
285+ ) {
294286 return string_to_uint64 (str.data (), str.length (), value, base);
295287 }
296288
@@ -302,7 +294,9 @@ namespace OpenVic::StringUtils {
302294 * still starts with "0", otherwise 10. The std::from_chars_result return value is used to report whether
303295 * or not conversion was successful.
304296 */
305- [[nodiscard]] inline constexpr std::from_chars_result string_to_int64 (char const * str, char const * const end, int64_t & value, int base = 10 ) {
297+ [[nodiscard]] inline constexpr std::from_chars_result string_to_int64 ( //
298+ char const * str, char const * const end, std::int64_t & value, int base = 10
299+ ) {
306300 // If base is zero, base is determined by the string prefix.
307301 if (base == 0 ) {
308302 if (str && *str == ' 0' ) {
@@ -325,132 +319,15 @@ namespace OpenVic::StringUtils {
325319 return from_chars (str, end, value, base);
326320 }
327321
328- [[nodiscard]] inline constexpr std::from_chars_result string_to_int64 (char const * str, size_t length, int64_t & value, int base = 10 ) {
322+ [[nodiscard]] inline constexpr std::from_chars_result string_to_int64 ( //
323+ char const * str, size_t length, std::int64_t & value, int base = 10
324+ ) {
329325 return string_to_int64 (str, str + length, value, base);
330326 }
331327
332- [[nodiscard]] inline constexpr std::from_chars_result string_to_int64 (std::string_view str, int64_t & value, int base = 10 ) {
328+ [[nodiscard]] inline constexpr std::from_chars_result string_to_int64 ( //
329+ std::string_view str, std::int64_t & value, int base = 10
330+ ) {
333331 return string_to_int64 (str.data (), str.length (), value, base);
334332 }
335-
336- inline constexpr bool strings_equal_case_insensitive (std::string_view const & lhs, std::string_view const & rhs) {
337- if (lhs.size () != rhs.size ()) {
338- return false ;
339- }
340- constexpr auto ichar_equals = [](unsigned char l, unsigned char r) {
341- return std::tolower (l) == std::tolower (r);
342- };
343- return std::equal (lhs.begin (), lhs.end (), rhs.begin (), rhs.end (), ichar_equals);
344- }
345-
346- inline memory::string string_tolower (std::string_view str) {
347- memory::string result { str };
348- std::transform (result.begin (), result.end (), result.begin (),
349- [](unsigned char c) -> unsigned char { return std::tolower (c); }
350- );
351- return result;
352- }
353-
354- inline memory::string string_toupper (std::string_view str) {
355- memory::string result { str };
356- std::transform (result.begin (), result.end (), result.begin (),
357- [](unsigned char c) -> unsigned char { return std::toupper (c); }
358- );
359- return result;
360- }
361-
362- inline constexpr std::string_view bool_to_yes_no (bool b) {
363- return b ? " yes" : " no" ;
364- }
365-
366- inline constexpr std::string_view get_filename (std::string_view path) {
367- size_t pos = path.size ();
368- while (pos > 0 && path[pos - 1 ] != ' /' && path[pos - 1 ] != ' \\ ' ) {
369- --pos;
370- }
371- path.remove_prefix (pos);
372- return path;
373- }
374-
375- inline constexpr char const * get_filename (char const * filepath, char const * default_path = nullptr ) {
376- const std::string_view filename { get_filename (std::string_view { filepath }) };
377- if (!filename.empty ()) {
378- return filename.data ();
379- }
380- return default_path;
381- }
382-
383- inline memory::string make_forward_slash_path (std::string_view path) {
384- memory::string ret { path };
385- std::replace (ret.begin (), ret.end (), ' \\ ' , ' /' );
386- for (char & c : ret) {
387- if (c == ' \\ ' ) {
388- c = ' /' ;
389- }
390- }
391- return ret;
392- }
393-
394- inline constexpr std::string_view remove_leading_slashes (std::string_view path) {
395- size_t count = 0 ;
396- while (count < path.size () && (path[count] == ' /' || path[count] == ' \\ ' )) {
397- ++count;
398- }
399- path.remove_prefix (count);
400- return path;
401- }
402-
403- template <typename ... Args>
404- requires (std::is_same_v<std::string_view, Args> && ...)
405- inline memory::string _append_string_views (Args... args) {
406- memory::string ret;
407- ret.reserve ((args.size () + ...));
408- (ret.append (args), ...);
409- return ret;
410- }
411-
412- template <typename ... Args>
413- requires (std::is_convertible_v<Args, std::string_view> && ...)
414- inline memory::string append_string_views (Args... args) {
415- return _append_string_views (std::string_view { args }...);
416- }
417-
418- template <typename T, typename ... Args>
419- static memory::string string_join (tsl::ordered_map<memory::string, T, Args...> const & map, std::string_view delimiter = " , " ) {
420- if (map.empty ()) {
421- return " " ;
422- }
423-
424- static auto transformer = [](std::pair<std::string_view, T> const & pair) -> std::string_view {
425- return pair.first ;
426- };
427- return map | ranges::views::transform (transformer) | ranges::views::join (delimiter) | ranges::to<memory::string>();
428- }
429-
430- inline constexpr size_t get_extension_pos (std::string_view const & path) {
431- size_t pos = path.size ();
432- while (pos > 0 && path[--pos] != ' .' ) {}
433- return pos;
434- }
435-
436- inline constexpr std::string_view get_extension (std::string_view path) {
437- if (!path.empty ()) {
438- const size_t pos = get_extension_pos (path);
439- if (path[pos] == ' .' ) {
440- path.remove_prefix (pos);
441- return path;
442- }
443- }
444- return {};
445- }
446-
447- inline constexpr std::string_view remove_extension (std::string_view path) {
448- if (!path.empty ()) {
449- const size_t pos = get_extension_pos (path);
450- if (path[pos] == ' .' ) {
451- path.remove_suffix (path.size () - pos);
452- }
453- }
454- return path;
455- }
456333}
0 commit comments