27template<
typename ObjType>
30 { obj.toString() } -> std::convertible_to<std::string_view>;
35#define PH_DEFINE_INLINE_TO_STRING_FORMATTER_SPECIALIZATION(...)\
36 struct std::formatter<__VA_ARGS__> : std::formatter<std::string>\
38 static_assert(::ph::string_utils::CHasToString<__VA_ARGS__>,\
39 "type " #__VA_ARGS__ " must have a const method toString() and the result should be "\
40 "implicitly convertible to std::string"); \
45 inline auto format(const __VA_ARGS__& value, std::format_context& ctx) const\
47 return std::formatter<std::string>::format(\
48 value.toString(), ctx);\
64#define PH_DEFINE_INLINE_TO_STRING_FORMATTER(...)\
66 PH_DEFINE_INLINE_TO_STRING_FORMATTER_SPECIALIZATION(__VA_ARGS__)
82#define PH_DEFINE_INLINE_TO_STRING_FORMATTER_TEMPLATE(...)\
83 PH_DEFINE_INLINE_TO_STRING_FORMATTER_SPECIALIZATION(__VA_ARGS__)
97template<EWhitespace TYPE = EWhitespace::Common>
111 "Must include a case for each enum entry; did you forget to add one?");
117template<EWhitespace TYPE = EWhitespace::Common>
123inline bool has_any_of(
const std::string_view srcStr,
const std::string_view candidates)
125 const auto foundPos = srcStr.find_first_of(candidates);
126 return foundPos != std::string_view::npos;
129inline bool has_none_of(
const std::string_view srcStr,
const std::string_view candidates)
143inline std::string_view
cut_head(
const std::string_view srcStr,
const std::string_view candidates)
145 const auto nonCutPos = srcStr.find_first_not_of(candidates);
147 auto cutStr = srcStr;
151 cutStr.remove_prefix(
152 nonCutPos != std::string_view::npos ? nonCutPos : srcStr.size());
166inline std::string_view
cut_tail(
const std::string_view srcStr,
const std::string_view candidates)
168 const auto nonCutPos = srcStr.find_last_not_of(candidates);
170 auto cutStr = srcStr;
175 cutStr.remove_suffix(
176 nonCutPos != std::string_view::npos ? srcStr.size() - 1 - nonCutPos : srcStr.size());
190inline std::string_view
cut_ends(
const std::string_view srcStr,
const std::string_view candidates)
200template<EWhitespace TYPE = EWhitespace::Common>
201inline std::string_view
trim_head(
const std::string_view srcStr)
211template<EWhitespace TYPE = EWhitespace::Common>
212inline std::string_view
trim_tail(
const std::string_view srcStr)
222template<EWhitespace TYPE = EWhitespace::Common>
223inline std::string_view
trim(
const std::string_view srcStr)
236 std::string_view srcStr,
237 std::string_view*
const out_remainingStr =
nullptr,
240 srcStr =
cut_head(srcStr, tokenSeparators);
242 const auto separatorPos = srcStr.find_first_of(tokenSeparators);
243 if(separatorPos != std::string_view::npos)
245 const auto nextToken = srcStr.substr(0, separatorPos);
249 *out_remainingStr = srcStr.substr(separatorPos + 1);
269 const auto mappedCharIdx =
static_cast<unsigned char>(ch);
282 const auto mappedCharIdx =
static_cast<unsigned char>(ch);
318inline std::string
repeat(
const std::string_view str,
const std::size_t n)
320 const std::size_t totalSize = str.size() * n;
324 result.reserve(totalSize);
325 for(std::size_t i = 0; i < n; ++i)
337 str.erase(std::remove(str.begin(), str.end(), ch), str.end());
340namespace detail_from_to_char
352 constexpr std::errc NO_ERROR_VALUE = std::errc();
359 case std::errc::invalid_argument:
361 "input cannot be interpreted as a numeric value");
363 case std::errc::result_out_of_range:
365 "result will overflow the arithmetic type");
367 case std::errc::value_too_large:
369 "result cannot fit in the output buffer");
373 "unknown error: std::errc = " + std::to_string(
374 static_cast<std::underlying_type_t<std::errc>
>(errorCode)));
386 static_assert(std::is_floating_point_v<T>,
387 "parse_float() accepts only floating point type.");
390 const std::string_view floatStrNoLeadingWS =
trim_head(floatStr);
393 const std::from_chars_result result = std::from_chars(
394 floatStrNoLeadingWS.data(),
395 floatStrNoLeadingWS.data() + floatStrNoLeadingWS.size(),
413 static_assert(std::is_integral_v<T>,
414 "parse_int() accepts only integer type.");
420 if(intStr.starts_with(
"0x"))
425 intStr.remove_prefix(2);
429 using IntType = std::conditional_t<std::is_same_v<T, bool>,
unsigned char, T>;
431 std::remove_const_t<IntType> intValue;
432 const std::from_chars_result result = std::from_chars(
434 intStr.data() + intStr.size(),
440 return static_cast<T
>(intValue);
446template<
typename NumberType>
449 if constexpr(std::is_floating_point_v<NumberType>)
455 static_assert(std::is_integral_v<NumberType>);
475inline std::size_t
stringify_float(
const T value,
char*
const out_buffer,
const std::size_t bufferSize)
480 static_assert(std::is_floating_point_v<T>,
481 "stringify_float() accepts only floating point type.");
486 const std::to_chars_result result = std::to_chars(
488 out_buffer + bufferSize,
494 PH_ASSERT(out_buffer < result.ptr && result.ptr <= out_buffer + bufferSize);
495 return static_cast<std::size_t
>(result.ptr - out_buffer);
508template<std::
integral T>
511 char*
const out_buffer,
512 const std::size_t bufferSize,
520 using IntType = std::conditional_t<std::is_same_v<T, bool>,
unsigned char, T>;
521 auto intValue =
static_cast<std::remove_const_t<IntType>
>(value);
523 std::size_t numCharsWritten = 0;
526 if constexpr(std::is_signed_v<T>)
533 intValue = -intValue;
538 std::array<
unsigned char,
sizeof(IntType) * CHAR_BIT> tmpBuffer;
539 auto tmpBufferEnd = tmpBuffer.end();
546 }
while(intValue > 0);
548 auto numDigits = tmpBuffer.end() - tmpBufferEnd;
549 if(numCharsWritten + numDigits > bufferSize)
552 "result cannot fit in the output buffer: need={}, given={}",
553 numCharsWritten + numDigits, bufferSize);
557 std::copy(tmpBufferEnd, tmpBuffer.end(), out_buffer + numCharsWritten);
558 numCharsWritten += numDigits;
561 return numCharsWritten;
574template<std::
integral T>
577 char*
const out_buffer,
578 const std::size_t bufferSize,
584 if(2 <= base && base <= 36)
590 using IntType = std::conditional_t<std::is_same_v<T, bool>,
unsigned char, T>;
591 const auto intValue =
static_cast<IntType
>(value);
593 std::to_chars_result result = std::to_chars(
595 out_buffer + bufferSize,
602 PH_ASSERT(out_buffer < result.ptr && result.ptr <= out_buffer + bufferSize);
603 return static_cast<std::size_t
>(result.ptr - out_buffer);
616template<
typename NumberType>
618 const NumberType value,
619 char*
const out_buffer,
620 const std::size_t bufferSize)
622 if constexpr(std::is_floating_point_v<NumberType>)
628 static_assert(std::is_integral_v<NumberType>);
641template<
typename NumberType>
643 const NumberType value,
644 std::string& out_str,
645 const std::size_t maxChars = 64)
647 const auto originalSize = out_str.size();
648 out_str.resize(originalSize + maxChars);
651 value, out_str.data() + originalSize, maxChars);
653 out_str.resize(originalSize + newSize);
663template<
typename NumberType>
665 const NumberType value,
666 const std::size_t maxChars = 64)
#define PH_ASSERT_GE(a, b)
Definition assertion.h:67
#define PH_ASSERT_IN_RANGE_INCLUSIVE(value, lowerBound, upperBound)
Similar to PH_ASSERT_IN_RANGE(3), except the bounds are inclusive.
Definition assertion.h:80
#define PH_ASSERT(condition)
Definition assertion.h:49
Definition exceptions.h:67
Definition exceptions.h:73
Definition exceptions.h:49
General exception thrown on runtime error.
Definition exceptions.h:21
Definition string_utils.h:28
void throw_from_std_errc_if_has_error(const std::errc errorCode)
Definition string_utils.h:343
constexpr std::array< unsigned char, 256 > ASCII_TO_UPPER
Definition string_utils_table.h:26
constexpr std::array< unsigned char, 256 > ASCII_TO_LOWER
Definition string_utils_table.h:67
constexpr std::array< unsigned char, 62 > BASE62_DIGITS
Definition string_utils_table.h:103
constexpr std::string_view common_whitespaces
Commonly used whitespace characters.
Definition string_utils_table.h:13
constexpr std::string_view standard_whitespaces
Standard whitespace characters.
Definition string_utils_table.h:19
Contains various string manipulation helpers.
Definition string_utils.h:25
std::string_view trim_head(const std::string_view srcStr)
Remove white spaces from the beginning.
Definition string_utils.h:201
std::size_t stringify_int(const T value, char *const out_buffer, const std::size_t bufferSize, const int base=10)
Converts an integer to string.
Definition string_utils.h:575
std::string_view trim_tail(const std::string_view srcStr)
Remove white spaces from the end.
Definition string_utils.h:212
char az_to_AZ(const char ch)
Convert lower-case characters to upper-case.
Definition string_utils.h:265
bool has_any_of(const std::string_view srcStr, const std::string_view candidates)
Definition string_utils.h:123
std::string_view trim(const std::string_view srcStr)
Remove white spaces from both ends.
Definition string_utils.h:223
T parse_float(const std::string_view floatStr)
Returns a float by processing its string representation. Supports float, double, and long double.
Definition string_utils.h:384
void erase_all(std::string &str, const char ch)
Remove all occurrence of a character in the string.
Definition string_utils.h:335
std::string_view cut_head(const std::string_view srcStr, const std::string_view candidates)
Remove characters from the beginning.
Definition string_utils.h:143
std::string_view cut_tail(const std::string_view srcStr, const std::string_view candidates)
Remove characters from the end.
Definition string_utils.h:166
constexpr bool is_whitespace(const char ch)
Definition string_utils.h:118
T parse_int(std::string_view intStr)
Returns an integer by processing its string representation. Supports the following:
Definition string_utils.h:409
std::string repeat(const std::string_view str, const std::size_t n)
Repeat the input string for N times.
Definition string_utils.h:318
EWhitespace
Definition string_utils.h:89
char AZ_to_az(const char ch)
Convert upper-case characters to lower-case.
Definition string_utils.h:278
std::string_view cut_ends(const std::string_view srcStr, const std::string_view candidates)
Remove characters from both ends.
Definition string_utils.h:190
std::string_view get_whitespaces()
Definition string_utils.h:98
std::size_t stringify_int_alphabetic(const T value, char *const out_buffer, const std::size_t bufferSize, const int base)
Converts an integer to base [2, 62] string.
Definition string_utils.h:509
bool has_none_of(const std::string_view srcStr, const std::string_view candidates)
Definition string_utils.h:129
std::string_view next_token(std::string_view srcStr, std::string_view *const out_remainingStr=nullptr, const std::string_view tokenSeparators=get_whitespaces<>())
Retrieve a token from a string.
Definition string_utils.h:235
NumberType parse_number(const std::string_view numberStr)
Returns a number by processing its string representation. Accepts all types supported by parse_float(...
Definition string_utils.h:447
std::size_t stringify_float(const T value, char *const out_buffer, const std::size_t bufferSize)
Converts a float to string.
Definition string_utils.h:475
std::size_t stringify_number(const NumberType value, char *const out_buffer, const std::size_t bufferSize)
Converts a number to string. Accepts all types supported by stringify_float(T, char*,...
Definition string_utils.h:617
void throw_formatted(const std::format_string< Args... > msgFormat, Args &&... args)
Definition exceptions.h:85