3102 json lowercase hex (#4306)

* Made it possible to use lowercase hex numbers, also when encoding JSON (#3102)

Co-authored-by: Thomas Weyn <Thomas.Weyn@cebir.be>

* fix(JSONString): Remove deprecated toJSON functions #4305

* fix(NumericString): conversions inconsistencies #4304

---------

Co-authored-by: Archipel <thomas@weynwebworks.com>
Co-authored-by: Thomas Weyn <Thomas.Weyn@cebir.be>
This commit is contained in:
Aleksandar Fabijanic
2023-11-27 22:43:20 +01:00
committed by GitHub
parent 9141368eca
commit 57bc0bbbb5
13 changed files with 292 additions and 173 deletions

View File

@@ -38,37 +38,18 @@ enum JSONOptions
/// unicode characters will be escaped in the resulting
/// string.
JSON_WRAP_STRINGS = 4
JSON_WRAP_STRINGS = 4,
/// If specified, the object will preserve the items
/// insertion order. Otherwise, items will be sorted
/// by keys.
JSON_LOWERCASE_HEX = 8
/// If specified, all encoding happens with lowercase
/// HEX characters instead of capitals
};
//@ deprecated
void Foundation_API toJSON(const std::string& value, std::ostream& out, bool wrap = true);
/// Formats string value into the supplied output stream by
/// escaping control and ALL Unicode characters.
/// If wrap is true, the resulting string is enclosed in double quotes.
///
/// This function is deprecated, please use
///
/// void Poco::toJSON(const std::string&, std::ostream&, int)
//@ deprecated
std::string Foundation_API toJSON(const std::string& value, bool wrap = true);
/// Formats string value by escaping control and ALL Unicode characters.
/// If wrap is true, the resulting string is enclosed in double quotes
///
/// Returns formatted string.
///
/// This function is deprecated, please use
///
/// std::string Poco::toJSON(const std::string&, int)
void Foundation_API toJSON(const std::string& value, std::ostream& out, int options);
void Foundation_API toJSON(const std::string& value, std::ostream& out, int options = Poco::JSON_WRAP_STRINGS);
/// Formats string value into the supplied output stream by
/// escaping control characters.
/// If JSON_WRAP_STRINGS is in options, the resulting strings is enclosed in double quotes
@@ -76,7 +57,7 @@ void Foundation_API toJSON(const std::string& value, std::ostream& out, int opti
/// only the compulsory ones.
std::string Foundation_API toJSON(const std::string& value, int options);
std::string Foundation_API toJSON(const std::string& value, int options = Poco::JSON_WRAP_STRINGS);
/// Formats string value by escaping control characters.
/// If JSON_WRAP_STRINGS is in options, the resulting string is enclosed in double quotes
/// If JSON_ESCAPE_UNICODE is in options, all unicode characters will be escaped, otherwise

View File

@@ -302,11 +302,11 @@ public:
/// right justified and zero-padded in a field
/// having at least the specified width.
static void appendHex(std::string& str, int value);
static void appendHex(std::string& str, int value, bool lowercase = false);
/// Formats an int value in hexadecimal notation.
/// The value is treated as unsigned.
static void appendHex(std::string& str, int value, int width);
static void appendHex(std::string& str, int value, int width, bool lowercase = false);
/// Formats a int value in hexadecimal notation,
/// right justified and zero-padded in
/// a field having at least the specified width.
@@ -535,7 +535,7 @@ inline std::string NumberFormatter::format0(int value, int width)
inline std::string NumberFormatter::formatHex(int value, bool prefix)
{
std::string result;
uIntToStr(static_cast<unsigned int>(value), 0x10, result, prefix);
intToStr(static_cast<unsigned int>(value), 0x10, result, prefix);
return result;
}
@@ -543,7 +543,7 @@ inline std::string NumberFormatter::formatHex(int value, bool prefix)
inline std::string NumberFormatter::formatHex(int value, int width, bool prefix)
{
std::string result;
uIntToStr(static_cast<unsigned int>(value), 0x10, result, prefix, width, '0');
intToStr(static_cast<unsigned int>(value), 0x10, result, prefix, width, '0');
return result;
}
@@ -551,7 +551,7 @@ inline std::string NumberFormatter::formatHex(int value, int width, bool prefix)
inline std::string NumberFormatter::format(unsigned value)
{
std::string result;
uIntToStr(value, 10, result);
intToStr(value, 10, result);
return result;
}
@@ -559,7 +559,7 @@ inline std::string NumberFormatter::format(unsigned value)
inline std::string NumberFormatter::format(unsigned value, int width)
{
std::string result;
uIntToStr(value, 10, result, false, width, ' ');
intToStr(value, 10, result, false, width, ' ');
return result;
}
@@ -567,7 +567,7 @@ inline std::string NumberFormatter::format(unsigned value, int width)
inline std::string NumberFormatter::format0(unsigned int value, int width)
{
std::string result;
uIntToStr(value, 10, result, false, width, '0');
intToStr(value, 10, result, false, width, '0');
return result;
}
@@ -575,7 +575,7 @@ inline std::string NumberFormatter::format0(unsigned int value, int width)
inline std::string NumberFormatter::formatHex(unsigned value, bool prefix)
{
std::string result;
uIntToStr(value, 0x10, result, prefix);
intToStr(value, 0x10, result, prefix);
return result;
}
@@ -583,7 +583,7 @@ inline std::string NumberFormatter::formatHex(unsigned value, bool prefix)
inline std::string NumberFormatter::formatHex(unsigned value, int width, bool prefix)
{
std::string result;
uIntToStr(value, 0x10, result, prefix, width, '0');
intToStr(value, 0x10, result, prefix, width, '0');
return result;
}
@@ -615,7 +615,7 @@ inline std::string NumberFormatter::format0(long value, int width)
inline std::string NumberFormatter::formatHex(long value, bool prefix)
{
std::string result;
uIntToStr(static_cast<unsigned long>(value), 0x10, result, prefix);
intToStr(static_cast<unsigned long>(value), 0x10, result, prefix);
return result;
}
@@ -623,7 +623,7 @@ inline std::string NumberFormatter::formatHex(long value, bool prefix)
inline std::string NumberFormatter::formatHex(long value, int width, bool prefix)
{
std::string result;
uIntToStr(static_cast<unsigned long>(value), 0x10, result, prefix, width, '0');
intToStr(static_cast<unsigned long>(value), 0x10, result, prefix, width, '0');
return result;
}
@@ -631,7 +631,7 @@ inline std::string NumberFormatter::formatHex(long value, int width, bool prefix
inline std::string NumberFormatter::format(unsigned long value)
{
std::string result;
uIntToStr(value, 10, result);
intToStr(value, 10, result);
return result;
}
@@ -639,7 +639,7 @@ inline std::string NumberFormatter::format(unsigned long value)
inline std::string NumberFormatter::format(unsigned long value, int width)
{
std::string result;
uIntToStr(value, 10, result, false, width, ' ');
intToStr(value, 10, result, false, width, ' ');
return result;
}
@@ -647,7 +647,7 @@ inline std::string NumberFormatter::format(unsigned long value, int width)
inline std::string NumberFormatter::format0(unsigned long value, int width)
{
std::string result;
uIntToStr(value, 10, result, false, width, '0');
intToStr(value, 10, result, false, width, '0');
return result;
}
@@ -655,7 +655,7 @@ inline std::string NumberFormatter::format0(unsigned long value, int width)
inline std::string NumberFormatter::formatHex(unsigned long value, bool prefix)
{
std::string result;
uIntToStr(value, 0x10, result, prefix);
intToStr(value, 0x10, result, prefix);
return result;
}
@@ -663,7 +663,7 @@ inline std::string NumberFormatter::formatHex(unsigned long value, bool prefix)
inline std::string NumberFormatter::formatHex(unsigned long value, int width, bool prefix)
{
std::string result;
uIntToStr(value, 0x10, result, prefix, width, '0');
intToStr(value, 0x10, result, prefix, width, '0');
return result;
}
@@ -699,7 +699,7 @@ inline std::string NumberFormatter::format0(long long value, int width)
inline std::string NumberFormatter::formatHex(long long value, bool prefix)
{
std::string result;
uIntToStr(static_cast<unsigned long long>(value), 0x10, result, prefix);
intToStr(static_cast<unsigned long long>(value), 0x10, result, prefix);
return result;
}
@@ -707,7 +707,7 @@ inline std::string NumberFormatter::formatHex(long long value, bool prefix)
inline std::string NumberFormatter::formatHex(long long value, int width, bool prefix)
{
std::string result;
uIntToStr(static_cast<unsigned long long>(value), 0x10, result, prefix, width, '0');
intToStr(static_cast<unsigned long long>(value), 0x10, result, prefix, width, '0');
return result;
}
@@ -715,7 +715,7 @@ inline std::string NumberFormatter::formatHex(long long value, int width, bool p
inline std::string NumberFormatter::format(unsigned long long value)
{
std::string result;
uIntToStr(value, 10, result);
intToStr(value, 10, result);
return result;
}
@@ -723,7 +723,7 @@ inline std::string NumberFormatter::format(unsigned long long value)
inline std::string NumberFormatter::format(unsigned long long value, int width)
{
std::string result;
uIntToStr(value, 10, result, false, width, ' ');
intToStr(value, 10, result, false, width, ' ');
return result;
}
@@ -731,7 +731,7 @@ inline std::string NumberFormatter::format(unsigned long long value, int width)
inline std::string NumberFormatter::format0(unsigned long long value, int width)
{
std::string result;
uIntToStr(value, 10, result, false, width, '0');
intToStr(value, 10, result, false, width, '0');
return result;
}
@@ -739,7 +739,7 @@ inline std::string NumberFormatter::format0(unsigned long long value, int width)
inline std::string NumberFormatter::formatHex(unsigned long long value, bool prefix)
{
std::string result;
uIntToStr(value, 0x10, result, prefix);
intToStr(value, 0x10, result, prefix);
return result;
}
@@ -747,7 +747,7 @@ inline std::string NumberFormatter::formatHex(unsigned long long value, bool pre
inline std::string NumberFormatter::formatHex(unsigned long long value, int width, bool prefix)
{
std::string result;
uIntToStr(value, 0x10, result, prefix, width, '0');
intToStr(value, 0x10, result, prefix, width, '0');
return result;
}
@@ -782,7 +782,7 @@ inline std::string NumberFormatter::format0(Int64 value, int width)
inline std::string NumberFormatter::formatHex(Int64 value, bool prefix)
{
std::string result;
uIntToStr(static_cast<UInt64>(value), 0x10, result, prefix);
intToStr(static_cast<UInt64>(value), 0x10, result, prefix);
return result;
}
@@ -790,7 +790,7 @@ inline std::string NumberFormatter::formatHex(Int64 value, bool prefix)
inline std::string NumberFormatter::formatHex(Int64 value, int width, bool prefix)
{
std::string result;
uIntToStr(static_cast<UInt64>(value), 0x10, result, prefix, width, '0');
intToStr(static_cast<UInt64>(value), 0x10, result, prefix, width, '0');
return result;
}
@@ -798,7 +798,7 @@ inline std::string NumberFormatter::formatHex(Int64 value, int width, bool prefi
inline std::string NumberFormatter::format(UInt64 value)
{
std::string result;
uIntToStr(value, 10, result);
intToStr(value, 10, result);
return result;
}
@@ -806,7 +806,7 @@ inline std::string NumberFormatter::format(UInt64 value)
inline std::string NumberFormatter::format(UInt64 value, int width)
{
std::string result;
uIntToStr(value, 10, result, false, width, ' ');
intToStr(value, 10, result, false, width, ' ');
return result;
}
@@ -814,7 +814,7 @@ inline std::string NumberFormatter::format(UInt64 value, int width)
inline std::string NumberFormatter::format0(UInt64 value, int width)
{
std::string result;
uIntToStr(value, 10, result, false, width, '0');
intToStr(value, 10, result, false, width, '0');
return result;
}
@@ -822,7 +822,7 @@ inline std::string NumberFormatter::format0(UInt64 value, int width)
inline std::string NumberFormatter::formatHex(UInt64 value, bool prefix)
{
std::string result;
uIntToStr(value, 0x10, result, prefix);
intToStr(value, 0x10, result, prefix);
return result;
}
@@ -830,7 +830,7 @@ inline std::string NumberFormatter::formatHex(UInt64 value, bool prefix)
inline std::string NumberFormatter::formatHex(UInt64 value, int width, bool prefix)
{
std::string result;
uIntToStr(value, 0x10, result, prefix, width, '0');
intToStr(value, 0x10, result, prefix, width, '0');
return result;
}

View File

@@ -33,6 +33,7 @@
#if !defined(POCO_NO_LOCALE)
#include <locale>
#endif
#include <type_traits>
#if defined(POCO_NOINTMAX)
typedef Poco::UInt64 uintmax_t;
typedef Poco::Int64 intmax_t;
@@ -207,7 +208,9 @@ bool strToInt(const char* pStr, I& outResult, short base, char thSep = ',')
/// Converts zero-terminated character array to integer number;
/// Thousand separators are recognized for base10 and current locale;
/// they are silently skipped and not verified for correct positioning.
/// It is not allowed to convert a negative number to unsigned integer.
/// It is not allowed to convert a negative number to anything except
/// 10-base signed integer.
/// For hexadecimal numbers, the case of the digits is not relevant.
///
/// Function returns true if successful. If parsing was unsuccessful,
/// the return value is false with the result value undetermined.
@@ -216,7 +219,9 @@ bool strToInt(const char* pStr, I& outResult, short base, char thSep = ',')
if (!pStr) return false;
while (std::isspace(*pStr)) ++pStr;
if (*pStr == '\0') return false;
if ((*pStr == '\0') || ((*pStr == '-') && ((base != 10) || (std::is_unsigned<I>::value))))
return false;
bool negative = false;
if ((base == 10) && (*pStr == '-'))
{
@@ -363,10 +368,16 @@ namespace Impl {
const char* _end;
};
template <typename T>
using EnableSigned = typename std::enable_if< std::is_signed<T>::value >::type*;
template <typename T>
using EnableUnsigned = typename std::enable_if< std::is_unsigned<T>::value >::type*;
} // namespace Impl
template <typename T>
template <typename T, Impl::EnableSigned<T> = nullptr>
bool intToStr(T value,
unsigned short base,
char* result,
@@ -374,8 +385,9 @@ bool intToStr(T value,
bool prefix = false,
int width = -1,
char fill = ' ',
char thSep = 0)
/// Converts integer to string. Numeric bases from binary to hexadecimal are supported.
char thSep = 0,
bool lowercase = false)
/// Converts integer to string. Standard numeric bases from binary to hexadecimal are supported.
/// If width is non-zero, it pads the return value with fill character to the specified width.
/// When padding is zero character ('0'), it is prepended to the number itself; all other
/// paddings are prepended to the formatted result with minus sign or base prefix included
@@ -383,6 +395,8 @@ bool intToStr(T value,
/// "0x" for hexadecimal) is prepended. For all other bases, prefix argument is ignored.
/// Formatted string has at least [width] total length.
{
poco_assert_dbg (((value < 0) && (base == 10)) || (value >= 0));
if (base < 2 || base > 0x10)
{
*result = '\0';
@@ -396,7 +410,7 @@ bool intToStr(T value,
{
tmpVal = value;
value /= base;
*ptr++ = "FEDCBA9876543210123456789ABCDEF"[15 + (tmpVal - value * base)];
*ptr++ = (lowercase ? "fedcba9876543210123456789abcdef" : "FEDCBA9876543210123456789ABCDEF")[15 + (tmpVal - value * base)];
if (thSep && (base == 10) && (++thCount == 3))
{
*ptr++ = thSep;
@@ -444,15 +458,16 @@ bool intToStr(T value,
}
template <typename T>
bool uIntToStr(T value,
template <typename T, Impl::EnableUnsigned<T> = nullptr>
bool intToStr(T value,
unsigned short base,
char* result,
std::size_t& size,
bool prefix = false,
int width = -1,
char fill = ' ',
char thSep = 0)
char thSep = 0,
bool lowercase = false)
/// Converts unsigned integer to string. Numeric bases from binary to hexadecimal are supported.
/// If width is non-zero, it pads the return value with fill character to the specified width.
/// When padding is zero character ('0'), it is prepended to the number itself; all other
@@ -474,7 +489,7 @@ bool uIntToStr(T value,
{
tmpVal = value;
value /= base;
*ptr++ = "FEDCBA9876543210123456789ABCDEF"[15 + (tmpVal - value * base)];
*ptr++ = (lowercase ? "fedcba9876543210123456789abcdef" : "FEDCBA9876543210123456789ABCDEF")[15 + (tmpVal - value * base)];
if (thSep && (base == 10) && (++thCount == 3))
{
*ptr++ = thSep;
@@ -510,7 +525,7 @@ bool uIntToStr(T value,
char tmp;
while(ptrr < ptr)
{
tmp = *ptr;
tmp = *ptr;
*ptr-- = *ptrr;
*ptrr++ = tmp;
}
@@ -519,29 +534,67 @@ bool uIntToStr(T value,
}
//@ deprecated
template <typename T>
bool intToStr (T number, unsigned short base, std::string& result, bool prefix = false, int width = -1, char fill = ' ', char thSep = 0)
/// Converts integer to string; This is a wrapper function, for details see see the
bool uIntToStr(T value,
unsigned short base,
char* result,
std::size_t& size,
bool prefix = false,
int width = -1,
char fill = ' ',
char thSep = 0,
bool lowercase = false)
/// Converts unsigned integer to string. Numeric bases from binary to hexadecimal are supported.
/// If width is non-zero, it pads the return value with fill character to the specified width.
/// When padding is zero character ('0'), it is prepended to the number itself; all other
/// paddings are prepended to the formatted result with minus sign or base prefix included
/// If prefix is true and base is octal or hexadecimal, respective prefix ('0' for octal,
/// "0x" for hexadecimal) is prepended. For all other bases, prefix argument is ignored.
/// Formatted string has at least [width] total length.
///
/// This function is deprecated; use intToStr instead.
{
return intToStr(value, base, result, size, prefix, width, fill, thSep, lowercase);
}
template <typename T>
bool intToStr (T number,
unsigned short base,
std::string& result,
bool prefix = false,
int width = -1,
char fill = ' ',
char thSep = 0,
bool lowercase = false)
/// Converts integer to string; This is a wrapper function, for details see the
/// bool intToStr(T, unsigned short, char*, int, int, char, char) implementation.
{
char res[POCO_MAX_INT_STRING_LEN] = {0};
std::size_t size = POCO_MAX_INT_STRING_LEN;
bool ret = intToStr(number, base, res, size, prefix, width, fill, thSep);
bool ret = intToStr(number, base, res, size, prefix, width, fill, thSep, lowercase);
result.assign(res, size);
return ret;
}
//@ deprecated
template <typename T>
bool uIntToStr (T number, unsigned short base, std::string& result, bool prefix = false, int width = -1, char fill = ' ', char thSep = 0)
/// Converts unsigned integer to string; This is a wrapper function, for details see see the
bool uIntToStr (T number,
unsigned short base,
std::string& result,
bool prefix = false,
int width = -1,
char fill = ' ',
char thSep = 0,
bool lowercase = false)
/// Converts unsigned integer to string; This is a wrapper function, for details see the
/// bool uIntToStr(T, unsigned short, char*, int, int, char, char) implementation.
///
/// This function is deprecated; use intToStr instead.
{
char res[POCO_MAX_INT_STRING_LEN] = {0};
std::size_t size = POCO_MAX_INT_STRING_LEN;
bool ret = uIntToStr(number, base, res, size, prefix, width, fill, thSep);
result.assign(res, size);
return ret;
return intToStr(number, base, result, prefix, width, fill, thSep, lowercase);
}

View File

@@ -63,7 +63,7 @@ struct Foundation_API UTF8
/// If strictJSON is true, \a and \v will be escaped to \\u0007 and \\u000B
/// instead of \\a and \\v for strict JSON conformance.
static std::string escape(const std::string::const_iterator& begin, const std::string::const_iterator& end, bool strictJSON = false);
static std::string escape(const std::string::const_iterator& begin, const std::string::const_iterator& end, bool strictJSON = false, bool lowerCaseHex = false);
/// Escapes a string. Special characters like tab, backslash, ... are
/// escaped. Unicode characters are escaped to \uxxxx.
/// If strictJSON is true, \a and \v will be escaped to \\u0007 and \\u000B