1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
#ifndef COMPONENTS_MISC_STRINGS_CONVERSION_H
#define COMPONENTS_MISC_STRINGS_CONVERSION_H
#include <charconv>
#include <cstdint>
#include <optional>
#include <string>
#include <system_error>
#if !(defined(_MSC_VER) && (_MSC_VER >= 1924)) && !(defined(__GNUC__) && __GNUC__ >= 11) || defined(__clang__) \
|| defined(__apple_build_version__)
#include <ios>
#include <locale>
#include <sstream>
#endif
namespace Misc::StringUtils
{
inline const char* u8StringToString(const char8_t* str)
{
return reinterpret_cast<const char*>(str);
}
inline char* u8StringToString(char8_t* str)
{
return reinterpret_cast<char*>(str);
}
inline std::string u8StringToString(std::u8string_view str)
{
return { str.begin(), str.end() };
}
inline std::string u8StringToString(std::u8string&& str)
{
return { str.begin(), str.end() };
}
inline const char8_t* stringToU8String(const char* str)
{
return reinterpret_cast<const char8_t*>(
str); // Undefined behavior if the contents of "char" aren't UTF8 or ASCII.
}
inline char8_t* stringToU8String(char* str)
{
return reinterpret_cast<char8_t*>(str); // Undefined behavior if the contents of "char" aren't UTF8 or ASCII.
}
inline std::u8string stringToU8String(std::string_view str)
{
return { str.begin(), str.end() }; // Undefined behavior if the contents of "char" aren't UTF8 or ASCII.
}
inline std::u8string stringToU8String(std::string&& str)
{
return { str.begin(), str.end() }; // Undefined behavior if the contents of "char" aren't UTF8 or ASCII.
}
template <typename T>
inline std::optional<T> toNumeric(std::string_view s)
{
T result{};
auto [ptr, ec]{ std::from_chars(s.data(), s.data() + s.size(), result) };
if (ec == std::errc())
{
return result;
}
return std::nullopt;
}
template <typename T>
inline T toNumeric(std::string_view s, T defaultValue)
{
if (auto numeric = toNumeric<T>(s))
{
return *numeric;
}
return defaultValue;
}
// support for std::from_chars as of 2023-02-27
// - Visual Studio 2019 version 16.4 (1924)
// - GCC 11
// - Clang does not support floating points yet
// - Apples Clang does not support floating points yet
#if !(defined(_MSC_VER) && (_MSC_VER >= 1924)) && !(defined(__GNUC__) && __GNUC__ >= 11) || defined(__clang__) \
|| defined(__apple_build_version__)
template <>
inline std::optional<float> toNumeric<float>(std::string_view s)
{
if (!s.empty())
{
std::istringstream iss(s.data());
iss.imbue(std::locale::classic());
float value;
if (iss >> value)
{
return value;
}
}
return std::nullopt;
}
template <>
inline std::optional<double> toNumeric<double>(std::string_view s)
{
if (!s.empty())
{
std::istringstream iss(s.data());
iss.imbue(std::locale::classic());
double value;
if (iss >> value)
{
return value;
}
}
return std::nullopt;
}
#endif
inline std::string toHex(std::string_view value)
{
std::string buffer(value.size() * 2, '0');
char* out = buffer.data();
for (const char v : value)
{
const std::ptrdiff_t space = static_cast<std::ptrdiff_t>(static_cast<std::uint8_t>(v) <= 0xf);
const auto [ptr, ec] = std::to_chars(out + space, out + space + 2, static_cast<std::uint8_t>(v), 16);
if (ec != std::errc())
throw std::system_error(std::make_error_code(ec));
out += 2;
}
return buffer;
}
}
#endif // COMPONENTS_MISC_STRINGS_CONVERSION_H
|