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 /// unicode characters will be escaped in the resulting
/// string. /// string.
JSON_WRAP_STRINGS = 4 JSON_WRAP_STRINGS = 4,
/// If specified, the object will preserve the items /// If specified, the object will preserve the items
/// insertion order. Otherwise, items will be sorted /// insertion order. Otherwise, items will be sorted
/// by keys. /// 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, int options = Poco::JSON_WRAP_STRINGS);
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);
/// Formats string value into the supplied output stream by /// Formats string value into the supplied output stream by
/// escaping control characters. /// escaping control characters.
/// If JSON_WRAP_STRINGS is in options, the resulting strings is enclosed in double quotes /// 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. /// 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. /// Formats string value by escaping control characters.
/// If JSON_WRAP_STRINGS is in options, the resulting string is enclosed in double quotes /// 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 /// 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 /// right justified and zero-padded in a field
/// having at least the specified width. /// 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. /// Formats an int value in hexadecimal notation.
/// The value is treated as unsigned. /// 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, /// Formats a int value in hexadecimal notation,
/// right justified and zero-padded in /// right justified and zero-padded in
/// a field having at least the specified width. /// 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) inline std::string NumberFormatter::formatHex(int value, bool prefix)
{ {
std::string result; std::string result;
uIntToStr(static_cast<unsigned int>(value), 0x10, result, prefix); intToStr(static_cast<unsigned int>(value), 0x10, result, prefix);
return result; 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) inline std::string NumberFormatter::formatHex(int value, int width, bool prefix)
{ {
std::string result; 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; return result;
} }
@@ -551,7 +551,7 @@ inline std::string NumberFormatter::formatHex(int value, int width, bool prefix)
inline std::string NumberFormatter::format(unsigned value) inline std::string NumberFormatter::format(unsigned value)
{ {
std::string result; std::string result;
uIntToStr(value, 10, result); intToStr(value, 10, result);
return result; return result;
} }
@@ -559,7 +559,7 @@ inline std::string NumberFormatter::format(unsigned value)
inline std::string NumberFormatter::format(unsigned value, int width) inline std::string NumberFormatter::format(unsigned value, int width)
{ {
std::string result; std::string result;
uIntToStr(value, 10, result, false, width, ' '); intToStr(value, 10, result, false, width, ' ');
return result; 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) inline std::string NumberFormatter::format0(unsigned int value, int width)
{ {
std::string result; std::string result;
uIntToStr(value, 10, result, false, width, '0'); intToStr(value, 10, result, false, width, '0');
return result; 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) inline std::string NumberFormatter::formatHex(unsigned value, bool prefix)
{ {
std::string result; std::string result;
uIntToStr(value, 0x10, result, prefix); intToStr(value, 0x10, result, prefix);
return result; 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) inline std::string NumberFormatter::formatHex(unsigned value, int width, bool prefix)
{ {
std::string result; std::string result;
uIntToStr(value, 0x10, result, prefix, width, '0'); intToStr(value, 0x10, result, prefix, width, '0');
return result; return result;
} }
@@ -615,7 +615,7 @@ inline std::string NumberFormatter::format0(long value, int width)
inline std::string NumberFormatter::formatHex(long value, bool prefix) inline std::string NumberFormatter::formatHex(long value, bool prefix)
{ {
std::string result; std::string result;
uIntToStr(static_cast<unsigned long>(value), 0x10, result, prefix); intToStr(static_cast<unsigned long>(value), 0x10, result, prefix);
return result; 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) inline std::string NumberFormatter::formatHex(long value, int width, bool prefix)
{ {
std::string result; 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; 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) inline std::string NumberFormatter::format(unsigned long value)
{ {
std::string result; std::string result;
uIntToStr(value, 10, result); intToStr(value, 10, result);
return 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) inline std::string NumberFormatter::format(unsigned long value, int width)
{ {
std::string result; std::string result;
uIntToStr(value, 10, result, false, width, ' '); intToStr(value, 10, result, false, width, ' ');
return result; 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) inline std::string NumberFormatter::format0(unsigned long value, int width)
{ {
std::string result; std::string result;
uIntToStr(value, 10, result, false, width, '0'); intToStr(value, 10, result, false, width, '0');
return result; 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) inline std::string NumberFormatter::formatHex(unsigned long value, bool prefix)
{ {
std::string result; std::string result;
uIntToStr(value, 0x10, result, prefix); intToStr(value, 0x10, result, prefix);
return result; 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) inline std::string NumberFormatter::formatHex(unsigned long value, int width, bool prefix)
{ {
std::string result; std::string result;
uIntToStr(value, 0x10, result, prefix, width, '0'); intToStr(value, 0x10, result, prefix, width, '0');
return result; 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) inline std::string NumberFormatter::formatHex(long long value, bool prefix)
{ {
std::string result; 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; 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) inline std::string NumberFormatter::formatHex(long long value, int width, bool prefix)
{ {
std::string result; 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; 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) inline std::string NumberFormatter::format(unsigned long long value)
{ {
std::string result; std::string result;
uIntToStr(value, 10, result); intToStr(value, 10, result);
return 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) inline std::string NumberFormatter::format(unsigned long long value, int width)
{ {
std::string result; std::string result;
uIntToStr(value, 10, result, false, width, ' '); intToStr(value, 10, result, false, width, ' ');
return result; 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) inline std::string NumberFormatter::format0(unsigned long long value, int width)
{ {
std::string result; std::string result;
uIntToStr(value, 10, result, false, width, '0'); intToStr(value, 10, result, false, width, '0');
return result; 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) inline std::string NumberFormatter::formatHex(unsigned long long value, bool prefix)
{ {
std::string result; std::string result;
uIntToStr(value, 0x10, result, prefix); intToStr(value, 0x10, result, prefix);
return result; 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) inline std::string NumberFormatter::formatHex(unsigned long long value, int width, bool prefix)
{ {
std::string result; std::string result;
uIntToStr(value, 0x10, result, prefix, width, '0'); intToStr(value, 0x10, result, prefix, width, '0');
return result; return result;
} }
@@ -782,7 +782,7 @@ inline std::string NumberFormatter::format0(Int64 value, int width)
inline std::string NumberFormatter::formatHex(Int64 value, bool prefix) inline std::string NumberFormatter::formatHex(Int64 value, bool prefix)
{ {
std::string result; std::string result;
uIntToStr(static_cast<UInt64>(value), 0x10, result, prefix); intToStr(static_cast<UInt64>(value), 0x10, result, prefix);
return result; 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) inline std::string NumberFormatter::formatHex(Int64 value, int width, bool prefix)
{ {
std::string result; 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; return result;
} }
@@ -798,7 +798,7 @@ inline std::string NumberFormatter::formatHex(Int64 value, int width, bool prefi
inline std::string NumberFormatter::format(UInt64 value) inline std::string NumberFormatter::format(UInt64 value)
{ {
std::string result; std::string result;
uIntToStr(value, 10, result); intToStr(value, 10, result);
return result; return result;
} }
@@ -806,7 +806,7 @@ inline std::string NumberFormatter::format(UInt64 value)
inline std::string NumberFormatter::format(UInt64 value, int width) inline std::string NumberFormatter::format(UInt64 value, int width)
{ {
std::string result; std::string result;
uIntToStr(value, 10, result, false, width, ' '); intToStr(value, 10, result, false, width, ' ');
return result; return result;
} }
@@ -814,7 +814,7 @@ inline std::string NumberFormatter::format(UInt64 value, int width)
inline std::string NumberFormatter::format0(UInt64 value, int width) inline std::string NumberFormatter::format0(UInt64 value, int width)
{ {
std::string result; std::string result;
uIntToStr(value, 10, result, false, width, '0'); intToStr(value, 10, result, false, width, '0');
return result; return result;
} }
@@ -822,7 +822,7 @@ inline std::string NumberFormatter::format0(UInt64 value, int width)
inline std::string NumberFormatter::formatHex(UInt64 value, bool prefix) inline std::string NumberFormatter::formatHex(UInt64 value, bool prefix)
{ {
std::string result; std::string result;
uIntToStr(value, 0x10, result, prefix); intToStr(value, 0x10, result, prefix);
return result; 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) inline std::string NumberFormatter::formatHex(UInt64 value, int width, bool prefix)
{ {
std::string result; std::string result;
uIntToStr(value, 0x10, result, prefix, width, '0'); intToStr(value, 0x10, result, prefix, width, '0');
return result; return result;
} }

View File

@@ -33,6 +33,7 @@
#if !defined(POCO_NO_LOCALE) #if !defined(POCO_NO_LOCALE)
#include <locale> #include <locale>
#endif #endif
#include <type_traits>
#if defined(POCO_NOINTMAX) #if defined(POCO_NOINTMAX)
typedef Poco::UInt64 uintmax_t; typedef Poco::UInt64 uintmax_t;
typedef Poco::Int64 intmax_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; /// Converts zero-terminated character array to integer number;
/// Thousand separators are recognized for base10 and current locale; /// Thousand separators are recognized for base10 and current locale;
/// they are silently skipped and not verified for correct positioning. /// 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, /// Function returns true if successful. If parsing was unsuccessful,
/// the return value is false with the result value undetermined. /// 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; if (!pStr) return false;
while (std::isspace(*pStr)) ++pStr; 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; bool negative = false;
if ((base == 10) && (*pStr == '-')) if ((base == 10) && (*pStr == '-'))
{ {
@@ -363,10 +368,16 @@ namespace Impl {
const char* _end; 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 } // namespace Impl
template <typename T> template <typename T, Impl::EnableSigned<T> = nullptr>
bool intToStr(T value, bool intToStr(T value,
unsigned short base, unsigned short base,
char* result, char* result,
@@ -374,8 +385,9 @@ bool intToStr(T value,
bool prefix = false, bool prefix = false,
int width = -1, int width = -1,
char fill = ' ', char fill = ' ',
char thSep = 0) char thSep = 0,
/// Converts integer to string. Numeric bases from binary to hexadecimal are supported. 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. /// 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 /// 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 /// 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. /// "0x" for hexadecimal) is prepended. For all other bases, prefix argument is ignored.
/// Formatted string has at least [width] total length. /// Formatted string has at least [width] total length.
{ {
poco_assert_dbg (((value < 0) && (base == 10)) || (value >= 0));
if (base < 2 || base > 0x10) if (base < 2 || base > 0x10)
{ {
*result = '\0'; *result = '\0';
@@ -396,7 +410,7 @@ bool intToStr(T value,
{ {
tmpVal = value; tmpVal = value;
value /= base; value /= base;
*ptr++ = "FEDCBA9876543210123456789ABCDEF"[15 + (tmpVal - value * base)]; *ptr++ = (lowercase ? "fedcba9876543210123456789abcdef" : "FEDCBA9876543210123456789ABCDEF")[15 + (tmpVal - value * base)];
if (thSep && (base == 10) && (++thCount == 3)) if (thSep && (base == 10) && (++thCount == 3))
{ {
*ptr++ = thSep; *ptr++ = thSep;
@@ -444,15 +458,16 @@ bool intToStr(T value,
} }
template <typename T> template <typename T, Impl::EnableUnsigned<T> = nullptr>
bool uIntToStr(T value, bool intToStr(T value,
unsigned short base, unsigned short base,
char* result, char* result,
std::size_t& size, std::size_t& size,
bool prefix = false, bool prefix = false,
int width = -1, int width = -1,
char fill = ' ', char fill = ' ',
char thSep = 0) char thSep = 0,
bool lowercase = false)
/// Converts unsigned integer to string. Numeric bases from binary to hexadecimal are supported. /// 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. /// 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 /// 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; tmpVal = value;
value /= base; value /= base;
*ptr++ = "FEDCBA9876543210123456789ABCDEF"[15 + (tmpVal - value * base)]; *ptr++ = (lowercase ? "fedcba9876543210123456789abcdef" : "FEDCBA9876543210123456789ABCDEF")[15 + (tmpVal - value * base)];
if (thSep && (base == 10) && (++thCount == 3)) if (thSep && (base == 10) && (++thCount == 3))
{ {
*ptr++ = thSep; *ptr++ = thSep;
@@ -510,7 +525,7 @@ bool uIntToStr(T value,
char tmp; char tmp;
while(ptrr < ptr) while(ptrr < ptr)
{ {
tmp = *ptr; tmp = *ptr;
*ptr-- = *ptrr; *ptr-- = *ptrr;
*ptrr++ = tmp; *ptrr++ = tmp;
} }
@@ -519,29 +534,67 @@ bool uIntToStr(T value,
} }
//@ deprecated
template <typename T> 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 uIntToStr(T value,
/// Converts integer to string; This is a wrapper function, for details see see the 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. /// bool intToStr(T, unsigned short, char*, int, int, char, char) implementation.
{ {
char res[POCO_MAX_INT_STRING_LEN] = {0}; char res[POCO_MAX_INT_STRING_LEN] = {0};
std::size_t size = POCO_MAX_INT_STRING_LEN; 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); result.assign(res, size);
return ret; return ret;
} }
//@ deprecated
template <typename T> template <typename T>
bool uIntToStr (T number, unsigned short base, std::string& result, bool prefix = false, int width = -1, char fill = ' ', char thSep = 0) bool uIntToStr (T number,
/// Converts unsigned integer to string; This is a wrapper function, for details see see the 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. /// 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}; return intToStr(number, base, result, prefix, width, fill, thSep, lowercase);
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;
} }

View File

@@ -63,7 +63,7 @@ struct Foundation_API UTF8
/// If strictJSON is true, \a and \v will be escaped to \\u0007 and \\u000B /// If strictJSON is true, \a and \v will be escaped to \\u0007 and \\u000B
/// instead of \\a and \\v for strict JSON conformance. /// 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 /// Escapes a string. Special characters like tab, backslash, ... are
/// escaped. Unicode characters are escaped to \uxxxx. /// escaped. Unicode characters are escaped to \uxxxx.
/// If strictJSON is true, \a and \v will be escaped to \\u0007 and \\u000B /// If strictJSON is true, \a and \v will be escaped to \\u0007 and \\u000B

View File

@@ -32,6 +32,7 @@ void writeString(const std::string &value, T& obj, typename WriteFunc<T, S>::Typ
{ {
bool wrap = ((options & Poco::JSON_WRAP_STRINGS) != 0); bool wrap = ((options & Poco::JSON_WRAP_STRINGS) != 0);
bool escapeAllUnicode = ((options & Poco::JSON_ESCAPE_UNICODE) != 0); bool escapeAllUnicode = ((options & Poco::JSON_ESCAPE_UNICODE) != 0);
bool lowerCaseHex = ((options & Poco::JSON_LOWERCASE_HEX) != 0);
if (value.size() == 0) if (value.size() == 0)
{ {
@@ -42,7 +43,7 @@ void writeString(const std::string &value, T& obj, typename WriteFunc<T, S>::Typ
if(wrap) (obj.*write)("\"", 1); if(wrap) (obj.*write)("\"", 1);
if(escapeAllUnicode) if(escapeAllUnicode)
{ {
std::string str = Poco::UTF8::escape(value.begin(), value.end(), true); std::string str = Poco::UTF8::escape(value.begin(), value.end(), true, lowerCaseHex);
(obj.*write)(str.c_str(), str.size()); (obj.*write)(str.c_str(), str.size());
} }
else else
@@ -51,7 +52,7 @@ void writeString(const std::string &value, T& obj, typename WriteFunc<T, S>::Typ
{ {
if ((*it >= 0 && *it <= 31) || (*it == '"') || (*it == '\\')) if ((*it >= 0 && *it <= 31) || (*it == '"') || (*it == '\\'))
{ {
std::string str = Poco::UTF8::escape(it, it + 1, true); std::string str = Poco::UTF8::escape(it, it + 1, true, lowerCaseHex);
(obj.*write)(str.c_str(), str.size()); (obj.*write)(str.c_str(), str.size());
} }
else (obj.*write)(&(*it), 1); else (obj.*write)(&(*it), 1);
@@ -67,23 +68,6 @@ void writeString(const std::string &value, T& obj, typename WriteFunc<T, S>::Typ
namespace Poco { namespace Poco {
void toJSON(const std::string& value, std::ostream& out, bool wrap)
{
int options = (wrap ? Poco::JSON_WRAP_STRINGS : 0);
writeString<std::ostream, std::streamsize>(value, out, &std::ostream::write, options);
}
std::string toJSON(const std::string& value, bool wrap)
{
int options = (wrap ? Poco::JSON_WRAP_STRINGS : 0);
std::string ret;
writeString<std::string,
std::string::size_type>(value, ret, &std::string::append, options);
return ret;
}
void toJSON(const std::string& value, std::ostream& out, int options) void toJSON(const std::string& value, std::ostream& out, int options)
{ {
writeString<std::ostream, std::streamsize>(value, out, &std::ostream::write, options); writeString<std::ostream, std::streamsize>(value, out, &std::ostream::write, options);

View File

@@ -83,20 +83,20 @@ void NumberFormatter::append0(std::string& str, int value, int width)
} }
void NumberFormatter::appendHex(std::string& str, int value) void NumberFormatter::appendHex(std::string& str, int value, bool lowercase)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(static_cast<unsigned int>(value), 0x10, result, sz); intToStr(static_cast<unsigned int>(value), 0x10, result, sz, false, -1, ' ', 0, lowercase);
str.append(result, sz); str.append(result, sz);
} }
void NumberFormatter::appendHex(std::string& str, int value, int width) void NumberFormatter::appendHex(std::string& str, int value, int width, bool lowercase)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(static_cast<unsigned int>(value), 0x10, result, sz, false, width, '0'); intToStr(static_cast<unsigned int>(value), 0x10, result, sz, false, width, '0', 0, lowercase);
str.append(result, sz); str.append(result, sz);
} }
@@ -105,7 +105,7 @@ void NumberFormatter::append(std::string& str, unsigned value)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 10, result, sz); intToStr(value, 10, result, sz);
str.append(result, sz); str.append(result, sz);
} }
@@ -114,7 +114,7 @@ void NumberFormatter::append(std::string& str, unsigned value, int width)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 10, result, sz, false, width); intToStr(value, 10, result, sz, false, width);
str.append(result, sz); str.append(result, sz);
} }
@@ -123,7 +123,7 @@ void NumberFormatter::append0(std::string& str, unsigned int value, int width)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 10, result, sz, false, width, '0'); intToStr(value, 10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -132,7 +132,7 @@ void NumberFormatter::appendHex(std::string& str, unsigned value)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 0x10, result, sz); intToStr(value, 0x10, result, sz);
str.append(result, sz); str.append(result, sz);
} }
@@ -141,7 +141,7 @@ void NumberFormatter::appendHex(std::string& str, unsigned value, int width)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 0x10, result, sz, false, width, '0'); intToStr(value, 0x10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -177,7 +177,7 @@ void NumberFormatter::appendHex(std::string& str, long value)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(static_cast<unsigned long>(value), 0x10, result, sz); intToStr(static_cast<unsigned long>(value), 0x10, result, sz);
str.append(result, sz); str.append(result, sz);
} }
@@ -186,7 +186,7 @@ void NumberFormatter::appendHex(std::string& str, long value, int width)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(static_cast<unsigned long>(value), 0x10, result, sz, false, width, '0'); intToStr(static_cast<unsigned long>(value), 0x10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -195,7 +195,7 @@ void NumberFormatter::append(std::string& str, unsigned long value)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 10, result, sz); intToStr(value, 10, result, sz);
str.append(result, sz); str.append(result, sz);
} }
@@ -204,7 +204,7 @@ void NumberFormatter::append(std::string& str, unsigned long value, int width)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 10, result, sz, false, width, '0'); intToStr(value, 10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -213,7 +213,7 @@ void NumberFormatter::append0(std::string& str, unsigned long value, int width)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 10, result, sz, false, width, '0'); intToStr(value, 10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -222,7 +222,7 @@ void NumberFormatter::appendHex(std::string& str, unsigned long value)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 0x10, result, sz); intToStr(value, 0x10, result, sz);
str.append(result, sz); str.append(result, sz);
} }
@@ -231,7 +231,7 @@ void NumberFormatter::appendHex(std::string& str, unsigned long value, int width
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 0x10, result, sz, false, width, '0'); intToStr(value, 0x10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -271,7 +271,7 @@ void NumberFormatter::appendHex(std::string& str, long long value)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(static_cast<unsigned long long>(value), 0x10, result, sz); intToStr(static_cast<unsigned long long>(value), 0x10, result, sz);
str.append(result, sz); str.append(result, sz);
} }
@@ -280,7 +280,7 @@ void NumberFormatter::appendHex(std::string& str, long long value, int width)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(static_cast<unsigned long long>(value), 0x10, result, sz, false, width, '0'); intToStr(static_cast<unsigned long long>(value), 0x10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -289,7 +289,7 @@ void NumberFormatter::append(std::string& str, unsigned long long value)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 10, result, sz); intToStr(value, 10, result, sz);
str.append(result, sz); str.append(result, sz);
} }
@@ -298,7 +298,7 @@ void NumberFormatter::append(std::string& str, unsigned long long value, int wid
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 10, result, sz, false, width, '0'); intToStr(value, 10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -307,7 +307,7 @@ void NumberFormatter::append0(std::string& str, unsigned long long value, int wi
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 10, result, sz, false, width, '0'); intToStr(value, 10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -316,7 +316,7 @@ void NumberFormatter::appendHex(std::string& str, unsigned long long value)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 0x10, result, sz); intToStr(value, 0x10, result, sz);
str.append(result, sz); str.append(result, sz);
} }
@@ -325,7 +325,7 @@ void NumberFormatter::appendHex(std::string& str, unsigned long long value, int
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 0x10, result, sz, false, width, '0'); intToStr(value, 0x10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -364,7 +364,7 @@ void NumberFormatter::appendHex(std::string& str, Int64 value)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(static_cast<UInt64>(value), 0x10, result, sz); intToStr(static_cast<UInt64>(value), 0x10, result, sz);
str.append(result, sz); str.append(result, sz);
} }
@@ -373,7 +373,7 @@ void NumberFormatter::appendHex(std::string& str, Int64 value, int width)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(static_cast<UInt64>(value), 0x10, result, sz, false, width, '0'); intToStr(static_cast<UInt64>(value), 0x10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -382,7 +382,7 @@ void NumberFormatter::append(std::string& str, UInt64 value)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 10, result, sz); intToStr(value, 10, result, sz);
str.append(result, sz); str.append(result, sz);
} }
@@ -391,7 +391,7 @@ void NumberFormatter::append(std::string& str, UInt64 value, int width)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 10, result, sz, false, width, '0'); intToStr(value, 10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -400,7 +400,7 @@ void NumberFormatter::append0(std::string& str, UInt64 value, int width)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 10, result, sz, false, width, '0'); intToStr(value, 10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }
@@ -409,7 +409,7 @@ void NumberFormatter::appendHex(std::string& str, UInt64 value)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 0x10, result, sz); intToStr(value, 0x10, result, sz);
str.append(result, sz); str.append(result, sz);
} }
@@ -418,7 +418,7 @@ void NumberFormatter::appendHex(std::string& str, UInt64 value, int width)
{ {
char result[NF_MAX_INT_STRING_LEN]; char result[NF_MAX_INT_STRING_LEN];
std::size_t sz = NF_MAX_INT_STRING_LEN; std::size_t sz = NF_MAX_INT_STRING_LEN;
uIntToStr(value, 0x10, result, sz, false, width, '0'); intToStr(value, 0x10, result, sz, false, width, '0');
str.append(result, sz); str.append(result, sz);
} }

View File

@@ -178,7 +178,7 @@ std::string UTF8::escape(const std::string &s, bool strictJSON)
} }
std::string UTF8::escape(const std::string::const_iterator& begin, const std::string::const_iterator& end, bool strictJSON) std::string UTF8::escape(const std::string::const_iterator& begin, const std::string::const_iterator& end, bool strictJSON, bool lowerCaseHex)
{ {
static Poco::UInt32 offsetsFromUTF8[6] = { static Poco::UInt32 offsetsFromUTF8[6] = {
0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x00000000UL, 0x00003080UL, 0x000E2080UL,
@@ -208,7 +208,7 @@ std::string UTF8::escape(const std::string::const_iterator& begin, const std::st
else if (ch == '\r') result += "\\r"; else if (ch == '\r') result += "\\r";
else if (ch == '\b') result += "\\b"; else if (ch == '\b') result += "\\b";
else if (ch == '\f') result += "\\f"; else if (ch == '\f') result += "\\f";
else if (ch == '\v') result += (strictJSON ? "\\u000B" : "\\v"); else if (ch == '\v') result += (strictJSON ? (lowerCaseHex ? "\\u000b" : "\\u000B") : "\\v");
else if (ch == '\a') result += (strictJSON ? "\\u0007" : "\\a"); else if (ch == '\a') result += (strictJSON ? "\\u0007" : "\\a");
else if (ch == '\\') result += "\\\\"; else if (ch == '\\') result += "\\\\";
else if (ch == '\"') result += "\\\""; else if (ch == '\"') result += "\\\"";
@@ -217,20 +217,20 @@ std::string UTF8::escape(const std::string::const_iterator& begin, const std::st
else if (ch < 32 || ch == 0x7f) else if (ch < 32 || ch == 0x7f)
{ {
result += "\\u"; result += "\\u";
NumberFormatter::appendHex(result, (unsigned short) ch, 4); NumberFormatter::appendHex(result, (unsigned short) ch, 4, lowerCaseHex);
} }
else if (ch > 0xFFFF) else if (ch > 0xFFFF)
{ {
ch -= 0x10000; ch -= 0x10000;
result += "\\u"; result += "\\u";
NumberFormatter::appendHex(result, (unsigned short) (( ch >> 10 ) & 0x03ff ) + 0xd800, 4); NumberFormatter::appendHex(result, (unsigned short) (( ch >> 10 ) & 0x03ff ) + 0xd800, 4, lowerCaseHex);
result += "\\u"; result += "\\u";
NumberFormatter::appendHex(result, (unsigned short) (ch & 0x03ff ) + 0xdc00, 4); NumberFormatter::appendHex(result, (unsigned short) (ch & 0x03ff ) + 0xdc00, 4, lowerCaseHex);
} }
else if (ch >= 0x80 && ch <= 0xFFFF) else if (ch >= 0x80 && ch <= 0xFFFF)
{ {
result += "\\u"; result += "\\u";
NumberFormatter::appendHex(result, (unsigned short) ch, 4); NumberFormatter::appendHex(result, (unsigned short) ch, 4, lowerCaseHex);
} }
else else
{ {

View File

@@ -58,7 +58,7 @@ using Poco::strToInt;
using Poco::strToFloat; using Poco::strToFloat;
using Poco::strToDouble; using Poco::strToDouble;
using Poco::intToStr; using Poco::intToStr;
using Poco::uIntToStr; using Poco::intToStr;
using Poco::floatToStr; using Poco::floatToStr;
using Poco::doubleToStr; using Poco::doubleToStr;
using Poco::thousandSeparator; using Poco::thousandSeparator;
@@ -944,67 +944,92 @@ void StringTest::testIntToString()
assertTrue (result == "1001001100101100000001011010010"); assertTrue (result == "1001001100101100000001011010010");
assertTrue (intToStr(1234567890, 2, result, true, 35, '0')); assertTrue (intToStr(1234567890, 2, result, true, 35, '0'));
assertTrue (result == "00001001001100101100000001011010010"); assertTrue (result == "00001001001100101100000001011010010");
assertTrue (uIntToStr(0xFF, 2, result)); assertTrue (intToStr(0xFF, 2, result));
assertTrue (result == "11111111"); assertTrue (result == "11111111");
assertTrue (uIntToStr(0x0F, 2, result, false, 8, '0')); assertTrue (intToStr(0x0F, 2, result, false, 8, '0'));
assertTrue (result == "00001111"); assertTrue (result == "00001111");
assertTrue (uIntToStr(0x0F, 2, result)); assertTrue (intToStr(0x0F, 2, result));
assertTrue (result == "1111"); assertTrue (result == "1111");
assertTrue (uIntToStr(0xF0, 2, result)); assertTrue (intToStr(0xF0, 2, result));
assertTrue (result == "11110000"); assertTrue (result == "11110000");
assertTrue (uIntToStr(0xFFFF, 2, result)); assertTrue (intToStr(0xFFFF, 2, result));
assertTrue (result == "1111111111111111"); assertTrue (result == "1111111111111111");
assertTrue (uIntToStr(0xFF00, 2, result)); assertTrue (intToStr(0xFF00, 2, result));
assertTrue (result == "1111111100000000"); assertTrue (result == "1111111100000000");
assertTrue (uIntToStr(0xFFFFFFFF, 2, result)); assertTrue (intToStr(0xFFFFFFFF, 2, result));
assertTrue (result == "11111111111111111111111111111111"); assertTrue (result == "11111111111111111111111111111111");
assertTrue (uIntToStr(0xFF00FF00, 2, result)); assertTrue (intToStr(0xFF00FF00, 2, result));
assertTrue (result == "11111111000000001111111100000000"); assertTrue (result == "11111111000000001111111100000000");
assertTrue (uIntToStr(0xF0F0F0F0, 2, result)); assertTrue (intToStr(0xF0F0F0F0, 2, result));
assertTrue (result == "11110000111100001111000011110000"); assertTrue (result == "11110000111100001111000011110000");
#if defined(POCO_HAVE_INT64) #if defined(POCO_HAVE_INT64)
assertTrue (uIntToStr(0xFFFFFFFFFFFFFFFF, 2, result)); assertTrue (intToStr(0xFFFFFFFFFFFFFFFF, 2, result));
assertTrue (result == "1111111111111111111111111111111111111111111111111111111111111111"); assertTrue (result == "1111111111111111111111111111111111111111111111111111111111111111");
assertTrue (uIntToStr(0xFF00000FF00000FF, 2, result)); assertTrue (intToStr(0xFF00000FF00000FF, 2, result));
assertTrue (result == "1111111100000000000000000000111111110000000000000000000011111111"); assertTrue (result == "1111111100000000000000000000111111110000000000000000000011111111");
#endif #endif
// octal // octal
assertTrue (uIntToStr(1234567890, 010, result)); assertTrue (intToStr(1234567890, 010, result));
assertTrue (result == "11145401322"); assertTrue (result == "11145401322");
assertTrue (uIntToStr(1234567890, 010, result, true)); assertTrue (intToStr(1234567890, 010, result, true));
assertTrue (result == "011145401322"); assertTrue (result == "011145401322");
assertTrue (uIntToStr(1234567890, 010, result, true, 15, '0')); assertTrue (intToStr(1234567890, 010, result, true, 15, '0'));
assertTrue (result == "000011145401322"); assertTrue (result == "000011145401322");
assertTrue (uIntToStr(012345670, 010, result, true)); assertTrue (intToStr(012345670, 010, result, true));
assertTrue (result == "012345670"); assertTrue (result == "012345670");
assertTrue (uIntToStr(012345670, 010, result)); assertTrue (intToStr(012345670, 010, result));
assertTrue (result == "12345670"); assertTrue (result == "12345670");
// hexadecimal // hexadecimal
assertTrue (uIntToStr(0, 0x10, result, true)); // uppercase
assertTrue (intToStr(0, 0x10, result, true));
assertTrue (result == "0x0"); assertTrue (result == "0x0");
assertTrue (uIntToStr(0, 0x10, result, true, 4, '0')); assertTrue (intToStr(0, 0x10, result, true, 4, '0'));
assertTrue (result == "0x00"); assertTrue (result == "0x00");
assertTrue (uIntToStr(0, 0x10, result, false, 4, '0')); assertTrue (intToStr(0, 0x10, result, false, 4, '0'));
assertTrue (result == "0000"); assertTrue (result == "0000");
assertTrue (uIntToStr(1234567890, 0x10, result)); assertTrue (intToStr(1234567890, 0x10, result));
assertTrue (result == "499602D2"); assertTrue (result == "499602D2");
assertTrue (uIntToStr(1234567890, 0x10, result, true)); assertTrue (intToStr(1234567890, 0x10, result, true));
assertTrue (result == "0x499602D2"); assertTrue (result == "0x499602D2");
assertTrue (uIntToStr(1234567890, 0x10, result, true, 15, '0')); assertTrue (intToStr(1234567890, 0x10, result, true, 15, '0'));
assertTrue (result == "0x00000499602D2"); assertTrue (result == "0x00000499602D2");
assertTrue (uIntToStr(0x1234567890ABCDEF, 0x10, result, true)); assertTrue (intToStr(0x1234567890ABCDEF, 0x10, result, true));
assertTrue (result == "0x1234567890ABCDEF"); assertTrue (result == "0x1234567890ABCDEF");
assertTrue (uIntToStr(0xDEADBEEF, 0x10, result)); assertTrue (intToStr(0xDEADBEEF, 0x10, result));
assertTrue (result == "DEADBEEF"); assertTrue (result == "DEADBEEF");
#if defined(POCO_HAVE_INT64) #if defined(POCO_HAVE_INT64)
assertTrue (uIntToStr(0xFFFFFFFFFFFFFFFF, 0x10, result)); assertTrue (intToStr(0xFFFFFFFFFFFFFFFF, 0x10, result));
assertTrue (result == "FFFFFFFFFFFFFFFF"); assertTrue (result == "FFFFFFFFFFFFFFFF");
assertTrue (uIntToStr(0xFFFFFFFFFFFFFFFF, 0x10, result, true)); assertTrue (intToStr(0xFFFFFFFFFFFFFFFF, 0x10, result, true));
assertTrue (result == "0xFFFFFFFFFFFFFFFF"); assertTrue (result == "0xFFFFFFFFFFFFFFFF");
#endif #endif
// lowercase
assertTrue (intToStr(0, 0x10, result, true, -1, (char)32, 0, true));
assertTrue (result == "0x0");
assertTrue (intToStr(0, 0x10, result, true, 4, '0', 0, true));
assertTrue (result == "0x00");
assertTrue (intToStr(0, 0x10, result, false, 4, '0', 0, true));
assertTrue (result == "0000");
assertTrue (intToStr(1234567890, 0x10, result, false, -1, (char)32, 0, true));
assertTrue (result == "499602d2");
assertTrue (intToStr(1234567890, 0x10, result, true, -1, (char)32, 0, true));
assertTrue (result == "0x499602d2");
assertTrue (intToStr(1234567890, 0x10, result, true, 15, '0', 0, true));
assertTrue (result == "0x00000499602d2");
assertTrue (intToStr(0x1234567890ABCDEF, 0x10, result, true, -1, (char)32, 0, true));
assertTrue (result == "0x1234567890abcdef");
assertTrue (intToStr(0xDEADBEEF, 0x10, result, false, -1, (char)32, 0, true));
assertTrue (result == "deadbeef");
#if defined(POCO_HAVE_INT64)
assertTrue (intToStr(0xFFFFFFFFFFFFFFFF, 0x10, result, false, -1, (char)32, 0, true));
assertTrue (result == "ffffffffffffffff");
assertTrue (intToStr(0xFFFFFFFFFFFFFFFF, 0x10, result, true, -1, (char)32, 0, true));
assertTrue (result == "0xffffffffffffffff");
#endif
try try
{ {
char pResult[POCO_MAX_INT_STRING_LEN]; char pResult[POCO_MAX_INT_STRING_LEN];
@@ -1245,16 +1270,17 @@ void formatSprintf(double value, std::string& str)
void StringTest::testJSONString() void StringTest::testJSONString()
{ {
assertTrue (toJSON("\\", false) == "\\\\"); assertTrue (toJSON("\\", 0) == "\\\\");
assertTrue (toJSON("\"", false) == "\\\""); assertTrue (toJSON("\"", 0) == "\\\"");
assertTrue (toJSON("\a", false) == "\\u0007"); assertTrue (toJSON("\a", 0) == "\\u0007");
assertTrue (toJSON("\b", false) == "\\b"); assertTrue (toJSON("\b", 0) == "\\b");
assertTrue (toJSON("\f", false) == "\\f"); assertTrue (toJSON("\f", 0) == "\\f");
assertTrue (toJSON("\n", false) == "\\n"); assertTrue (toJSON("\n", 0) == "\\n");
assertTrue (toJSON("\r", false) == "\\r"); assertTrue (toJSON("\r", 0) == "\\r");
assertTrue (toJSON("\t", false) == "\\t"); assertTrue (toJSON("\t", 0) == "\\t");
assertTrue (toJSON("\v", false) == "\\u000B"); assertTrue (toJSON("\v", 0) == "\\u000B");
assertTrue (toJSON("a", false) == "a"); assertTrue (toJSON("\v", Poco::JSON_LOWERCASE_HEX) == "\\u000b");
assertTrue (toJSON("a", 0) == "a");
assertTrue (toJSON("\xD0\x82", 0) == "\xD0\x82"); assertTrue (toJSON("\xD0\x82", 0) == "\xD0\x82");
assertTrue (toJSON("\xD0\x82", Poco::JSON_ESCAPE_UNICODE) == "\\u0402"); assertTrue (toJSON("\xD0\x82", Poco::JSON_ESCAPE_UNICODE) == "\\u0402");
@@ -1296,12 +1322,34 @@ void StringTest::testJSONString()
ostr.str(""); ostr.str("");
toJSON("tb\t", ostr); toJSON("tb\t", ostr);
assertTrue (ostr.str() == "\"tb\\t\""); assertTrue (ostr.str() == "\"tb\\t\"");
ostr.str(""); ostr.str("");
toJSON("\xD0\x82", ostr); toJSON("\xD0\x82", ostr);
assertTrue (ostr.str() == "\"\xD0\x82\""); assertTrue (ostr.str() == "\"\xD0\x82\"");
ostr.str(""); ostr.str("");
toJSON("\xD0\x82", ostr, Poco::JSON_WRAP_STRINGS); toJSON("\xD0\x82", ostr, Poco::JSON_WRAP_STRINGS);
assertTrue (ostr.str() == "\"\xD0\x82\""); assertTrue (ostr.str() == "\"\xD0\x82\"");
// wrap
// uppercase (default)
ostr.str("");
toJSON("\v", ostr);
assertTrue (ostr.str() == "\"\\u000B\"");
// lowercase
ostr.str("");
toJSON("\v", ostr, Poco::JSON_WRAP_STRINGS | Poco::JSON_LOWERCASE_HEX);
assertTrue (ostr.str() == "\"\\u000b\"");
// no wrap
// uppercase
ostr.str("");
toJSON("\v", ostr, 0);
assertTrue (ostr.str() == "\\u000B");
// lowercase
ostr.str("");
toJSON("\v", ostr, Poco::JSON_LOWERCASE_HEX);
assertTrue (ostr.str() == "\\u000b");
ostr.str(""); ostr.str("");
toJSON("\xD0\x82", ostr, Poco::JSON_WRAP_STRINGS | Poco::JSON_ESCAPE_UNICODE); toJSON("\xD0\x82", ostr, Poco::JSON_WRAP_STRINGS | Poco::JSON_ESCAPE_UNICODE);
assertTrue (ostr.str() == "\"\\u0402\""); assertTrue (ostr.str() == "\"\\u0402\"");

View File

@@ -90,6 +90,12 @@ public:
bool getEscapeUnicode() const; bool getEscapeUnicode() const;
/// Returns the flag for escaping unicode. /// Returns the flag for escaping unicode.
void setLowercaseHex(bool lowercaseHex);
/// Sets the flag for using lowercase hex numbers
bool getLowercaseHex() const;
/// Returns the flag for using lowercase hex numbers
ValueVec::const_iterator begin() const; ValueVec::const_iterator begin() const;
/// Returns the begin iterator for values. /// Returns the begin iterator for values.
@@ -206,6 +212,7 @@ private:
// is because Array can be returned stringified from a Dynamic::Var:toString(), // is because Array can be returned stringified from a Dynamic::Var:toString(),
// so it must know whether to escape unicode or not. // so it must know whether to escape unicode or not.
bool _escapeUnicode; bool _escapeUnicode;
bool _lowercaseHex;
}; };
@@ -224,6 +231,17 @@ inline bool Array::getEscapeUnicode() const
return _escapeUnicode; return _escapeUnicode;
} }
inline void Array::setLowercaseHex(bool lowercaseHex)
{
_lowercaseHex = lowercaseHex;
}
inline bool Array::getLowercaseHex() const
{
return _lowercaseHex;
}
inline Array::ValueVec::const_iterator Array::begin() const inline Array::ValueVec::const_iterator Array::begin() const
{ {

View File

@@ -101,7 +101,13 @@ public:
bool getEscapeUnicode() const; bool getEscapeUnicode() const;
/// Returns the flag for escaping unicode. /// Returns the flag for escaping unicode.
void setLowercaseHex(bool lowercaseHex);
/// Sets the flag for using lowercase hex numbers
bool getLowercaseHex() const;
/// Returns the flag for using lowercase hex numbers
Iterator begin(); Iterator begin();
/// Returns begin iterator for values. /// Returns begin iterator for values.
@@ -255,6 +261,7 @@ private:
{ {
int options = Poco::JSON_WRAP_STRINGS; int options = Poco::JSON_WRAP_STRINGS;
options |= _escapeUnicode ? Poco::JSON_ESCAPE_UNICODE : 0; options |= _escapeUnicode ? Poco::JSON_ESCAPE_UNICODE : 0;
options |= _lowercaseHex ? Poco::JSON_LOWERCASE_HEX : 0;
out << '{'; out << '{';
@@ -349,6 +356,7 @@ private:
// because Object can be returned stringified from Dynamic::Var::toString(), // because Object can be returned stringified from Dynamic::Var::toString(),
// so it must know whether to escape unicode or not. // so it must know whether to escape unicode or not.
bool _escapeUnicode; bool _escapeUnicode;
bool _lowercaseHex;
mutable StructPtr _pStruct; mutable StructPtr _pStruct;
mutable OrdStructPtr _pOrdStruct; mutable OrdStructPtr _pOrdStruct;
mutable bool _modified; mutable bool _modified;
@@ -370,6 +378,17 @@ inline bool Object::getEscapeUnicode() const
return _escapeUnicode; return _escapeUnicode;
} }
inline void Object::setLowercaseHex(bool lowercaseHex)
{
_lowercaseHex = lowercaseHex;
}
inline bool Object::getLowercaseHex() const
{
return _lowercaseHex;
}
inline Object::Iterator Object::begin() inline Object::Iterator Object::begin()
{ {

View File

@@ -27,7 +27,8 @@ namespace JSON {
Array::Array(int options): Array::Array(int options):
_modified(false), _modified(false),
_escapeUnicode((options & Poco::JSON_ESCAPE_UNICODE) != 0) _escapeUnicode((options & Poco::JSON_ESCAPE_UNICODE) != 0),
_lowercaseHex((options & Poco::JSON_LOWERCASE_HEX) != 0)
{ {
} }
@@ -36,7 +37,8 @@ Array::Array(const Array& other) :
_values(other._values), _values(other._values),
_pArray(other._pArray), _pArray(other._pArray),
_modified(other._modified), _modified(other._modified),
_escapeUnicode(other._escapeUnicode) _escapeUnicode(other._escapeUnicode),
_lowercaseHex(other._lowercaseHex)
{ {
} }
@@ -45,7 +47,8 @@ Array::Array(Array&& other) noexcept:
_values(std::move(other._values)), _values(std::move(other._values)),
_pArray(std::move(other._pArray)), _pArray(std::move(other._pArray)),
_modified(other._modified), _modified(other._modified),
_escapeUnicode(other._escapeUnicode) _escapeUnicode(other._escapeUnicode),
_lowercaseHex(other._lowercaseHex)
{ {
} }
@@ -58,6 +61,7 @@ Array& Array::operator = (const Array& other)
_pArray = other._pArray; _pArray = other._pArray;
_modified = other._modified; _modified = other._modified;
_escapeUnicode = other._escapeUnicode; _escapeUnicode = other._escapeUnicode;
_lowercaseHex = other._lowercaseHex;
} }
return *this; return *this;
} }
@@ -69,6 +73,7 @@ Array& Array::operator = (Array&& other) noexcept
_pArray = std::move(other._pArray); _pArray = std::move(other._pArray);
_modified = other._modified; _modified = other._modified;
_escapeUnicode = other._escapeUnicode; _escapeUnicode = other._escapeUnicode;
_lowercaseHex = other._lowercaseHex;
return *this; return *this;
} }
@@ -154,6 +159,7 @@ void Array::stringify(std::ostream& out, unsigned int indent, int step) const
{ {
int options = Poco::JSON_WRAP_STRINGS; int options = Poco::JSON_WRAP_STRINGS;
options |= _escapeUnicode ? Poco::JSON_ESCAPE_UNICODE : 0; options |= _escapeUnicode ? Poco::JSON_ESCAPE_UNICODE : 0;
options |= _lowercaseHex ? Poco::JSON_LOWERCASE_HEX : 0;
if (step == -1) step = indent; if (step == -1) step = indent;

View File

@@ -27,6 +27,7 @@ namespace JSON {
Object::Object(int options): Object::Object(int options):
_preserveInsOrder((options & Poco::JSON_PRESERVE_KEY_ORDER) != 0), _preserveInsOrder((options & Poco::JSON_PRESERVE_KEY_ORDER) != 0),
_escapeUnicode((options & Poco::JSON_ESCAPE_UNICODE) != 0), _escapeUnicode((options & Poco::JSON_ESCAPE_UNICODE) != 0),
_lowercaseHex((options & Poco::JSON_LOWERCASE_HEX) != 0),
_modified(false) _modified(false)
{ {
} }
@@ -35,6 +36,7 @@ Object::Object(int options):
Object::Object(const Object& other) : _values(other._values), Object::Object(const Object& other) : _values(other._values),
_preserveInsOrder(other._preserveInsOrder), _preserveInsOrder(other._preserveInsOrder),
_escapeUnicode(other._escapeUnicode), _escapeUnicode(other._escapeUnicode),
_lowercaseHex(other._lowercaseHex),
_pStruct(!other._modified ? other._pStruct : 0), _pStruct(!other._modified ? other._pStruct : 0),
_modified(other._modified) _modified(other._modified)
{ {
@@ -47,6 +49,7 @@ Object::Object(Object&& other) noexcept:
_keys(std::move(other._keys)), _keys(std::move(other._keys)),
_preserveInsOrder(other._preserveInsOrder), _preserveInsOrder(other._preserveInsOrder),
_escapeUnicode(other._escapeUnicode), _escapeUnicode(other._escapeUnicode),
_lowercaseHex(other._lowercaseHex),
_pStruct(std::move(other._pStruct)), _pStruct(std::move(other._pStruct)),
_pOrdStruct(std::move(other._pOrdStruct)), _pOrdStruct(std::move(other._pOrdStruct)),
_modified(other._modified) _modified(other._modified)
@@ -67,6 +70,7 @@ Object &Object::operator = (const Object &other)
_keys = other._keys; _keys = other._keys;
_preserveInsOrder = other._preserveInsOrder; _preserveInsOrder = other._preserveInsOrder;
_escapeUnicode = other._escapeUnicode; _escapeUnicode = other._escapeUnicode;
_lowercaseHex = other._lowercaseHex;
_pStruct = !other._modified ? other._pStruct : 0; _pStruct = !other._modified ? other._pStruct : 0;
_modified = other._modified; _modified = other._modified;
} }
@@ -80,6 +84,7 @@ Object& Object::operator = (Object&& other) noexcept
_keys = std::move(other._keys); _keys = std::move(other._keys);
_preserveInsOrder = other._preserveInsOrder; _preserveInsOrder = other._preserveInsOrder;
_escapeUnicode = other._escapeUnicode; _escapeUnicode = other._escapeUnicode;
_lowercaseHex = other._lowercaseHex;
_pStruct = std::move(other._pStruct); _pStruct = std::move(other._pStruct);
_pOrdStruct = std::move(other._pOrdStruct); _pOrdStruct = std::move(other._pOrdStruct);
_modified = other._modified; _modified = other._modified;

View File

@@ -28,6 +28,7 @@ namespace JSON {
void Stringifier::stringify(const Var& any, std::ostream& out, unsigned int indent, int step, int options) void Stringifier::stringify(const Var& any, std::ostream& out, unsigned int indent, int step, int options)
{ {
bool escapeUnicode = ((options & Poco::JSON_ESCAPE_UNICODE) != 0); bool escapeUnicode = ((options & Poco::JSON_ESCAPE_UNICODE) != 0);
bool lowercaseHex = ((options & Poco::JSON_LOWERCASE_HEX) != 0);
if (step == -1) step = indent; if (step == -1) step = indent;
@@ -35,24 +36,28 @@ void Stringifier::stringify(const Var& any, std::ostream& out, unsigned int inde
{ {
Object& o = const_cast<Object&>(any.extract<Object>()); Object& o = const_cast<Object&>(any.extract<Object>());
o.setEscapeUnicode(escapeUnicode); o.setEscapeUnicode(escapeUnicode);
o.setLowercaseHex(lowercaseHex);
o.stringify(out, indent == 0 ? 0 : indent, step); o.stringify(out, indent == 0 ? 0 : indent, step);
} }
else if (any.type() == typeid(Array)) else if (any.type() == typeid(Array))
{ {
Array& a = const_cast<Array&>(any.extract<Array>()); Array& a = const_cast<Array&>(any.extract<Array>());
a.setEscapeUnicode(escapeUnicode); a.setEscapeUnicode(escapeUnicode);
a.setLowercaseHex(lowercaseHex);
a.stringify(out, indent == 0 ? 0 : indent, step); a.stringify(out, indent == 0 ? 0 : indent, step);
} }
else if (any.type() == typeid(Object::Ptr)) else if (any.type() == typeid(Object::Ptr))
{ {
Object::Ptr& o = const_cast<Object::Ptr&>(any.extract<Object::Ptr>()); Object::Ptr& o = const_cast<Object::Ptr&>(any.extract<Object::Ptr>());
o->setEscapeUnicode(escapeUnicode); o->setEscapeUnicode(escapeUnicode);
o->setLowercaseHex(lowercaseHex);
o->stringify(out, indent == 0 ? 0 : indent, step); o->stringify(out, indent == 0 ? 0 : indent, step);
} }
else if (any.type() == typeid(Array::Ptr)) else if (any.type() == typeid(Array::Ptr))
{ {
Array::Ptr& a = const_cast<Array::Ptr&>(any.extract<Array::Ptr>()); Array::Ptr& a = const_cast<Array::Ptr&>(any.extract<Array::Ptr>());
a->setEscapeUnicode(escapeUnicode); a->setEscapeUnicode(escapeUnicode);
a->setLowercaseHex(lowercaseHex);
a->stringify(out, indent == 0 ? 0 : indent, step); a->stringify(out, indent == 0 ? 0 : indent, step);
} }
else if (any.isEmpty()) else if (any.isEmpty())