mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-04 19:25:51 +00:00
Fix String from number conversions
This commit is contained in:
@@ -129,7 +129,6 @@
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\beast_SparseSet.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\DynamicList.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\beast_Variant.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\lashMap.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\diagnostic\beast_Debug.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\diagnostic\beast_Error.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\diagnostic\beast_FatalError.h" />
|
||||
@@ -237,6 +236,8 @@
|
||||
<ClInclude Include="..\..\modules\beast_core\text\beast_StringPairArray.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\text\beast_StringPool.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\text\beast_TextDiff.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\text\StringCharPointerType.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\text\StringFromNumber.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\beast_ChildProcess.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\beast_CriticalSection.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\beast_DynamicLibrary.h" />
|
||||
|
||||
@@ -935,6 +935,12 @@
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\detail\removecv.h">
|
||||
<Filter>beast_core\containers\detail</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\text\StringCharPointerType.h">
|
||||
<Filter>beast_core\text</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\text\StringFromNumber.h">
|
||||
<Filter>beast_core\text</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\modules\beast_core\beast_core.cpp">
|
||||
|
||||
@@ -271,6 +271,8 @@ extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) n
|
||||
#include "containers/beast_LockFreeStack.h"
|
||||
#include "threads/beast_SpinDelay.h"
|
||||
#include "memory/beast_StaticObject.h"
|
||||
# include "text/StringCharPointerType.h"
|
||||
# include "text/StringFromNumber.h"
|
||||
#include "text/beast_String.h"
|
||||
#include "memory/beast_MemoryAlignment.h"
|
||||
#include "memory/beast_CacheLine.h"
|
||||
|
||||
54
modules/beast_core/text/StringCharPointerType.h
Normal file
54
modules/beast_core/text/StringCharPointerType.h
Normal file
@@ -0,0 +1,54 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_STRINGCHARPOINTERTYPE_H_INCLUDED
|
||||
#define BEAST_STRINGCHARPOINTERTYPE_H_INCLUDED
|
||||
|
||||
/** This is the character encoding type used internally to store the string.
|
||||
|
||||
By setting the value of BEAST_STRING_UTF_TYPE to 8, 16, or 32, you can change the
|
||||
internal storage format of the String class. UTF-8 uses the least space (if your strings
|
||||
contain few extended characters), but call operator[] involves iterating the string to find
|
||||
the required index. UTF-32 provides instant random access to its characters, but uses 4 bytes
|
||||
per character to store them. UTF-16 uses more space than UTF-8 and is also slow to index,
|
||||
but is the native wchar_t format used in Windows.
|
||||
|
||||
It doesn't matter too much which format you pick, because the toUTF8(), toUTF16() and
|
||||
toUTF32() methods let you access the string's content in any of the other formats.
|
||||
*/
|
||||
#if (BEAST_STRING_UTF_TYPE == 32)
|
||||
typedef CharPointer_UTF32 StringCharPointerType;
|
||||
|
||||
#elif (BEAST_STRING_UTF_TYPE == 16)
|
||||
typedef CharPointer_UTF16 StringCharPointerType;
|
||||
|
||||
#elif (BEAST_STRING_UTF_TYPE == 8)
|
||||
typedef CharPointer_UTF8 StringCharPointerType;
|
||||
|
||||
#else
|
||||
#error "You must set the value of BEAST_STRING_UTF_TYPE to be either 8, 16, or 32!"
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
159
modules/beast_core/text/StringFromNumber.h
Normal file
159
modules/beast_core/text/StringFromNumber.h
Normal file
@@ -0,0 +1,159 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.beast.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CORE_STRINGFROMNUMBER_H_INCLUDED
|
||||
#define BEAST_CORE_STRINGFROMNUMBER_H_INCLUDED
|
||||
|
||||
// This is private!
|
||||
//
|
||||
class NumberToStringConverters
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
charsNeededForInt = 32,
|
||||
charsNeededForDouble = 48
|
||||
};
|
||||
|
||||
// pass in a pointer to the END of a buffer..
|
||||
template <typename Type>
|
||||
static char* printDigits (char* t, Type v) noexcept
|
||||
{
|
||||
*--t = 0;
|
||||
do
|
||||
{
|
||||
*--t = '0' + (char) (v % 10);
|
||||
v /= 10;
|
||||
}
|
||||
while (v > 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4127) // conditional expression is constant
|
||||
#pragma warning (disable: 4146) // unary minus operator applied to unsigned type, result still unsigned
|
||||
#endif
|
||||
// pass in a pointer to the END of a buffer..
|
||||
template <typename IntegerType>
|
||||
static char* numberToString (char* t, IntegerType const n) noexcept
|
||||
{
|
||||
if (std::numeric_limits <IntegerType>::is_signed)
|
||||
{
|
||||
if (n >= 0)
|
||||
return printDigits (t, static_cast <uint64> (n));
|
||||
|
||||
// NB: this needs to be careful not to call
|
||||
// -std::numeric_limits<int64>::min(),
|
||||
// which has undefined behaviour
|
||||
//
|
||||
t = printDigits (t, static_cast <uint64> (-(n + 1)) + 1);
|
||||
*--t = '-';
|
||||
return t;
|
||||
}
|
||||
return printDigits (t, n);
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
struct StackArrayStream : public std::basic_streambuf <char, std::char_traits <char> >
|
||||
{
|
||||
explicit StackArrayStream (char* d)
|
||||
{
|
||||
imbue (std::locale::classic());
|
||||
setp (d, d + charsNeededForDouble);
|
||||
}
|
||||
|
||||
size_t writeDouble (double n, int numDecPlaces)
|
||||
{
|
||||
{
|
||||
std::ostream o (this);
|
||||
|
||||
if (numDecPlaces > 0)
|
||||
o.precision ((std::streamsize) numDecPlaces);
|
||||
|
||||
o << n;
|
||||
}
|
||||
|
||||
return (size_t) (pptr() - pbase());
|
||||
}
|
||||
};
|
||||
|
||||
static char* doubleToString (char* buffer,
|
||||
const int numChars, double n, int numDecPlaces, size_t& len) noexcept
|
||||
{
|
||||
if (numDecPlaces > 0 && numDecPlaces < 7 && n > -1.0e20 && n < 1.0e20)
|
||||
{
|
||||
char* const end = buffer + numChars;
|
||||
char* t = end;
|
||||
int64 v = (int64) (pow (10.0, numDecPlaces) * std::abs (n) + 0.5);
|
||||
*--t = (char) 0;
|
||||
|
||||
while (numDecPlaces >= 0 || v > 0)
|
||||
{
|
||||
if (numDecPlaces == 0)
|
||||
*--t = '.';
|
||||
|
||||
*--t = (char) ('0' + (v % 10));
|
||||
|
||||
v /= 10;
|
||||
--numDecPlaces;
|
||||
}
|
||||
|
||||
if (n < 0)
|
||||
*--t = '-';
|
||||
|
||||
len = (size_t) (end - t - 1);
|
||||
return t;
|
||||
}
|
||||
|
||||
StackArrayStream strm (buffer);
|
||||
len = strm.writeDouble (n, numDecPlaces);
|
||||
bassert (len <= charsNeededForDouble);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static StringCharPointerType createFromFixedLength (
|
||||
const char* const src, const size_t numChars);
|
||||
|
||||
template <typename IntegerType>
|
||||
static StringCharPointerType createFromInteger (const IntegerType number)
|
||||
{
|
||||
char buffer [charsNeededForInt];
|
||||
char* const end = buffer + numElementsInArray (buffer);
|
||||
char* const start = numberToString (end, number);
|
||||
return createFromFixedLength (start, (size_t) (end - start - 1));
|
||||
}
|
||||
|
||||
static StringCharPointerType createFromDouble (
|
||||
const double number, const int numberOfDecimalPlaces)
|
||||
{
|
||||
char buffer [charsNeededForDouble];
|
||||
size_t len;
|
||||
char* const start = doubleToString (buffer, numElementsInArray (buffer), (double) number, numberOfDecimalPlaces, len);
|
||||
return createFromFixedLength (start, len);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -235,13 +235,24 @@ private:
|
||||
StringHolder StringHolder::empty;
|
||||
const String String::empty;
|
||||
|
||||
//==============================================================================
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
StringCharPointerType NumberToStringConverters::createFromFixedLength (
|
||||
const char* const src, const size_t numChars)
|
||||
{
|
||||
return StringHolder::createFromFixedLength (src, numChars);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void String::preallocateBytes (const size_t numBytesNeeded)
|
||||
{
|
||||
text = StringHolder::makeUniqueWithByteSize (text, numBytesNeeded + sizeof (CharPointerType::CharType));
|
||||
text = StringHolder::makeUniqueWithByteSize (
|
||||
text, numBytesNeeded + sizeof (CharPointerType::CharType));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
String::String() noexcept : text (StringHolder::getEmpty())
|
||||
{
|
||||
}
|
||||
@@ -356,130 +367,7 @@ String String::charToString (const beast_wchar character)
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
namespace NumberToStringConverters
|
||||
{
|
||||
enum
|
||||
{
|
||||
charsNeededForInt = 32,
|
||||
charsNeededForDouble = 48
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
static char* printDigits (char* t, Type v) noexcept
|
||||
{
|
||||
*--t = 0;
|
||||
|
||||
do
|
||||
{
|
||||
*--t = '0' + (char) (v % 10);
|
||||
v /= 10;
|
||||
|
||||
} while (v > 0);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4127) // conditional expression is constant
|
||||
#pragma warning (disable: 4146) // unary minus operator applied to unsigned type, result still unsigned
|
||||
#endif
|
||||
// pass in a pointer to the END of a buffer..
|
||||
template <typename IntegerType>
|
||||
static char* numberToString (char* t, IntegerType const n) noexcept
|
||||
{
|
||||
if (std::numeric_limits <IntegerType>::is_signed)
|
||||
{
|
||||
if (n >= 0)
|
||||
return printDigits (t, static_cast <uint64> (n));
|
||||
|
||||
// NB: this needs to be careful not to call -std::numeric_limits<int64>::min(),
|
||||
// which has undefined behaviour
|
||||
t = printDigits (t, static_cast <uint64> (-(n + 1)) + 1);
|
||||
*--t = '-';
|
||||
return t;
|
||||
}
|
||||
return printDigits (t, n);
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
struct StackArrayStream : public std::basic_streambuf<char, std::char_traits<char> >
|
||||
{
|
||||
explicit StackArrayStream (char* d)
|
||||
{
|
||||
imbue (std::locale::classic());
|
||||
setp (d, d + charsNeededForDouble);
|
||||
}
|
||||
|
||||
size_t writeDouble (double n, int numDecPlaces)
|
||||
{
|
||||
{
|
||||
std::ostream o (this);
|
||||
|
||||
if (numDecPlaces > 0)
|
||||
o.precision ((std::streamsize) numDecPlaces);
|
||||
|
||||
o << n;
|
||||
}
|
||||
|
||||
return (size_t) (pptr() - pbase());
|
||||
}
|
||||
};
|
||||
|
||||
static char* doubleToString (char* buffer, const int numChars, double n, int numDecPlaces, size_t& len) noexcept
|
||||
{
|
||||
if (numDecPlaces > 0 && numDecPlaces < 7 && n > -1.0e20 && n < 1.0e20)
|
||||
{
|
||||
char* const end = buffer + numChars;
|
||||
char* t = end;
|
||||
int64 v = (int64) (pow (10.0, numDecPlaces) * std::abs (n) + 0.5);
|
||||
*--t = (char) 0;
|
||||
|
||||
while (numDecPlaces >= 0 || v > 0)
|
||||
{
|
||||
if (numDecPlaces == 0)
|
||||
*--t = '.';
|
||||
|
||||
*--t = (char) ('0' + (v % 10));
|
||||
|
||||
v /= 10;
|
||||
--numDecPlaces;
|
||||
}
|
||||
|
||||
if (n < 0)
|
||||
*--t = '-';
|
||||
|
||||
len = (size_t) (end - t - 1);
|
||||
return t;
|
||||
}
|
||||
|
||||
StackArrayStream strm (buffer);
|
||||
len = strm.writeDouble (n, numDecPlaces);
|
||||
bassert (len <= charsNeededForDouble);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
template <typename IntegerType>
|
||||
static String::CharPointerType createFromInteger (const IntegerType number)
|
||||
{
|
||||
char buffer [charsNeededForInt];
|
||||
char* const end = buffer + numElementsInArray (buffer);
|
||||
char* const start = numberToString (end, number);
|
||||
return StringHolder::createFromFixedLength (start, (size_t) (end - start - 1));
|
||||
}
|
||||
|
||||
static String::CharPointerType createFromDouble (const double number, const int numberOfDecimalPlaces)
|
||||
{
|
||||
char buffer [charsNeededForDouble];
|
||||
size_t len;
|
||||
char* const start = doubleToString (buffer, numElementsInArray (buffer), (double) number, numberOfDecimalPlaces, len);
|
||||
return StringHolder::createFromFixedLength (start, len);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
String::String (const int number) : text (NumberToStringConverters::createFromInteger (number)) {}
|
||||
String::String (const unsigned int number) : text (NumberToStringConverters::createFromInteger (number)) {}
|
||||
String::String (const short number) : text (NumberToStringConverters::createFromInteger ((int) number)) {}
|
||||
@@ -492,40 +380,6 @@ String::String (const double number) : text (NumberToStringConverters::c
|
||||
String::String (const float number, const int numberOfDecimalPlaces) : text (NumberToStringConverters::createFromDouble ((double) number, numberOfDecimalPlaces)) {}
|
||||
String::String (const double number, const int numberOfDecimalPlaces) : text (NumberToStringConverters::createFromDouble (number, numberOfDecimalPlaces)) {}
|
||||
|
||||
template <typename Number>
|
||||
String String::fromNumber (Number number, int)
|
||||
{
|
||||
return String (NumberToStringConverters::createFromInteger <Number> (number), FromNumber ());
|
||||
}
|
||||
|
||||
template <>
|
||||
String String::fromNumber <float> (float number, int numberOfDecimalPlaces)
|
||||
{
|
||||
if (numberOfDecimalPlaces == 0)
|
||||
number = std::floor (number);
|
||||
|
||||
return String (NumberToStringConverters::createFromDouble (
|
||||
number, numberOfDecimalPlaces));
|
||||
}
|
||||
|
||||
template <>
|
||||
String String::fromNumber <double> (double number, int numberOfDecimalPlaces)
|
||||
{
|
||||
if (numberOfDecimalPlaces == 0)
|
||||
number = std::floor (number);
|
||||
|
||||
return String (NumberToStringConverters::createFromDouble (
|
||||
number, numberOfDecimalPlaces));
|
||||
}
|
||||
|
||||
template String String::fromNumber <int16> (int16, int);
|
||||
template String String::fromNumber <int32> (int32, int);
|
||||
template String String::fromNumber <int64> (int64, int);
|
||||
template String String::fromNumber <uint16> (uint16, int);
|
||||
template String String::fromNumber <uint32> (uint32, int);
|
||||
template String String::fromNumber <uint64> (uint64, int);
|
||||
template String String::fromNumber <std::size_t> (std::size_t, int);
|
||||
|
||||
//==============================================================================
|
||||
int String::length() const noexcept
|
||||
{
|
||||
|
||||
@@ -153,27 +153,8 @@ public:
|
||||
*/
|
||||
static const String empty;
|
||||
|
||||
/** This is the character encoding type used internally to store the string.
|
||||
|
||||
By setting the value of BEAST_STRING_UTF_TYPE to 8, 16, or 32, you can change the
|
||||
internal storage format of the String class. UTF-8 uses the least space (if your strings
|
||||
contain few extended characters), but call operator[] involves iterating the string to find
|
||||
the required index. UTF-32 provides instant random access to its characters, but uses 4 bytes
|
||||
per character to store them. UTF-16 uses more space than UTF-8 and is also slow to index,
|
||||
but is the native wchar_t format used in Windows.
|
||||
|
||||
It doesn't matter too much which format you pick, because the toUTF8(), toUTF16() and
|
||||
toUTF32() methods let you access the string's content in any of the other formats.
|
||||
*/
|
||||
#if (BEAST_STRING_UTF_TYPE == 32)
|
||||
typedef CharPointer_UTF32 CharPointerType;
|
||||
#elif (BEAST_STRING_UTF_TYPE == 16)
|
||||
typedef CharPointer_UTF16 CharPointerType;
|
||||
#elif (BEAST_STRING_UTF_TYPE == 8)
|
||||
typedef CharPointer_UTF8 CharPointerType;
|
||||
#else
|
||||
#error "You must set the value of BEAST_STRING_UTF_TYPE to be either 8, 16, or 32!"
|
||||
#endif
|
||||
/** This is the character encoding type used internally to store the string. */
|
||||
typedef StringCharPointerType CharPointerType;
|
||||
|
||||
//==============================================================================
|
||||
/** Generates a probably-unique 32-bit hashcode from this string. */
|
||||
@@ -1215,7 +1196,36 @@ private:
|
||||
operator bool() const noexcept { return false; }
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <typename Number>
|
||||
inline String String::fromNumber (Number number, int)
|
||||
{
|
||||
return String (NumberToStringConverters::createFromInteger
|
||||
<Number> (number), FromNumber ());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline String String::fromNumber <float> (float number, int numberOfDecimalPlaces)
|
||||
{
|
||||
if (numberOfDecimalPlaces == 0)
|
||||
number = std::floor (number);
|
||||
return String (NumberToStringConverters::createFromDouble (
|
||||
number, numberOfDecimalPlaces));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline String String::fromNumber <double> (double number, int numberOfDecimalPlaces)
|
||||
{
|
||||
if (numberOfDecimalPlaces == 0)
|
||||
number = std::floor (number);
|
||||
|
||||
return String (NumberToStringConverters::createFromDouble (
|
||||
number, numberOfDecimalPlaces));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Concatenates two strings. */
|
||||
BEAST_API String BEAST_CALLTYPE operator+ (const char* string1, const String& string2);
|
||||
/** Concatenates two strings. */
|
||||
|
||||
Reference in New Issue
Block a user