StringUtil: Add base support and hexadecimal functions

This commit is contained in:
Jean-Baptiste Boric 2020-12-10 22:42:04 +01:00 committed by Connor McLaughlin
parent fd39f09aa7
commit 9bd28f39a5
2 changed files with 57 additions and 18 deletions

View file

@ -2,6 +2,7 @@
#include <cctype> #include <cctype>
#include <codecvt> #include <codecvt>
#include <cstdio> #include <cstdio>
#include <sstream>
#ifdef WIN32 #ifdef WIN32
#include "windows_headers.h" #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; 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 #ifdef WIN32
std::wstring UTF8StringToWideString(const std::string_view& str) std::wstring UTF8StringToWideString(const std::string_view& str)

View file

@ -3,9 +3,11 @@
#include <cstdarg> #include <cstdarg>
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
#include <iomanip>
#include <optional> #include <optional>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <vector>
#if defined(__has_include) && __has_include(<charconv>) #if defined(__has_include) && __has_include(<charconv>)
#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 /// Wrapper arond std::from_chars
template<typename T> template<typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
inline std::optional<T> FromChars(const std::string_view& str) inline std::optional<T> FromChars(const std::string_view& str, int base = 10)
{ {
T value; T value;
#if defined(__has_include) && __has_include(<charconv>) #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); const std::from_chars_result result = std::from_chars(str.data(), str.data() + str.length(), value);
if (result.ec != std::errc()) if (result.ec != std::errc())
return std::nullopt; return std::nullopt;
#else #else
/// libstdc++ does not support from_chars with floats yet
std::string temp(str); std::string temp(str);
std::istringstream ss(temp); std::istringstream ss(temp);
ss >> value; ss >> value;
@ -74,7 +97,7 @@ inline std::optional<T> FromChars(const std::string_view& str)
/// Explicit override for booleans /// Explicit override for booleans
template<> 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 || 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) 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; return std::nullopt;
} }
#ifndef _MSC_VER /// Encode/decode hexadecimal byte buffers
/// from_chars doesn't seem to work with floats on gcc std::optional<std::vector<u8>> DecodeHex(const std::string_view& str);
template<> std::string EncodeHex(const u8* data, int length);
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
/// starts_with from C++20 /// starts_with from C++20
ALWAYS_INLINE static bool StartsWith(const std::string_view& str, const char* prefix) ALWAYS_INLINE static bool StartsWith(const std::string_view& str, const char* prefix)