mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-18 14:25:38 +00:00
StringUtil: Add base support and hexadecimal functions
This commit is contained in:
parent
fd39f09aa7
commit
9bd28f39a5
|
@ -2,6 +2,7 @@
|
|||
#include <cctype>
|
||||
#include <codecvt>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef WIN32
|
||||
#include "windows_headers.h"
|
||||
|
@ -163,6 +164,33 @@ std::size_t Strlcpy(char* dst, const std::string_view& src, std::size_t size)
|
|||
return len;
|
||||
}
|
||||
|
||||
std::optional<std::vector<u8>> DecodeHex(const std::string_view& in)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
data.reserve(in.size()/2);
|
||||
|
||||
for (int i = 0; i < in.size()/2; i++) {
|
||||
auto byte = StringUtil::FromChars<u8>(in.substr(i*2, 2), 16);
|
||||
if (byte) {
|
||||
data.push_back(*byte);
|
||||
}
|
||||
else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
return { data };
|
||||
}
|
||||
|
||||
std::string EncodeHex(const u8* data, int length)
|
||||
{
|
||||
std::stringstream ss;
|
||||
for (int i = 0; i < length; i++) {
|
||||
ss << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(data[i]);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
std::wstring UTF8StringToWideString(const std::string_view& str)
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__has_include) && __has_include(<charconv>)
|
||||
#include <charconv>
|
||||
|
@ -52,16 +54,37 @@ static inline int Strncasecmp(const char* s1, const char* s2, std::size_t n)
|
|||
}
|
||||
|
||||
/// Wrapper arond std::from_chars
|
||||
template<typename T>
|
||||
inline std::optional<T> FromChars(const std::string_view& str)
|
||||
template<typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
|
||||
inline std::optional<T> FromChars(const std::string_view& str, int base = 10)
|
||||
{
|
||||
T value;
|
||||
|
||||
#if defined(__has_include) && __has_include(<charconv>)
|
||||
const std::from_chars_result result = std::from_chars(str.data(), str.data() + str.length(), value, base);
|
||||
if (result.ec != std::errc())
|
||||
return std::nullopt;
|
||||
#else
|
||||
std::string temp(str);
|
||||
std::istringstream ss(temp);
|
||||
ss >> std::setbase(base) >> value;
|
||||
if (ss.fail())
|
||||
return std::nullopt;
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
|
||||
inline std::optional<T> FromChars(const std::string_view& str)
|
||||
{
|
||||
T value;
|
||||
|
||||
#if defined(__has_include) && __has_include(<charconv>) && defined(_MSC_VER)
|
||||
const std::from_chars_result result = std::from_chars(str.data(), str.data() + str.length(), value);
|
||||
if (result.ec != std::errc())
|
||||
return std::nullopt;
|
||||
#else
|
||||
/// libstdc++ does not support from_chars with floats yet
|
||||
std::string temp(str);
|
||||
std::istringstream ss(temp);
|
||||
ss >> value;
|
||||
|
@ -74,7 +97,7 @@ inline std::optional<T> FromChars(const std::string_view& str)
|
|||
|
||||
/// Explicit override for booleans
|
||||
template<>
|
||||
inline std::optional<bool> FromChars(const std::string_view& str)
|
||||
inline std::optional<bool> FromChars(const std::string_view& str, int base)
|
||||
{
|
||||
if (Strncasecmp("true", str.data(), str.length()) == 0 || Strncasecmp("yes", str.data(), str.length()) == 0 ||
|
||||
Strncasecmp("on", str.data(), str.length()) == 0 || Strncasecmp("1", str.data(), str.length()) == 0)
|
||||
|
@ -91,21 +114,9 @@ inline std::optional<bool> FromChars(const std::string_view& str)
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
/// from_chars doesn't seem to work with floats on gcc
|
||||
template<>
|
||||
inline std::optional<float> FromChars(const std::string_view& str)
|
||||
{
|
||||
float value;
|
||||
std::string temp(str);
|
||||
std::istringstream ss(temp);
|
||||
ss >> value;
|
||||
if (ss.fail())
|
||||
return std::nullopt;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
/// Encode/decode hexadecimal byte buffers
|
||||
std::optional<std::vector<u8>> DecodeHex(const std::string_view& str);
|
||||
std::string EncodeHex(const u8* data, int length);
|
||||
|
||||
/// starts_with from C++20
|
||||
ALWAYS_INLINE static bool StartsWith(const std::string_view& str, const char* prefix)
|
||||
|
|
Loading…
Reference in a new issue