integer to string conversion

replaced sprintf-based  int-to-string functionality with built-in
intToString
This commit is contained in:
aleks-f
2012-11-22 10:08:46 -06:00
parent 9d420106e2
commit 9cd0f0b4f7
7 changed files with 532 additions and 185 deletions

View File

@@ -41,6 +41,7 @@
#include "Poco/Foundation.h" #include "Poco/Foundation.h"
#include "Poco/NumericString.h"
namespace Poco { namespace Poco {
@@ -55,9 +56,6 @@ class Foundation_API NumberFormatter
/// the formatted value. /// the formatted value.
/// * append* functions append the formatted value to /// * append* functions append the formatted value to
/// an existing string. /// an existing string.
///
/// Internally, std::sprintf() is used to do the actual
/// formatting.
{ {
public: public:
enum BoolFormat enum BoolFormat
@@ -67,6 +65,8 @@ public:
FMT_ON_OFF FMT_ON_OFF
}; };
static const unsigned NF_MAX_NUM_STRING_SIZE = 32;
static std::string format(int value); static std::string format(int value);
/// Formats an integer value in decimal notation. /// Formats an integer value in decimal notation.
@@ -80,14 +80,18 @@ 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 std::string formatHex(int value); static std::string formatHex(int value, bool prefix = false);
/// Formats an int value in hexadecimal notation. /// Formats an int value in hexadecimal notation.
/// If prefix is true, "0x" prefix is prepended to the
/// resulting string.
/// The value is treated as unsigned. /// The value is treated as unsigned.
static std::string formatHex(int value, int width); static std::string formatHex(int value, int width, bool prefix = 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.
/// If prefix is true, "0x" prefix is prepended to the
/// resulting string.
/// The value is treated as unsigned. /// The value is treated as unsigned.
static std::string format(unsigned value); static std::string format(unsigned value);
@@ -103,13 +107,17 @@ public:
/// right justified and zero-padded in a field having at /// right justified and zero-padded in a field having at
/// least the specified width. /// least the specified width.
static std::string formatHex(unsigned value); static std::string formatHex(unsigned value, bool prefix = false);
/// Formats an unsigned int value in hexadecimal notation. /// Formats an unsigned int value in hexadecimal notation.
/// If prefix is true, "0x" prefix is prepended to the
/// resulting string.
static std::string formatHex(unsigned value, int width); static std::string formatHex(unsigned value, int width, bool prefix = 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.
/// If prefix is true, "0x" prefix is prepended to the
/// resulting string.
static std::string format(long value); static std::string format(long value);
/// Formats a long value in decimal notation. /// Formats a long value in decimal notation.
@@ -124,14 +132,18 @@ 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 std::string formatHex(long value); static std::string formatHex(long value, bool prefix = false);
/// Formats an unsigned long value in hexadecimal notation. /// Formats an unsigned long value in hexadecimal notation.
/// If prefix is true, "0x" prefix is prepended to the
/// resulting string.
/// The value is treated as unsigned. /// The value is treated as unsigned.
static std::string formatHex(long value, int width); static std::string formatHex(long value, int width, bool prefix = false);
/// Formats an unsigned long value in hexadecimal notation, /// Formats an unsigned long value in hexadecimal notation,
/// right justified and zero-padded in a field having at least the /// right justified and zero-padded in a field having at least the
/// specified width. /// specified width.
/// If prefix is true, "0x" prefix is prepended to the
/// resulting string.
/// The value is treated as unsigned. /// The value is treated as unsigned.
static std::string format(unsigned long value); static std::string format(unsigned long value);
@@ -147,13 +159,17 @@ public:
/// right justified and zero-padded /// right justified and zero-padded
/// in a field having at least the specified width. /// in a field having at least the specified width.
static std::string formatHex(unsigned long value); static std::string formatHex(unsigned long value, bool prefix = false);
/// Formats an unsigned long value in hexadecimal notation. /// Formats an unsigned long value in hexadecimal notation.
/// If prefix is true, "0x" prefix is prepended to the
/// resulting string.
static std::string formatHex(unsigned long value, int width); static std::string formatHex(unsigned long value, int width, bool prefix = false);
/// Formats an unsigned long value in hexadecimal notation, /// Formats an unsigned long value in hexadecimal notation,
/// right justified and zero-padded in a field having at least the /// right justified and zero-padded in a field having at least the
/// specified width. /// specified width.
/// If prefix is true, "0x" prefix is prepended to the
/// resulting string.
#if defined(POCO_HAVE_INT64) && !defined(POCO_LONG_IS_64_BIT) #if defined(POCO_HAVE_INT64) && !defined(POCO_LONG_IS_64_BIT)
@@ -169,15 +185,18 @@ public:
/// right justified and zero-padded in a field having at least /// right justified and zero-padded in a field having at least
/// the specified width. /// the specified width.
static std::string formatHex(Int64 value); static std::string formatHex(Int64 value, bool prefix = false);
/// Formats a 64-bit integer value in hexadecimal notation. /// Formats a 64-bit integer value in hexadecimal notation.
/// If prefix is true, "0x" prefix is prepended to the
/// resulting string.
/// The value is treated as unsigned. /// The value is treated as unsigned.
static std::string formatHex(Int64 value, int width); static std::string formatHex(Int64 value, int width, bool prefix = false);
/// Formats a 64-bit integer value in hexadecimal notation, /// Formats a 64-bit integer value in hexadecimal notation,
/// right justified and zero-padded in a field having at least /// right justified and zero-padded in a field having at least
/// the specified width. /// the specified width.
/// The value is treated as unsigned. /// The value is treated as unsigned.
/// If prefix is true, "0x" prefix is prepended to the resulting string.
static std::string format(UInt64 value); static std::string format(UInt64 value);
/// Formats an unsigned 64-bit integer value in decimal notation. /// Formats an unsigned 64-bit integer value in decimal notation.
@@ -191,13 +210,16 @@ public:
/// right justified and zero-padded in a field having at least the /// right justified and zero-padded in a field having at least the
/// specified width. /// specified width.
static std::string formatHex(UInt64 value); static std::string formatHex(UInt64 value, bool prefix = false);
/// Formats a 64-bit integer value in hexadecimal notation. /// Formats a 64-bit integer value in hexadecimal notation.
/// If prefix is true, "0x" prefix is prepended to the
/// resulting string.
static std::string formatHex(UInt64 value, int width); static std::string formatHex(UInt64 value, int width, bool prefix = false);
/// Formats a 64-bit integer value in hexadecimal notation, /// Formats a 64-bit integer value in hexadecimal notation,
/// right justified and zero-padded in a field having at least /// right justified and zero-padded in a field having at least
/// the specified width. /// the specified width. If prefix is true, "0x" prefix is
/// prepended to the resulting string.
#endif // defined(POCO_HAVE_INT64) && !defined(POCO_LONG_IS_64_BIT) #endif // defined(POCO_HAVE_INT64) && !defined(POCO_LONG_IS_64_BIT)
@@ -388,10 +410,11 @@ public:
// //
// inlines // inlines
// //
inline std::string NumberFormatter::format(int value) inline std::string NumberFormatter::format(int value)
{ {
std::string result; std::string result;
append(result, value); intToStr(value, 10, result);
return result; return result;
} }
@@ -399,7 +422,7 @@ inline std::string NumberFormatter::format(int value)
inline std::string NumberFormatter::format(int value, int width) inline std::string NumberFormatter::format(int value, int width)
{ {
std::string result; std::string result;
append(result, value, width); intToStr(value, 10, result, false, width, ' ');
return result; return result;
} }
@@ -407,23 +430,23 @@ inline std::string NumberFormatter::format(int value, int width)
inline std::string NumberFormatter::format0(int value, int width) inline std::string NumberFormatter::format0(int value, int width)
{ {
std::string result; std::string result;
append0(result, value, width); intToStr(value, 10, result, false, width, '0');
return result; return result;
} }
inline std::string NumberFormatter::formatHex(int value) inline std::string NumberFormatter::formatHex(int value, bool prefix)
{ {
std::string result; std::string result;
appendHex(result, value); intToStr(value, 0x10, result, prefix);
return result; return result;
} }
inline std::string NumberFormatter::formatHex(int value, int width) inline std::string NumberFormatter::formatHex(int value, int width, bool prefix)
{ {
std::string result; std::string result;
appendHex(result, value, width); intToStr(value, 0x10, result, prefix, width, '0');
return result; return result;
} }
@@ -431,7 +454,7 @@ inline std::string NumberFormatter::formatHex(int value, int width)
inline std::string NumberFormatter::format(unsigned value) inline std::string NumberFormatter::format(unsigned value)
{ {
std::string result; std::string result;
append(result, value); intToStr(value, 10, result);
return result; return result;
} }
@@ -439,7 +462,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;
append(result, value, width); intToStr(value, 10, result, false, width, ' ');
return result; return result;
} }
@@ -447,23 +470,23 @@ 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;
append0(result, value, width); intToStr(value, 10, result, false, width, '0');
return result; return result;
} }
inline std::string NumberFormatter::formatHex(unsigned value) inline std::string NumberFormatter::formatHex(unsigned value, bool prefix)
{ {
std::string result; std::string result;
appendHex(result, value); intToStr(value, 0x10, result, prefix);
return result; return result;
} }
inline std::string NumberFormatter::formatHex(unsigned value, int width) inline std::string NumberFormatter::formatHex(unsigned value, int width, bool prefix)
{ {
std::string result; std::string result;
appendHex(result, value, width); intToStr(value, 0x10, result, prefix, width, '0');
return result; return result;
} }
@@ -471,7 +494,7 @@ inline std::string NumberFormatter::formatHex(unsigned value, int width)
inline std::string NumberFormatter::format(long value) inline std::string NumberFormatter::format(long value)
{ {
std::string result; std::string result;
append(result, value); intToStr(value, 10, result);
return result; return result;
} }
@@ -479,7 +502,7 @@ inline std::string NumberFormatter::format(long value)
inline std::string NumberFormatter::format(long value, int width) inline std::string NumberFormatter::format(long value, int width)
{ {
std::string result; std::string result;
append(result, value, width); intToStr(value, 10, result, false, width, ' ');
return result; return result;
} }
@@ -487,23 +510,23 @@ inline std::string NumberFormatter::format(long value, int width)
inline std::string NumberFormatter::format0(long value, int width) inline std::string NumberFormatter::format0(long value, int width)
{ {
std::string result; std::string result;
append0(result, value, width); intToStr(value, 10, result, false, width, '0');
return result; return result;
} }
inline std::string NumberFormatter::formatHex(long value) inline std::string NumberFormatter::formatHex(long value, bool prefix)
{ {
std::string result; std::string result;
appendHex(result, value); intToStr(value, 0x10, result, prefix);
return result; return result;
} }
inline std::string NumberFormatter::formatHex(long value, int width) inline std::string NumberFormatter::formatHex(long value, int width, bool prefix)
{ {
std::string result; std::string result;
appendHex(result, value, width); intToStr(value, 0x10, result, prefix, width, '0');
return result; return result;
} }
@@ -511,7 +534,7 @@ inline std::string NumberFormatter::formatHex(long value, int width)
inline std::string NumberFormatter::format(unsigned long value) inline std::string NumberFormatter::format(unsigned long value)
{ {
std::string result; std::string result;
append(result, value); intToStr(value, 10, result);
return result; return result;
} }
@@ -519,7 +542,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;
append(result, value, width); intToStr(value, 10, result, false, width, ' ');
return result; return result;
} }
@@ -527,23 +550,23 @@ 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;
append0(result, value, width); intToStr(value, 10, result, false, width, '0');
return result; return result;
} }
inline std::string NumberFormatter::formatHex(unsigned long value) inline std::string NumberFormatter::formatHex(unsigned long value, bool prefix)
{ {
std::string result; std::string result;
appendHex(result, value); intToStr(value, 0x10, result, prefix);
return result; return result;
} }
inline std::string NumberFormatter::formatHex(unsigned long value, int width) inline std::string NumberFormatter::formatHex(unsigned long value, int width, bool prefix)
{ {
std::string result; std::string result;
appendHex(result, value, width); intToStr(value, 0x10, result, prefix, width, '0');
return result; return result;
} }
@@ -554,7 +577,7 @@ inline std::string NumberFormatter::formatHex(unsigned long value, int width)
inline std::string NumberFormatter::format(Int64 value) inline std::string NumberFormatter::format(Int64 value)
{ {
std::string result; std::string result;
append(result, value); intToStr(value, 10, result);
return result; return result;
} }
@@ -562,7 +585,7 @@ inline std::string NumberFormatter::format(Int64 value)
inline std::string NumberFormatter::format(Int64 value, int width) inline std::string NumberFormatter::format(Int64 value, int width)
{ {
std::string result; std::string result;
append(result, value, width); intToStr(value, 10, result, false, width, ' ');
return result; return result;
} }
@@ -570,23 +593,23 @@ inline std::string NumberFormatter::format(Int64 value, int width)
inline std::string NumberFormatter::format0(Int64 value, int width) inline std::string NumberFormatter::format0(Int64 value, int width)
{ {
std::string result; std::string result;
append0(result, value, width); intToStr(value, 10, result, false, width, '0');
return result; return result;
} }
inline std::string NumberFormatter::formatHex(Int64 value) inline std::string NumberFormatter::formatHex(Int64 value, bool prefix)
{ {
std::string result; std::string result;
appendHex(result, value); intToStr(value, 0x10, result, prefix);
return result; return result;
} }
inline std::string NumberFormatter::formatHex(Int64 value, int width) inline std::string NumberFormatter::formatHex(Int64 value, int width, bool prefix)
{ {
std::string result; std::string result;
appendHex(result, value, width); intToStr(value, 0x10, result, prefix, width, '0');
return result; return result;
} }
@@ -594,7 +617,7 @@ inline std::string NumberFormatter::formatHex(Int64 value, int width)
inline std::string NumberFormatter::format(UInt64 value) inline std::string NumberFormatter::format(UInt64 value)
{ {
std::string result; std::string result;
append(result, value); intToStr(value, 10, result);
return result; return result;
} }
@@ -602,7 +625,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;
append(result, value, width); intToStr(value, 10, result, false, width, ' ');
return result; return result;
} }
@@ -610,23 +633,23 @@ 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;
append0(result, value, width); intToStr(value, 10, result, false, width, '0');
return result; return result;
} }
inline std::string NumberFormatter::formatHex(UInt64 value) inline std::string NumberFormatter::formatHex(UInt64 value, bool prefix)
{ {
std::string result; std::string result;
appendHex(result, value); intToStr(value, 0x10, result, prefix);
return result; return result;
} }
inline std::string NumberFormatter::formatHex(UInt64 value, int width) inline std::string NumberFormatter::formatHex(UInt64 value, int width, bool prefix)
{ {
std::string result; std::string result;
appendHex(result, value, width); intToStr(value, 0x10, result, prefix, width, '0');
return result; return result;
} }

View File

@@ -41,6 +41,7 @@
#include "Poco/Foundation.h" #include "Poco/Foundation.h"
#include "Poco/Buffer.h"
#include "Poco/FPEnvironment.h" #include "Poco/FPEnvironment.h"
#ifdef min #ifdef min
#undef min #undef min
@@ -54,6 +55,8 @@
#include <locale> #include <locale>
#endif #endif
#define POCO_MAX_NUM_STRING_LEN 65
namespace Poco { namespace Poco {
@@ -82,6 +85,10 @@ inline char thousandSeparator()
} }
//
// String to Number Conversions
//
template <typename I> template <typename I>
bool strToInt(const char* pStr, I& result, short base, char thSep = ',') bool strToInt(const char* pStr, I& result, short base, char thSep = ',')
/// Converts zero-terminated character array to integer number; /// Converts zero-terminated character array to integer number;
@@ -357,6 +364,174 @@ bool strToFloat (const std::string& s, F& result, char& eu = Impl::DUMMY_EXP_UND
} }
//
// Number to String Conversions
//
namespace Impl {
class Ptr
/// Utility char pointer wrapper class.
/// Class ensures increment/decrement remain within boundaries.
{
public:
Ptr(char* ptr, unsigned offset): _beg(ptr), _cur(ptr), _end(ptr + offset)
{
}
char*& operator ++ () // prefix
{
check(_cur + 1);
return ++_cur;
}
char* operator ++ (int) // postfix
{
check(_cur + 1);
char* tmp = _cur++;
return tmp;
}
char*& operator -- () // prefix
{
check(_cur - 1);
return --_cur;
}
char* operator -- (int) // postfix
{
check(_cur - 1);
char* tmp = _cur--;
return tmp;
}
char*& operator += (int incr)
{
check(_cur + incr);
return _cur += incr;
}
char*& operator -= (int decr)
{
check(_cur - decr);
return _cur -= decr;
}
operator char* () const
{
return _cur;
}
unsigned span() const
{
return _end - _beg;
}
private:
void check(char* ptr)
{
if (ptr > _end) throw RangeException();
}
const char* _beg;
char* _cur;
const char* _end;
};
} // namespace Impl
template <typename T>
bool intToStr(T value,
unsigned short base,
char* result,
unsigned& size,
bool prefix = false,
int width = -1,
char fill = ' ',
char thSep = 0)
/// Converts 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.
{
if (base < 2 || base > 0x10)
{
*result = '\0';
return false;
}
Impl::Ptr ptr(result, size);
int thCount = 0;
T tmpVal;
do
{
tmpVal = value;
value /= base;
*ptr++ = "FEDCBA9876543210123456789ABCDEF"[15 + (tmpVal - value * base)];
if (thSep && (base == 10) && (++thCount == 3))
{
*ptr++ = thSep;
thCount = 0;
}
} while (value);
if ('0' == fill)
{
if (tmpVal < 0) --width;
if (prefix && base == 010) --width;
if (prefix && base == 0x10) width -= 2;
while ((ptr - result) < width) *ptr++ = fill;
}
if (prefix && base == 010) *ptr++ = '0';
else if (prefix && base == 0x10)
{
*ptr++ = 'x';
*ptr++ = '0';
}
if (tmpVal < 0) *ptr++ = '-';
if ('0' != fill)
{
while ((ptr - result) < width) *ptr++ = fill;
}
size = ptr - result;
poco_assert_dbg (size <= ptr.span());
poco_assert_dbg ((-1 == width) || (size >= width));
*ptr-- = '\0';
char* ptrr = result;
char tmp;
while(ptrr < ptr)
{
tmp = *ptr;
*ptr-- = *ptrr;
*ptrr++ = tmp;
}
return true;
}
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 intToStr(T, unsigned short, char*, int, int, char, char) implementation.
{
char res[POCO_MAX_NUM_STRING_LEN] = {0};
unsigned size = POCO_MAX_NUM_STRING_LEN;
bool ret = intToStr(number, base, res, size, prefix, width, fill, thSep);
result.assign(res, size);
return ret;
}
} // namespace Poco } // namespace Poco

View File

@@ -78,185 +78,181 @@ std::string NumberFormatter::format(bool value, BoolFormat format)
void NumberFormatter::append(std::string& str, int value) void NumberFormatter::append(std::string& str, int value)
{ {
char buffer[64]; char result[NF_MAX_NUM_STRING_SIZE];
std::sprintf(buffer, "%d", value); unsigned sz = NF_MAX_NUM_STRING_SIZE;
str.append(buffer); intToStr(value, 10, result, sz);
str.append(result, sz);
} }
void NumberFormatter::append(std::string& str, int value, int width) void NumberFormatter::append(std::string& str, int value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 10, result, sz, false, width);
std::sprintf(buffer, "%*d", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::append0(std::string& str, int value, int width) void NumberFormatter::append0(std::string& str, int value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 10, result, sz, false, width, '0');
std::sprintf(buffer, "%0*d", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::appendHex(std::string& str, int value) void NumberFormatter::appendHex(std::string& str, int value)
{ {
char buffer[64]; char result[NF_MAX_NUM_STRING_SIZE];
std::sprintf(buffer, "%X", value); unsigned sz = NF_MAX_NUM_STRING_SIZE;
str.append(buffer); intToStr(value, 0x10, 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)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 0x10, result, sz, false, width, '0');
std::sprintf(buffer, "%0*X", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::append(std::string& str, unsigned value) void NumberFormatter::append(std::string& str, unsigned value)
{ {
char buffer[64]; char result[NF_MAX_NUM_STRING_SIZE];
std::sprintf(buffer, "%u", value); unsigned sz = NF_MAX_NUM_STRING_SIZE;
str.append(buffer); intToStr(value, 10, result, sz);
str.append(result, sz);
} }
void NumberFormatter::append(std::string& str, unsigned value, int width) void NumberFormatter::append(std::string& str, unsigned value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 10, result, sz, false, width);
std::sprintf(buffer, "%*u", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::append0(std::string& str, unsigned int value, int width) void NumberFormatter::append0(std::string& str, unsigned int value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 10, result, sz, false, width, '0');
std::sprintf(buffer, "%0*u", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::appendHex(std::string& str, unsigned value) void NumberFormatter::appendHex(std::string& str, unsigned value)
{ {
char buffer[64]; char result[NF_MAX_NUM_STRING_SIZE];
std::sprintf(buffer, "%X", value); unsigned sz = NF_MAX_NUM_STRING_SIZE;
str.append(buffer); intToStr(value, 0x10, result, sz);
str.append(result, sz);
} }
void NumberFormatter::appendHex(std::string& str, unsigned value, int width) void NumberFormatter::appendHex(std::string& str, unsigned value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 0x10, result, sz, false, width, '0');
std::sprintf(buffer, "%0*X", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::append(std::string& str, long value) void NumberFormatter::append(std::string& str, long value)
{ {
char buffer[64]; char result[NF_MAX_NUM_STRING_SIZE];
std::sprintf(buffer, "%ld", value); unsigned sz = NF_MAX_NUM_STRING_SIZE;
str.append(buffer); intToStr(value, 10, result, sz);
str.append(result, sz);
} }
void NumberFormatter::append(std::string& str, long value, int width) void NumberFormatter::append(std::string& str, long value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 10, result, sz, false, width);
std::sprintf(buffer, "%*ld", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::append0(std::string& str, long value, int width) void NumberFormatter::append0(std::string& str, long value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 10, result, sz, false, width, '0');
std::sprintf(buffer, "%0*ld", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::appendHex(std::string& str, long value) void NumberFormatter::appendHex(std::string& str, long value)
{ {
char buffer[64]; char result[NF_MAX_NUM_STRING_SIZE];
std::sprintf(buffer, "%lX", value); unsigned sz = NF_MAX_NUM_STRING_SIZE;
str.append(buffer); intToStr(value, 0x10, result, sz);
str.append(result, sz);
} }
void NumberFormatter::appendHex(std::string& str, long value, int width) void NumberFormatter::appendHex(std::string& str, long value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 0x10, result, sz, false, width, '0');
std::sprintf(buffer, "%0*lX", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::append(std::string& str, unsigned long value) void NumberFormatter::append(std::string& str, unsigned long value)
{ {
char buffer[64]; char result[NF_MAX_NUM_STRING_SIZE];
std::sprintf(buffer, "%lu", value); unsigned sz = NF_MAX_NUM_STRING_SIZE;
str.append(buffer); intToStr(value, 10, result, sz);
str.append(result, sz);
} }
void NumberFormatter::append(std::string& str, unsigned long value, int width) void NumberFormatter::append(std::string& str, unsigned long value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 10, result, sz, false, width, '0');
std::sprintf(buffer, "%*lu", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::append0(std::string& str, unsigned long value, int width) void NumberFormatter::append0(std::string& str, unsigned long value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 10, result, sz, false, width, '0');
std::sprintf(buffer, "%0*lu", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::appendHex(std::string& str, unsigned long value) void NumberFormatter::appendHex(std::string& str, unsigned long value)
{ {
char buffer[64]; char result[NF_MAX_NUM_STRING_SIZE];
std::sprintf(buffer, "%lX", value); unsigned sz = NF_MAX_NUM_STRING_SIZE;
str.append(buffer); intToStr(value, 0x10, result, sz);
str.append(result, sz);
} }
void NumberFormatter::appendHex(std::string& str, unsigned long value, int width) void NumberFormatter::appendHex(std::string& str, unsigned long value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 0x10, result, sz, false, width, '0');
std::sprintf(buffer, "%0*lX", width, value); str.append(result, sz);
str.append(buffer);
} }
@@ -265,93 +261,91 @@ void NumberFormatter::appendHex(std::string& str, unsigned long value, int width
void NumberFormatter::append(std::string& str, Int64 value) void NumberFormatter::append(std::string& str, Int64 value)
{ {
char buffer[64]; char result[NF_MAX_NUM_STRING_SIZE];
std::sprintf(buffer, "%"I64_FMT"d", value); unsigned sz = NF_MAX_NUM_STRING_SIZE;
str.append(buffer); intToStr(value, 10, result, sz);
str.append(result, sz);
} }
void NumberFormatter::append(std::string& str, Int64 value, int width) void NumberFormatter::append(std::string& str, Int64 value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 10, result, sz, false, width, '0');
std::sprintf(buffer, "%*"I64_FMT"d", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::append0(std::string& str, Int64 value, int width) void NumberFormatter::append0(std::string& str, Int64 value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 10, result, sz, false, width, '0');
std::sprintf(buffer, "%0*"I64_FMT"d", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::appendHex(std::string& str, Int64 value) void NumberFormatter::appendHex(std::string& str, Int64 value)
{ {
char buffer[64]; char result[NF_MAX_NUM_STRING_SIZE];
std::sprintf(buffer, "%"I64_FMT"X", value); unsigned sz = NF_MAX_NUM_STRING_SIZE;
str.append(buffer); intToStr(value, 0x10, result, sz);
str.append(result, sz);
} }
void NumberFormatter::appendHex(std::string& str, Int64 value, int width) void NumberFormatter::appendHex(std::string& str, Int64 value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 0x10, result, sz, false, width, '0');
std::sprintf(buffer, "%0*"I64_FMT"X", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::append(std::string& str, UInt64 value) void NumberFormatter::append(std::string& str, UInt64 value)
{ {
char buffer[64]; char result[NF_MAX_NUM_STRING_SIZE];
std::sprintf(buffer, "%"I64_FMT"u", value); unsigned sz = NF_MAX_NUM_STRING_SIZE;
str.append(buffer); intToStr(value, 10, result, sz);
str.append(result, sz);
} }
void NumberFormatter::append(std::string& str, UInt64 value, int width) void NumberFormatter::append(std::string& str, UInt64 value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 10, result, sz, false, width, '0');
std::sprintf(buffer, "%*"I64_FMT"u", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::append0(std::string& str, UInt64 value, int width) void NumberFormatter::append0(std::string& str, UInt64 value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 10, result, sz, false, width, '0');
std::sprintf(buffer, "%0*"I64_FMT"u", width, value); str.append(result, sz);
str.append(buffer);
} }
void NumberFormatter::appendHex(std::string& str, UInt64 value) void NumberFormatter::appendHex(std::string& str, UInt64 value)
{ {
char buffer[64]; char result[NF_MAX_NUM_STRING_SIZE];
std::sprintf(buffer, "%"I64_FMT"X", value); unsigned sz = NF_MAX_NUM_STRING_SIZE;
str.append(buffer); intToStr(value, 0x10, result, sz);
str.append(result, sz);
} }
void NumberFormatter::appendHex(std::string& str, UInt64 value, int width) void NumberFormatter::appendHex(std::string& str, UInt64 value, int width)
{ {
poco_assert (width > 0 && width < 64); char result[NF_MAX_NUM_STRING_SIZE];
unsigned sz = NF_MAX_NUM_STRING_SIZE;
char buffer[64]; intToStr(value, 0x10, result, sz, false, width, '0');
std::sprintf(buffer, "%0*"I64_FMT"X", width, value); str.append(result, sz);
str.append(buffer);
} }

View File

@@ -68,6 +68,10 @@ void NumberFormatterTest::testFormat()
assert (NumberFormatter::format((unsigned long) 123) == "123"); assert (NumberFormatter::format((unsigned long) 123) == "123");
assert (NumberFormatter::format((unsigned long) 123, 5) == " 123"); assert (NumberFormatter::format((unsigned long) 123, 5) == " 123");
assert (NumberFormatter::format(123) == "123");
assert (NumberFormatter::format(-123) == "-123");
assert (NumberFormatter::format(-123, 5) == " -123");
#if defined(POCO_HAVE_INT64) #if defined(POCO_HAVE_INT64)
assert (NumberFormatter::format((Int64) 123) == "123"); assert (NumberFormatter::format((Int64) 123) == "123");
assert (NumberFormatter::format((Int64) -123) == "-123"); assert (NumberFormatter::format((Int64) -123) == "-123");
@@ -148,6 +152,50 @@ void NumberFormatterTest::testFormatHex()
assert (NumberFormatter::formatHex((UInt64) 0x12, 4) == "0012"); assert (NumberFormatter::formatHex((UInt64) 0x12, 4) == "0012");
assert (NumberFormatter::formatHex((UInt64) 0xab, 4) == "00AB"); assert (NumberFormatter::formatHex((UInt64) 0xab, 4) == "00AB");
#endif #endif
assert (NumberFormatter::formatHex(0x12, true) == "0x12");
assert (NumberFormatter::formatHex(0xab, true) == "0xAB");
assert (NumberFormatter::formatHex(0x12, 4, true) == "0x12");
assert (NumberFormatter::formatHex(0xab, 4, true) == "0xAB");
assert (NumberFormatter::formatHex(0x12, 6, true) == "0x0012");
assert (NumberFormatter::formatHex(0xab, 6, true) == "0x00AB");
assert (NumberFormatter::formatHex((unsigned) 0x12, true) == "0x12");
assert (NumberFormatter::formatHex((unsigned) 0xab, true) == "0xAB");
assert (NumberFormatter::formatHex((unsigned) 0x12, 4, true) == "0x12");
assert (NumberFormatter::formatHex((unsigned) 0xab, 4, true) == "0xAB");
assert (NumberFormatter::formatHex((unsigned) 0x12, 6, true) == "0x0012");
assert (NumberFormatter::formatHex((unsigned) 0xab, 6, true) == "0x00AB");
assert (NumberFormatter::formatHex((long) 0x12, true) == "0x12");
assert (NumberFormatter::formatHex((long) 0xab, true) == "0xAB");
assert (NumberFormatter::formatHex((long) 0x12, 4, true) == "0x12");
assert (NumberFormatter::formatHex((long) 0xab, 4, true) == "0xAB");
assert (NumberFormatter::formatHex((long) 0x12, 6, true) == "0x0012");
assert (NumberFormatter::formatHex((long) 0xab, 6, true) == "0x00AB");
assert (NumberFormatter::formatHex((unsigned long) 0x12, true) == "0x12");
assert (NumberFormatter::formatHex((unsigned long) 0xab, true) == "0xAB");
assert (NumberFormatter::formatHex((unsigned long) 0x12, 4, true) == "0x12");
assert (NumberFormatter::formatHex((unsigned long) 0xab, 4, true) == "0xAB");
assert (NumberFormatter::formatHex((unsigned long) 0x12, 6, true) == "0x0012");
assert (NumberFormatter::formatHex((unsigned long) 0xab, 6, true) == "0x00AB");
#if defined(POCO_HAVE_INT64)
assert (NumberFormatter::formatHex((Int64) 0x12, true) == "0x12");
assert (NumberFormatter::formatHex((Int64) 0xab, true) == "0xAB");
assert (NumberFormatter::formatHex((Int64) 0x12, 4, true) == "0x12");
assert (NumberFormatter::formatHex((Int64) 0xab, 4, true) == "0xAB");
assert (NumberFormatter::formatHex((Int64) 0x12, 6, true) == "0x0012");
assert (NumberFormatter::formatHex((Int64) 0xab, 6, true) == "0x00AB");
assert (NumberFormatter::formatHex((UInt64) 0x12, true) == "0x12");
assert (NumberFormatter::formatHex((UInt64) 0xab, true) == "0xAB");
assert (NumberFormatter::formatHex((UInt64) 0x12, 4, true) == "0x12");
assert (NumberFormatter::formatHex((UInt64) 0xab, 4, true) == "0xAB");
assert (NumberFormatter::formatHex((UInt64) 0x12, 6, true) == "0x0012");
assert (NumberFormatter::formatHex((UInt64) 0xab, 6, true) == "0x00AB");
#endif
} }

View File

@@ -217,6 +217,7 @@ void NumberParserTest::testLimits()
assert(testLowerLimit<Int16>()); assert(testLowerLimit<Int16>());
assert(testUpperLimit<UInt16>()); assert(testUpperLimit<UInt16>());
assert(testUpperLimit<Int32>()); assert(testUpperLimit<Int32>());
assert(testLowerLimit<Int32>());
assert(testUpperLimit<UInt32>()); assert(testUpperLimit<UInt32>());
#if defined(POCO_HAVE_INT64) #if defined(POCO_HAVE_INT64)

View File

@@ -37,6 +37,7 @@
#include "Poco/Format.h" #include "Poco/Format.h"
#include "Poco/MemoryStream.h" #include "Poco/MemoryStream.h"
#include "Poco/Stopwatch.h" #include "Poco/Stopwatch.h"
#include "Poco/Exception.h"
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <cstdio> #include <cstdio>
@@ -60,11 +61,13 @@ using Poco::replaceInPlace;
using Poco::cat; using Poco::cat;
using Poco::strToInt; using Poco::strToInt;
using Poco::strToFloat; using Poco::strToFloat;
using Poco::intToStr;
using Poco::thousandSeparator; using Poco::thousandSeparator;
using Poco::decimalSeparator; using Poco::decimalSeparator;
using Poco::format; using Poco::format;
using Poco::MemoryInputStream; using Poco::MemoryInputStream;
using Poco::Stopwatch; using Poco::Stopwatch;
using Poco::RangeException;
StringTest::StringTest(const std::string& name): CppUnit::TestCase(name) StringTest::StringTest(const std::string& name): CppUnit::TestCase(name)
@@ -690,6 +693,106 @@ void StringTest::benchmarkStrToFloat()
} }
void StringTest::testIntToString()
{
//intToStr(T number, unsigned short base, std::string& result, bool prefix = false, int width = -1, char fill = ' ', char thSep = 0)
// decimal
std::string result;
assert (intToStr(0, 10, result));
assert (result == "0");
assert (intToStr(0, 10, result, false, 10, '0'));
assert (result == "0000000000");
assert (intToStr(1234567890, 10, result));
assert (result == "1234567890");
assert (intToStr(-1234567890, 10, result));
assert (result == "-1234567890");
assert (intToStr(-1234567890, 10, result, false, 15, '0'));
assert (result == "-00001234567890");
assert (intToStr(-1234567890, 10, result, false, 15));
assert (result == " -1234567890");
assert (intToStr(-1234567890, 10, result, false, 0, 0, ','));
assert (result == "-1,234,567,890");
// binary
assert (intToStr(1234567890, 2, result));
assert (result == "1001001100101100000001011010010");
assert (intToStr(1234567890, 2, result, true));
assert (result == "1001001100101100000001011010010");
assert (intToStr(1234567890, 2, result, true, 35, '0'));
assert (result == "00001001001100101100000001011010010");
assert (intToStr(0xFF, 2, result));
assert (result == "11111111");
assert (intToStr(0x0F, 2, result, false, 8, '0'));
assert (result == "00001111");
assert (intToStr(0x0F, 2, result));
assert (result == "1111");
assert (intToStr(0xF0, 2, result));
assert (result == "11110000");
assert (intToStr(0xFFFF, 2, result));
assert (result == "1111111111111111");
assert (intToStr(0xFF00, 2, result));
assert (result == "1111111100000000");
assert (intToStr(0xFFFFFFFF, 2, result));
assert (result == "11111111111111111111111111111111");
assert (intToStr(0xFF00FF00, 2, result));
assert (result == "11111111000000001111111100000000");
assert (intToStr(0xF0F0F0F0, 2, result));
assert (result == "11110000111100001111000011110000");
#if defined(POCO_HAVE_INT64)
assert (intToStr(0xFFFFFFFFFFFFFFFF, 2, result));
std::cout << 0xFFFFFFFFFFFFFFFF << std::endl;
assert (result == "1111111111111111111111111111111111111111111111111111111111111111");
assert (intToStr(0xFF00000FF00000FF, 2, result));
assert (result == "1111111100000000000000000000111111110000000000000000000011111111");
#endif
// octal
assert (intToStr(1234567890, 010, result));
assert (result == "11145401322");
assert (intToStr(1234567890, 010, result, true));
assert (result == "011145401322");
assert (intToStr(1234567890, 010, result, true, 15, '0'));
assert (result == "000011145401322");
assert (intToStr(012345670, 010, result, true));
assert (result == "012345670");
assert (intToStr(012345670, 010, result));
assert (result == "12345670");
// hexadecimal
assert (intToStr(0, 0x10, result, true));
assert (result == "0x0");
assert (intToStr(0, 0x10, result, true, 4, '0'));
assert (result == "0x00");
assert (intToStr(0, 0x10, result, false, 4, '0'));
assert (result == "0000");
assert (intToStr(1234567890, 0x10, result));
assert (result == "499602D2");
assert (intToStr(1234567890, 0x10, result, true));
assert (result == "0x499602D2");
assert (intToStr(1234567890, 0x10, result, true, 15, '0'));
assert (result == "0x00000499602D2");
assert (intToStr(0x1234567890ABCDEF, 0x10, result, true));
assert (result == "0x1234567890ABCDEF");
assert (intToStr(0xDEADBEEF, 0x10, result));
assert (result == "DEADBEEF");
#if defined(POCO_HAVE_INT64)
assert (intToStr(0xFFFFFFFFFFFFFFFF, 0x10, result));
assert (result == "FFFFFFFFFFFFFFFF");
assert (intToStr(0xFFFFFFFFFFFFFFFF, 0x10, result, true));
assert (result == "0xFFFFFFFFFFFFFFFF");
#endif
try
{
char pResult[POCO_MAX_NUM_STRING_LEN];
unsigned sz = POCO_MAX_NUM_STRING_LEN;
intToStr(0, 10, pResult, sz, false, sz + 1, ' ');
fail ("must throw RangeException");
} catch (RangeException&) { }
}
void StringTest::setUp() void StringTest::setUp()
{ {
} }
@@ -724,6 +827,7 @@ CppUnit::Test* StringTest::suite()
CppUnit_addTest(pSuite, StringTest, testNumericLocale); CppUnit_addTest(pSuite, StringTest, testNumericLocale);
//CppUnit_addTest(pSuite, StringTest, benchmarkStrToFloat); //CppUnit_addTest(pSuite, StringTest, benchmarkStrToFloat);
//CppUnit_addTest(pSuite, StringTest, benchmarkStrToInt); //CppUnit_addTest(pSuite, StringTest, benchmarkStrToInt);
CppUnit_addTest(pSuite, StringTest, testIntToString);
return pSuite; return pSuite;
} }

View File

@@ -70,6 +70,8 @@ public:
void benchmarkStrToFloat(); void benchmarkStrToFloat();
void benchmarkStrToInt(); void benchmarkStrToInt();
void testIntToString();
void setUp(); void setUp();
void tearDown(); void tearDown();