43 static std::string ToLower(std::string_view str) {
44 return str | std::ranges::views::transform([](
char c) {
return std::tolower(c); }) |
45 std::ranges::to<std::string>();
48 static std::string ToUpper(std::string_view str) {
49 return str | std::ranges::views::transform([](
char c) {
return std::toupper(c); }) |
50 std::ranges::to<std::string>();
53 static bool EqualsIgnoreCase(std::string_view lhs, std::string_view rhs) {
54 return std::ranges::equal(
55 lhs, rhs, [](
char lc,
char rc) {
return std::tolower(lc) == std::tolower(rc); });
58 static bool StartsWithIgnoreCase(std::string_view str, std::string_view prefix) {
59 if (str.size() < prefix.size()) {
62 return EqualsIgnoreCase(str.substr(0, prefix.size()), prefix);
69 if ((i & 0xC0) != 0x80) {
77 requires std::is_arithmetic_v<T> &&
FromChars<T> && (!std::same_as<T, bool>)
78 static Result<T> ParseNumber(std::string_view str) {
80 auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value);
81 if (ec == std::errc()) [[likely]] {
82 if (ptr != str.data() + str.size()) {
83 return InvalidArgument(
"Failed to parse {} from string '{}': trailing characters",
84 typeid(T).name(), str);
88 if (ec == std::errc::invalid_argument) {
89 return InvalidArgument(
"Failed to parse {} from string '{}': invalid argument",
90 typeid(T).name(), str);
92 if (ec == std::errc::result_out_of_range) {
93 return InvalidArgument(
"Failed to parse {} from string '{}': value out of range",
94 typeid(T).name(), str);
101 static Result<std::vector<uint8_t>> HexStringToBytes(std::string_view hex);
103 template <
typename T>
104 requires std::is_floating_point_v<T> && (!FromChars<T>)
105 static Result<T> ParseNumber(std::string_view str) {
108 std::string owned(str);
109 const char* start = owned.c_str();
113 if constexpr (std::same_as<T, float>) {
114 value = std::strtof(start, &end);
115 }
else if constexpr (std::same_as<T, double>) {
116 value = std::strtod(start, &end);
118 value = std::strtold(start, &end);
121 if (end == start || end != start +
static_cast<std::ptrdiff_t
>(owned.size())) {
122 return InvalidArgument(
"Failed to parse {} from string '{}': invalid argument",
123 typeid(T).name(), str);
125 if (errno == ERANGE) {
126 return InvalidArgument(
"Failed to parse {} from string '{}': value out of range",
127 typeid(T).name(), str);