1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-10-18 17:07:17 +02:00

Update POCO to 1.11.0

This commit is contained in:
Sandu Liviu Catalin
2021-08-22 18:07:06 +03:00
parent 151077c799
commit 7a3d92d1d1
450 changed files with 25219 additions and 6528 deletions

View File

@@ -21,8 +21,8 @@ namespace Poco {
//
// TraverseBase
//
TraverseBase::TraverseBase(DepthFun depthDeterminer, UInt16 maxDepth)
: _depthDeterminer(depthDeterminer), _maxDepth(maxDepth)
TraverseBase::TraverseBase(DepthFun depthDeterminer, UInt16 maxDepth):
_depthDeterminer(depthDeterminer), _maxDepth(maxDepth)
{
}
@@ -49,8 +49,8 @@ bool TraverseBase::isDirectory(Poco::File& file)
//
// ChildrenFirstTraverse
//
ChildrenFirstTraverse::ChildrenFirstTraverse(DepthFun depthDeterminer, UInt16 maxDepth)
: TraverseBase(depthDeterminer, maxDepth)
ChildrenFirstTraverse::ChildrenFirstTraverse(DepthFun depthDeterminer, UInt16 maxDepth):
TraverseBase(depthDeterminer, maxDepth)
{
}
@@ -61,10 +61,6 @@ const std::string ChildrenFirstTraverse::next(Stack* itStack, bool* isFinished)
poco_check_ptr(isFinished);
poco_assert(!(*isFinished));
std::stack<DirectoryIterator> it;
//_depthDeterminer(it);
// go deeper into not empty directory
// (if depth limit allows)
bool isDepthLimitReached = isFiniteDepth() && _depthDeterminer(*itStack) >= _maxDepth;
@@ -106,8 +102,8 @@ const std::string ChildrenFirstTraverse::next(Stack* itStack, bool* isFinished)
//
// SiblingsFirstTraverse
//
SiblingsFirstTraverse::SiblingsFirstTraverse(DepthFun depthDeterminer, UInt16 maxDepth)
: TraverseBase(depthDeterminer, maxDepth)
SiblingsFirstTraverse::SiblingsFirstTraverse(DepthFun depthDeterminer, UInt16 maxDepth):
TraverseBase(depthDeterminer, maxDepth)
{
_dirsStack.push(std::queue<std::string>());
}

View File

@@ -12,6 +12,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "Poco/Environment.h"
#include "Poco/Version.h"
#include <cstdlib>

View File

@@ -25,6 +25,11 @@
#include <iphlpapi.h>
#if defined(_MSC_VER)
#pragma warning(disable:4996) // deprecation warnings
#endif
namespace Poco {

View File

@@ -12,6 +12,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
// pull in platform identification macros needed below
#include "Poco/Platform.h"
#include "Poco/FPEnvironment.h"

View File

@@ -336,20 +336,22 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
struct stat st;
if (fstat(sd, &st) != 0)
{
int err = errno;
close(sd);
handleLastErrorImpl(_path);
handleLastErrorImpl(err, _path);
}
const long blockSize = st.st_blksize;
int dd;
if (options & OPT_FAIL_ON_OVERWRITE_IMPL) {
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_EXCL | O_WRONLY, st.st_mode);
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_EXCL | O_WRONLY, st.st_mode);
} else {
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode);
}
if (dd == -1)
{
int err = errno;
close(sd);
handleLastErrorImpl(path);
handleLastErrorImpl(err, path);
}
Buffer<char> buffer(blockSize);
try
@@ -361,7 +363,9 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
handleLastErrorImpl(path);
}
if (n < 0)
{
handleLastErrorImpl(_path);
}
}
catch (...)
{
@@ -372,11 +376,14 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
close(sd);
if (fsync(dd) != 0)
{
int err = errno;
close(dd);
handleLastErrorImpl(path);
handleLastErrorImpl(err, path);
}
if (close(dd) != 0)
{
handleLastErrorImpl(path);
}
}
@@ -387,7 +394,7 @@ void FileImpl::renameToImpl(const std::string& path, int options)
struct stat st;
if (stat(path.c_str(), &st) == 0 && (options & OPT_FAIL_ON_OVERWRITE_IMPL))
throw FileExistsException(path, EEXIST);
throw FileExistsException(path, EEXIST);
if (rename(_path.c_str(), path.c_str()) != 0)
handleLastErrorImpl(_path);
@@ -490,43 +497,49 @@ FileImpl::FileSizeImpl FileImpl::freeSpaceImpl() const
}
void FileImpl::handleLastErrorImpl(const std::string& path)
void FileImpl::handleLastErrorImpl(int err, const std::string& path)
{
switch (errno)
switch (err)
{
case EIO:
throw IOException(path, errno);
throw IOException(path, err);
case EPERM:
throw FileAccessDeniedException("insufficient permissions", path, errno);
throw FileAccessDeniedException("insufficient permissions", path, err);
case EACCES:
throw FileAccessDeniedException(path, errno);
throw FileAccessDeniedException(path, err);
case ENOENT:
throw FileNotFoundException(path, errno);
throw FileNotFoundException(path, err);
case ENOTDIR:
throw OpenFileException("not a directory", path, errno);
throw OpenFileException("not a directory", path, err);
case EISDIR:
throw OpenFileException("not a file", path, errno);
throw OpenFileException("not a file", path, err);
case EROFS:
throw FileReadOnlyException(path, errno);
throw FileReadOnlyException(path, err);
case EEXIST:
throw FileExistsException(path, errno);
throw FileExistsException(path, err);
case ENOSPC:
throw FileException("no space left on device", path, errno);
throw FileException("no space left on device", path, err);
case EDQUOT:
throw FileException("disk quota exceeded", path, errno);
throw FileException("disk quota exceeded", path, err);
#if !defined(_AIX)
case ENOTEMPTY:
throw DirectoryNotEmptyException(path, errno);
throw DirectoryNotEmptyException(path, err);
#endif
case ENAMETOOLONG:
throw PathSyntaxException(path, errno);
throw PathSyntaxException(path, err);
case ENFILE:
case EMFILE:
throw FileException("too many open files", path, errno);
throw FileException("too many open files", path, err);
default:
throw FileException(Error::getMessage(errno), path, errno);
throw FileException(Error::getMessage(err), path, err);
}
}
void FileImpl::handleLastErrorImpl(const std::string& path)
{
handleLastErrorImpl(errno, path);
}
} // namespace Poco

View File

@@ -49,8 +49,7 @@ void writeString(const std::string &value, T& obj, typename WriteFunc<T, S>::Typ
{
for(std::string::const_iterator it = value.begin(), end = value.end(); it != end; ++it)
{
// Forward slash isn't strictly required by JSON spec, but some parsers expect it
if((*it >= 0 && *it <= 31) || (*it == '"') || (*it == '\\') || (*it == '/'))
if((*it >= 0 && *it <= 31) || (*it == '"') || (*it == '\\'))
{
std::string str = Poco::UTF8::escape(it, it + 1, true);
(obj.*write)(str.c_str(), str.size());

View File

@@ -12,6 +12,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "Poco/LocalDateTime.h"
#include "Poco/Timezone.h"
#include "Poco/Timespan.h"
@@ -99,7 +104,7 @@ LocalDateTime::LocalDateTime(Timestamp::UtcTimeVal utcTime, Timestamp::TimeDiff
adjustForTzd();
}
LocalDateTime::~LocalDateTime()
{
}
@@ -179,31 +184,31 @@ bool LocalDateTime::operator == (const LocalDateTime& dateTime) const
}
bool LocalDateTime::operator != (const LocalDateTime& dateTime) const
bool LocalDateTime::operator != (const LocalDateTime& dateTime) const
{
return utcTime() != dateTime.utcTime();
}
bool LocalDateTime::operator < (const LocalDateTime& dateTime) const
bool LocalDateTime::operator < (const LocalDateTime& dateTime) const
{
return utcTime() < dateTime.utcTime();
}
bool LocalDateTime::operator <= (const LocalDateTime& dateTime) const
bool LocalDateTime::operator <= (const LocalDateTime& dateTime) const
{
return utcTime() <= dateTime.utcTime();
}
bool LocalDateTime::operator > (const LocalDateTime& dateTime) const
bool LocalDateTime::operator > (const LocalDateTime& dateTime) const
{
return utcTime() > dateTime.utcTime();
}
bool LocalDateTime::operator >= (const LocalDateTime& dateTime) const
bool LocalDateTime::operator >= (const LocalDateTime& dateTime) const
{
return utcTime() >= dateTime.utcTime();
}
@@ -270,7 +275,7 @@ void LocalDateTime::determineTzd(bool adjust)
_tzd = (Timezone::utcOffset() + ((broken->tm_isdst == 1) ? 3600 : 0));
#else
std::tm broken;
#if defined(POCO_VXWORKS)
#if defined(POCO_VXWORKS) && (defined(_VXWORKS_COMPATIBILITY_MODE) || (defined(_WRS_VXWORKS_MAJOR) && ((_WRS_VXWORKS_MAJOR < 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR < 9)))))
if (localtime_r(&epochTime, &broken) != OK)
throw Poco::SystemException("cannot get local time");
#else
@@ -307,7 +312,7 @@ std::time_t LocalDateTime::dstOffset(int& dstOffset) const
#else
local = std::mktime(&broken);
#endif
dstOffset = (broken.tm_isdst == 1) ? 3600 : 0;
return local;
}

View File

@@ -12,6 +12,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "Poco/NumberFormatter.h"
#include "Poco/MemoryStream.h"
#include <iomanip>
@@ -31,26 +36,22 @@
#endif
namespace Poco {
std::string NumberFormatter::format(bool value, BoolFormat format)
{
switch(format)
switch (format)
{
default:
case FMT_TRUE_FALSE:
if (value == true)
return "true";
return "false";
case FMT_YES_NO:
if (value == true)
return "yes";
return "no";
case FMT_ON_OFF:
if (value == true)
return "on";
return "off";
case FMT_YES_NO:
return value ? "yes" : "no";
case FMT_ON_OFF:
return value ? "on" : "off";
default: // including FMT_TRUE_FALSE:
return value ? "true" : "false";
}
}

View File

@@ -16,8 +16,8 @@
// +++ double conversion +++
#define double_conversion poco_double_conversion // don't collide with standalone double_conversion library
#define UNREACHABLE poco_bugcheck
// don't collide with standalone double_conversion library
#define double_conversion poco_double_conversion
#define UNIMPLEMENTED poco_bugcheck
#include "diy-fp.cc"
#include "cached-powers.cc"
@@ -51,7 +51,7 @@ void pad(std::string& str, int precision, int width, char prefix = ' ', char dec
std::string::size_type decSepPos = str.find(decSep);
if (decSepPos == std::string::npos)
{
str.append(1, '.');
str.append(1, decSep);
decSepPos = str.size() - 1;
}

View File

@@ -23,6 +23,7 @@
#include "Poco/Environment.h"
#include "Poco/NumberParser.h"
#include "Poco/StringTokenizer.h"
#include "Poco/Path.h"
namespace Poco {
@@ -31,10 +32,11 @@ namespace Poco {
const std::string PatternFormatter::PROP_PATTERN = "pattern";
const std::string PatternFormatter::PROP_TIMES = "times";
const std::string PatternFormatter::PROP_PRIORITY_NAMES = "priorityNames";
const std::string PatternFormatter::DEFAULT_PRIORITY_NAMES = "Fatal,Critical,Error,Warning,Notice,Information,Debug,Trace";
PatternFormatter::PatternFormatter():
_localTime(false)
_localTime(false),
_priorityNames(DEFAULT_PRIORITY_NAMES)
{
parsePriorityNames();
}
@@ -42,7 +44,8 @@ PatternFormatter::PatternFormatter():
PatternFormatter::PatternFormatter(const std::string& format):
_localTime(false),
_pattern(format)
_pattern(format),
_priorityNames(DEFAULT_PRIORITY_NAMES)
{
parsePriorityNames();
parsePattern();
@@ -79,6 +82,7 @@ void PatternFormatter::format(const Message& msg, std::string& text)
case 'I': NumberFormatter::append(text, msg.getTid()); break;
case 'N': text.append(Environment::nodeName()); break;
case 'U': text.append(msg.getSourceFile() ? msg.getSourceFile() : ""); break;
case 'O': text.append(msg.getSourceFile() ? Path(msg.getSourceFile()).getFileName() : ""); break;
case 'u': NumberFormatter::append(text, msg.getSourceLine()); break;
case 'w': text.append(DateTimeFormat::WEEKDAY_NAMES[dateTime.dayOfWeek()], 0, 3); break;
case 'W': text.append(DateTimeFormat::WEEKDAY_NAMES[dateTime.dayOfWeek()]); break;
@@ -230,48 +234,24 @@ std::string PatternFormatter::getProperty(const std::string& name) const
}
namespace
{
static std::string priorities[] =
{
"",
"Fatal",
"Critical",
"Error",
"Warning",
"Notice",
"Information",
"Debug",
"Trace"
};
}
void PatternFormatter::parsePriorityNames()
{
for (int i = 0; i <= 8; i++)
StringTokenizer st(_priorityNames, ",;", StringTokenizer::TOK_TRIM);
if (st.count() == 8)
{
_priorities[i] = priorities[i];
}
if (!_priorityNames.empty())
{
StringTokenizer st(_priorityNames, ",;", StringTokenizer::TOK_TRIM);
if (st.count() == 8)
for (int i = 1; i <= 8; i++)
{
for (int i = 1; i <= 8; i++)
{
_priorities[i] = st[i - 1];
}
_priorities[i] = st[i - 1];
}
else throw Poco::SyntaxException("priorityNames property must specify a comma-separated list of 8 property names");
}
else throw Poco::SyntaxException("priorityNames property must specify a comma-separated list of 8 property names");
}
const std::string& PatternFormatter::getPriorityName(int prio)
{
poco_assert (1 <= prio && prio <= 8);
return priorities[prio];
return _priorities[prio];
}

View File

@@ -173,6 +173,11 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env)
{
#if !defined(POCO_NO_FORK_EXEC)
// On some systems, sysconf(_SC_OPEN_MAX) returns a ridiculously high number,
// which would closing all file descriptors up to that number extremely slow.
// We therefore limit the maximum number of file descriptors we close.
const long CLOSE_FD_MAX = 100000;
// We must not allocated memory after fork(),
// therefore allocate all required buffers first.
std::vector<char> envChars = getEnvironmentVariablesBuffer(env);
@@ -223,7 +228,10 @@ ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command,
if (outPipe) outPipe->close(Pipe::CLOSE_BOTH);
if (errPipe) errPipe->close(Pipe::CLOSE_BOTH);
// close all open file descriptors other than stdin, stdout, stderr
for (int i = 3; i < sysconf(_SC_OPEN_MAX); ++i)
long fdMax = sysconf(_SC_OPEN_MAX);
// on some systems, sysconf(_SC_OPEN_MAX) returns a ridiculously high number
if (fdMax > CLOSE_FD_MAX) fdMax = CLOSE_FD_MAX;
for (long i = 3; i < fdMax; ++i)
{
close(i);
}

View File

@@ -411,9 +411,17 @@ bool ProcessImpl::isRunningImpl(PIDImpl pid)
{
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
bool result = true;
DWORD exitCode;
BOOL rc = GetExitCodeProcess(hProc, &exitCode);
if (!rc || exitCode != STILL_ACTIVE) result = false;
if (hProc)
{
DWORD exitCode;
BOOL rc = GetExitCodeProcess(hProc, &exitCode);
if (!rc || exitCode != STILL_ACTIVE) result = false;
CloseHandle(hProc);
}
else
{
result = false;
}
return result;
}

View File

@@ -211,10 +211,19 @@ bool ProcessImpl::isRunningImpl(PIDImpl pid)
{
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
bool result = true;
DWORD exitCode;
BOOL rc = GetExitCodeProcess(hProc, &exitCode);
if (!rc || exitCode != STILL_ACTIVE) result = false;
return result;}
if (hProc)
{
DWORD exitCode;
BOOL rc = GetExitCodeProcess(hProc, &exitCode);
if (!rc || exitCode != STILL_ACTIVE) result = false;
CloseHandle(hProc);
}
else
{
result = false;
}
return result;
}
void ProcessImpl::requestTerminationImpl(PIDImpl pid)

View File

@@ -16,6 +16,9 @@
#include "Poco/UnicodeConverter.h"
#include "Poco/Path.h"
#include "Poco/UnWindows.h"
#include "Poco/Error.h"
#include "Poco/Format.h"
#include "Poco/String.h"
namespace Poco {
@@ -48,7 +51,13 @@ void SharedLibraryImpl::loadImpl(const std::string& path, int /*flags*/)
std::wstring upath;
UnicodeConverter::toUTF16(path, upath);
_handle = LoadLibraryExW(upath.c_str(), 0, flags);
if (!_handle) throw LibraryLoadException(path);
if (!_handle)
{
DWORD errn = Error::last();
std::string err;
Poco::format(err, "Error %ul while loading [%s]: [%s]", errn, path, Poco::trim(Error::getMessage(errn)));
throw LibraryLoadException(err);
}
_path = path;
}

View File

@@ -107,10 +107,7 @@ void ThreadImpl::setPriorityImpl(int prio)
_pData->policy = SCHED_OTHER;
if (isRunningImpl())
{
struct sched_param par; struct MyStruct
{
};
struct sched_param par;
par.sched_priority = mapPrio(_pData->prio, SCHED_OTHER);
if (pthread_setschedparam(_pData->thread, SCHED_OTHER, &par))
throw SystemException("cannot set thread priority");

View File

@@ -12,6 +12,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "Poco/Timezone.h"
#include <ctime>

View File

@@ -30,12 +30,16 @@ int Timezone::utcOffset()
return now - utc;
}
int Timezone::dst()
{
std::time_t now = std::time(NULL);
struct std::tm t;
#if defined(_VXWORKS_COMPATIBILITY_MODE) || (defined(_WRS_VXWORKS_MAJOR) && ((_WRS_VXWORKS_MAJOR < 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR < 9))))
if (localtime_r(&now, &t) != OK)
#else
if (!localtime_r(&now, &t))
#endif
throw Poco::SystemException("cannot get local time DST offset");
return t.tm_isdst == 1 ? 3600 : 0;
}
@@ -49,7 +53,7 @@ bool Timezone::isDst(const Timestamp& timestamp)
return tms->tm_isdst > 0;
}
std::string Timezone::name()
{
// format of TIMEZONE environment variable:
@@ -62,13 +66,13 @@ std::string Timezone::name()
return tz;
}
std::string Timezone::standardName()
{
return name();
}
std::string Timezone::dstName()
{
return name();

View File

@@ -615,7 +615,7 @@ void URI::removeDotSegments(bool removeLeading)
}
void URI::getPathSegments(std::vector<std::string>& segments)
void URI::getPathSegments(std::vector<std::string>& segments) const
{
getPathSegments(_path, segments);
}

View File

@@ -432,9 +432,10 @@ Var Var::parse(const std::string& val, std::string::size_type& pos)
std::string str = parseString(val, pos);
if (str == "false")
return false;
if (str == "true")
else if (str == "true")
return true;
else if (str == "null")
return Var();
bool isNumber = false;
bool isSigned = false;

View File

@@ -47,7 +47,8 @@ bool isJSONString(const Var& any)
any.type() == typeid(char*) ||
any.type() == typeid(Poco::DateTime) ||
any.type() == typeid(Poco::LocalDateTime) ||
any.type() == typeid(Poco::Timestamp);
any.type() == typeid(Poco::Timestamp) ||
any.type() == typeid(Poco::UUID);
}

View File

@@ -31,6 +31,7 @@ VarIterator::VarIterator(Var* pVar, bool positionEnd):
_pVar(pVar),
_position(positionEnd ? POSITION_END : 0)
{
if (!_pVar || _pVar->isEmpty()) throw InvalidAccessException("Cannot create iterator on empty Var");
}

View File

@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <math.h>
#include <cmath>
#include "bignum-dtoa.h"

View File

@@ -31,7 +31,7 @@
namespace double_conversion {
Bignum::Bignum()
: bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
: bigits_buffer_(), bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
for (int i = 0; i < kBigitCapacity; ++i) {
bigits_[i] = 0;
}
@@ -104,7 +104,7 @@ void Bignum::AssignDecimalString(Vector<const char> value) {
const int kMaxUint64DecimalDigits = 19;
Zero();
int length = value.length();
int pos = 0;
unsigned int pos = 0;
// Let's just say that each digit needs 4 bits.
while (length >= kMaxUint64DecimalDigits) {
uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
@@ -445,26 +445,27 @@ void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
mask >>= 2;
uint64_t this_value = base;
bool delayed_multipliciation = false;
bool delayed_multiplication = false;
const uint64_t max_32bits = 0xFFFFFFFF;
while (mask != 0 && this_value <= max_32bits) {
this_value = this_value * this_value;
// Verify that there is enough space in this_value to perform the
// multiplication. The first bit_size bits must be 0.
if ((power_exponent & mask) != 0) {
ASSERT(bit_size > 0);
uint64_t base_bits_mask =
~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);
bool high_bits_zero = (this_value & base_bits_mask) == 0;
if (high_bits_zero) {
this_value *= base;
} else {
delayed_multipliciation = true;
delayed_multiplication = true;
}
}
mask >>= 1;
}
AssignUInt64(this_value);
if (delayed_multipliciation) {
if (delayed_multiplication) {
MultiplyByUInt32(base);
}

View File

@@ -49,7 +49,6 @@ class Bignum {
void AssignPowerUInt16(uint16_t base, int exponent);
void AddUInt16(uint16_t operand);
void AddUInt64(uint64_t operand);
void AddBignum(const Bignum& other);
// Precondition: this >= other.
@@ -137,7 +136,7 @@ class Bignum {
// The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
int exponent_;
DISALLOW_COPY_AND_ASSIGN(Bignum);
DC_DISALLOW_COPY_AND_ASSIGN(Bignum);
};
} // namespace double_conversion

View File

@@ -25,9 +25,9 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h>
#include <limits.h>
#include <math.h>
#include <climits>
#include <cmath>
#include <cstdarg>
#include "utils.h"
@@ -131,7 +131,6 @@ static const CachedPower kCachedPowers[] = {
{UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340},
};
static const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers);
static const int kCachedPowersOffset = 348; // -1 * the first decimal_exponent.
static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
// Difference between the decimal exponents in the table above.
@@ -149,7 +148,7 @@ void PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
int foo = kCachedPowersOffset;
int index =
(foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1;
ASSERT(0 <= index && index < kCachedPowersLength);
ASSERT(0 <= index && index < static_cast<int>(ARRAY_SIZE(kCachedPowers)));
CachedPower cached_power = kCachedPowers[index];
ASSERT(min_exponent <= cached_power.binary_exponent);
(void) max_exponent; // Mark variable as used.

View File

@@ -42,7 +42,7 @@ class DiyFp {
static const int kSignificandSize = 64;
DiyFp() : f_(0), e_(0) {}
DiyFp(uint64_t f, int e) : f_(f), e_(e) {}
DiyFp(uint64_t significand, int exponent) : f_(significand), e_(exponent) {}
// this = this - other.
// The exponents of both numbers must be the same and the significand of this
@@ -76,22 +76,22 @@ class DiyFp {
void Normalize() {
ASSERT(f_ != 0);
uint64_t f = f_;
int e = e_;
uint64_t significand = f_;
int exponent = e_;
// This method is mainly called for normalizing boundaries. In general
// boundaries need to be shifted by 10 bits. We thus optimize for this case.
const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000);
while ((f & k10MSBits) == 0) {
f <<= 10;
e -= 10;
while ((significand & k10MSBits) == 0) {
significand <<= 10;
exponent -= 10;
}
while ((f & kUint64MSB) == 0) {
f <<= 1;
e--;
while ((significand & kUint64MSB) == 0) {
significand <<= 1;
exponent--;
}
f_ = f;
e_ = e;
f_ = significand;
e_ = exponent;
}
static DiyFp Normalize(const DiyFp& a) {

View File

@@ -25,8 +25,9 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <limits.h>
#include <math.h>
#include <climits>
#include <locale>
#include <cmath>
#include "double-conversion.h"
@@ -118,7 +119,7 @@ void DoubleToStringConverter::CreateDecimalRepresentation(
StringBuilder* result_builder) const {
// Create a representation that is padded with zeros if needed.
if (decimal_point <= 0) {
// "0.00000decimal_rep".
// "0.00000decimal_rep" or "0.000decimal_rep00".
result_builder->AddCharacter('0');
if (digits_after_point > 0) {
result_builder->AddCharacter('.');
@@ -129,7 +130,7 @@ void DoubleToStringConverter::CreateDecimalRepresentation(
result_builder->AddPadding('0', remaining_digits);
}
} else if (decimal_point >= length) {
// "decimal_rep0000.00000" or "decimal_rep.0000"
// "decimal_rep0000.00000" or "decimal_rep.0000".
result_builder->AddSubstring(decimal_digits, length);
result_builder->AddPadding('0', decimal_point - length);
if (digits_after_point > 0) {
@@ -137,7 +138,7 @@ void DoubleToStringConverter::CreateDecimalRepresentation(
result_builder->AddPadding('0', digits_after_point);
}
} else {
// "decima.l_rep000"
// "decima.l_rep000".
ASSERT(digits_after_point > 0);
result_builder->AddSubstring(decimal_digits, decimal_point);
result_builder->AddCharacter('.');
@@ -249,6 +250,12 @@ bool DoubleToStringConverter::ToExponential(
const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
char decimal_rep[kDecimalRepCapacity];
#ifndef NDEBUG
// Problem: there is an assert in StringBuilder::AddSubstring() that
// will pass this buffer to strlen(), and this buffer is not generally
// null-terminated.
memset(decimal_rep, 0, sizeof(decimal_rep));
#endif
int decimal_rep_length;
if (requested_digits == -1) {
@@ -348,7 +355,6 @@ static BignumDtoaMode DtoaToBignumDtoaMode(
case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
default:
UNREACHABLE();
return BIGNUM_DTOA_SHORTEST;
}
}
@@ -415,20 +421,55 @@ void DoubleToStringConverter::DoubleToAscii(double v,
}
// Consumes the given substring from the iterator.
// Returns false, if the substring does not match.
static bool ConsumeSubString(const char** current,
const char* end,
const char* substring) {
ASSERT(**current == *substring);
namespace {
inline char ToLower(char ch) {
static const std::ctype<char>& cType =
std::use_facet<std::ctype<char> >(std::locale::classic());
return cType.tolower(ch);
}
inline char Pass(char ch) {
return ch;
}
template <class Iterator, class Converter>
static inline bool ConsumeSubStringImpl(Iterator* current,
Iterator end,
const char* substring,
Converter converter) {
ASSERT(converter(**current) == *substring);
for (substring++; *substring != '\0'; substring++) {
++*current;
if (*current == end || **current != *substring) return false;
if (*current == end || converter(**current) != *substring) {
return false;
}
}
++*current;
return true;
}
// Consumes the given substring from the iterator.
// Returns false, if the substring does not match.
template <class Iterator>
static bool ConsumeSubString(Iterator* current,
Iterator end,
const char* substring,
bool allow_case_insensibility) {
if (allow_case_insensibility) {
return ConsumeSubStringImpl(current, end, substring, ToLower);
} else {
return ConsumeSubStringImpl(current, end, substring, Pass);
}
}
// Consumes first character of the str is equal to ch
inline bool ConsumeFirstCharacter(char ch,
const char* str,
bool case_insensibility) {
return case_insensibility ? ToLower(ch) == str[0] : ch == str[0];
}
} // namespace
// Maximum number of significant digits in decimal representation.
// The longest possible double in decimal representation is
@@ -440,10 +481,36 @@ static bool ConsumeSubString(const char** current,
const int kMaxSignificantDigits = 772;
static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 };
static const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7);
static const uc16 kWhitespaceTable16[] = {
160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195,
8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279
};
static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16);
static bool isWhitespace(int x) {
if (x < 128) {
for (int i = 0; i < kWhitespaceTable7Length; i++) {
if (kWhitespaceTable7[i] == x) return true;
}
} else {
for (int i = 0; i < kWhitespaceTable16Length; i++) {
if (kWhitespaceTable16[i] == x) return true;
}
}
return false;
}
// Returns true if a nonspace found and false if the end has reached.
static inline bool AdvanceToNonspace(const char** current, const char* end) {
template <class Iterator>
static inline bool AdvanceToNonspace(Iterator* current, Iterator end) {
while (*current != end) {
if (**current != ' ') return true;
if (!isWhitespace(**current)) return true;
++*current;
}
return false;
@@ -468,10 +535,17 @@ static double SignedZero(bool sign) {
// because it constant-propagated the radix and concluded that the last
// condition was always true. By moving it into a separate function the
// compiler wouldn't warn anymore.
#ifdef _MSC_VER
#pragma optimize("",off)
static bool IsDecimalDigitForRadix(int c, int radix) {
return '0' <= c && c <= '9' && (c - '0') < radix;
}
#pragma optimize("",on)
#else
static bool inline IsDecimalDigitForRadix(int c, int radix) {
return '0' <= c && c <= '9' && (c - '0') < radix;
}
#endif
// Returns true if 'c' is a character digit that is valid for the given radix.
// The 'a_character' should be 'a' or 'A'.
//
@@ -483,45 +557,128 @@ static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
return radix > 10 && c >= a_character && c < a_character + radix - 10;
}
// Returns true, when the iterator is equal to end.
template<class Iterator>
static bool Advance (Iterator* it, uc16 separator, int base, Iterator& end) {
if (separator == StringToDoubleConverter::kNoSeparator) {
++(*it);
return *it == end;
}
if (!isDigit(**it, base)) {
++(*it);
return *it == end;
}
++(*it);
if (*it == end) return true;
if (*it + 1 == end) return false;
if (**it == separator && isDigit(*(*it + 1), base)) {
++(*it);
}
return *it == end;
}
// Checks whether the string in the range start-end is a hex-float string.
// This function assumes that the leading '0x'/'0X' is already consumed.
//
// Hex float strings are of one of the following forms:
// - hex_digits+ 'p' ('+'|'-')? exponent_digits+
// - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+
// - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+
template<class Iterator>
static bool IsHexFloatString(Iterator start,
Iterator end,
uc16 separator,
bool allow_trailing_junk) {
ASSERT(start != end);
Iterator current = start;
bool saw_digit = false;
while (isDigit(*current, 16)) {
saw_digit = true;
if (Advance(&current, separator, 16, end)) return false;
}
if (*current == '.') {
if (Advance(&current, separator, 16, end)) return false;
while (isDigit(*current, 16)) {
saw_digit = true;
if (Advance(&current, separator, 16, end)) return false;
}
}
if (!saw_digit) return false;
if (*current != 'p' && *current != 'P') return false;
if (Advance(&current, separator, 16, end)) return false;
if (*current == '+' || *current == '-') {
if (Advance(&current, separator, 16, end)) return false;
}
if (!isDigit(*current, 10)) return false;
if (Advance(&current, separator, 16, end)) return true;
while (isDigit(*current, 10)) {
if (Advance(&current, separator, 16, end)) return true;
}
return allow_trailing_junk || !AdvanceToNonspace(&current, end);
}
// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
template <int radix_log_2>
static double RadixStringToIeee(const char* current,
const char* end,
//
// If parse_as_hex_float is true, then the string must be a valid
// hex-float.
template <int radix_log_2, class Iterator>
static double RadixStringToIeee(Iterator* current,
Iterator end,
bool sign,
uc16 separator,
bool parse_as_hex_float,
bool allow_trailing_junk,
double junk_string_value,
bool read_as_double,
const char** trailing_pointer) {
ASSERT(current != end);
bool* result_is_junk) {
ASSERT(*current != end);
ASSERT(!parse_as_hex_float ||
IsHexFloatString(*current, end, separator, allow_trailing_junk));
const int kDoubleSize = Double::kSignificandSize;
const int kSingleSize = Single::kSignificandSize;
const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
// Skip leading 0s.
while (*current == '0') {
++current;
if (current == end) {
*trailing_pointer = end;
return SignedZero(sign);
}
}
*result_is_junk = true;
int64_t number = 0;
int exponent = 0;
const int radix = (1 << radix_log_2);
// Whether we have encountered a '.' and are parsing the decimal digits.
// Only relevant if parse_as_hex_float is true.
bool post_decimal = false;
do {
// Skip leading 0s.
while (**current == '0') {
if (Advance(current, separator, radix, end)) {
*result_is_junk = false;
return SignedZero(sign);
}
}
while (true) {
int digit;
if (IsDecimalDigitForRadix(*current, radix)) {
digit = static_cast<char>(*current) - '0';
} else if (IsCharacterDigitForRadix(*current, radix, 'a')) {
digit = static_cast<char>(*current) - 'a' + 10;
} else if (IsCharacterDigitForRadix(*current, radix, 'A')) {
digit = static_cast<char>(*current) - 'A' + 10;
if (IsDecimalDigitForRadix(**current, radix)) {
digit = static_cast<char>(**current) - '0';
if (post_decimal) exponent -= radix_log_2;
} else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
digit = static_cast<char>(**current) - 'a' + 10;
if (post_decimal) exponent -= radix_log_2;
} else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
digit = static_cast<char>(**current) - 'A' + 10;
if (post_decimal) exponent -= radix_log_2;
} else if (parse_as_hex_float && **current == '.') {
post_decimal = true;
Advance(current, separator, radix, end);
ASSERT(*current != end);
continue;
} else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) {
break;
} else {
if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {
if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
break;
} else {
return junk_string_value;
@@ -542,17 +699,26 @@ static double RadixStringToIeee(const char* current,
int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
number >>= overflow_bits_count;
exponent = overflow_bits_count;
exponent += overflow_bits_count;
bool zero_tail = true;
for (;;) {
++current;
if (current == end || !isDigit(*current, radix)) break;
zero_tail = zero_tail && *current == '0';
exponent += radix_log_2;
if (Advance(current, separator, radix, end)) break;
if (parse_as_hex_float && **current == '.') {
// Just run over the '.'. We are just trying to see whether there is
// a non-zero digit somewhere.
Advance(current, separator, radix, end);
ASSERT(*current != end);
post_decimal = true;
}
if (!isDigit(**current, radix)) break;
zero_tail = zero_tail && **current == '0';
if (!post_decimal) exponent += radix_log_2;
}
if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
if (!parse_as_hex_float &&
!allow_trailing_junk &&
AdvanceToNonspace(current, end)) {
return junk_string_value;
}
@@ -574,15 +740,41 @@ static double RadixStringToIeee(const char* current,
}
break;
}
++current;
} while (current != end);
if (Advance(current, separator, radix, end)) break;
}
ASSERT(number < ((int64_t)1 << kSignificandSize));
ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
*trailing_pointer = current;
*result_is_junk = false;
if (exponent == 0) {
if (parse_as_hex_float) {
ASSERT(**current == 'p' || **current == 'P');
Advance(current, separator, radix, end);
ASSERT(*current != end);
bool is_negative = false;
if (**current == '+') {
Advance(current, separator, radix, end);
ASSERT(*current != end);
} else if (**current == '-') {
is_negative = true;
Advance(current, separator, radix, end);
ASSERT(*current != end);
}
int written_exponent = 0;
while (IsDecimalDigitForRadix(**current, 10)) {
// No need to read exponents if they are too big. That could potentially overflow
// the `written_exponent` variable.
if (abs(written_exponent) <= 100 * Double::kMaxExponent) {
written_exponent = 10 * written_exponent + **current - '0';
}
if (Advance(current, separator, radix, end)) break;
}
if (is_negative) written_exponent = -written_exponent;
exponent += written_exponent;
}
if (exponent == 0 || number == 0) {
if (sign) {
if (number == 0) return -0.0;
number = -number;
@@ -591,17 +783,18 @@ static double RadixStringToIeee(const char* current,
}
ASSERT(number != 0);
return Double(DiyFp(number, exponent)).value();
double result = Double(DiyFp(number, exponent)).value();
return sign ? -result : result;
}
template <class Iterator>
double StringToDoubleConverter::StringToIeee(
const char* input,
Iterator input,
int length,
int* processed_characters_count,
bool read_as_double) const {
const char* current = input;
const char* end = input + length;
bool read_as_double,
int* processed_characters_count) const {
Iterator current = input;
Iterator end = input + length;
*processed_characters_count = 0;
@@ -609,6 +802,7 @@ double StringToDoubleConverter::StringToIeee(
const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
const bool allow_case_insensibility = (flags_ & ALLOW_CASE_INSENSIBILITY) != 0;
// To make sure that iterator dereferencing is valid the following
// convention is used:
@@ -648,7 +842,7 @@ double StringToDoubleConverter::StringToIeee(
if (*current == '+' || *current == '-') {
sign = (*current == '-');
++current;
const char* next_non_space = current;
Iterator next_non_space = current;
// Skip following spaces (if allowed).
if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
if (!allow_spaces_after_sign && (current != next_non_space)) {
@@ -658,8 +852,8 @@ double StringToDoubleConverter::StringToIeee(
}
if (infinity_symbol_ != NULL) {
if (*current == infinity_symbol_[0]) {
if (!ConsumeSubString(&current, end, infinity_symbol_)) {
if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensibility)) {
if (!ConsumeSubString(&current, end, infinity_symbol_, allow_case_insensibility)) {
return junk_string_value_;
}
@@ -677,8 +871,8 @@ double StringToDoubleConverter::StringToIeee(
}
if (nan_symbol_ != NULL) {
if (*current == nan_symbol_[0]) {
if (!ConsumeSubString(&current, end, nan_symbol_)) {
if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensibility)) {
if (!ConsumeSubString(&current, end, nan_symbol_, allow_case_insensibility)) {
return junk_string_value_;
}
@@ -697,8 +891,7 @@ double StringToDoubleConverter::StringToIeee(
bool leading_zero = false;
if (*current == '0') {
++current;
if (current == end) {
if (Advance(&current, separator_, 10, end)) {
*processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -706,31 +899,39 @@ double StringToDoubleConverter::StringToIeee(
leading_zero = true;
// It could be hexadecimal value.
if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) &&
(*current == 'x' || *current == 'X')) {
++current;
if (current == end || !isDigit(*current, 16)) {
return junk_string_value_; // "0x".
if (current == end) return junk_string_value_; // "0x"
bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) &&
IsHexFloatString(current, end, separator_, allow_trailing_junk);
if (!parse_as_hex_float && !isDigit(*current, 16)) {
return junk_string_value_;
}
const char* tail_pointer = NULL;
double result = RadixStringToIeee<4>(current,
bool result_is_junk;
double result = RadixStringToIeee<4>(&current,
end,
sign,
separator_,
parse_as_hex_float,
allow_trailing_junk,
junk_string_value_,
read_as_double,
&tail_pointer);
if (tail_pointer != NULL) {
if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end);
*processed_characters_count = static_cast<int>(tail_pointer - input);
&result_is_junk);
if (!result_is_junk) {
if (allow_trailing_spaces) AdvanceToNonspace(&current, end);
*processed_characters_count = static_cast<int>(current - input);
}
return result;
}
// Ignore leading zeros in the integer part.
while (*current == '0') {
++current;
if (current == end) {
if (Advance(&current, separator_, 10, end)) {
*processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -751,8 +952,7 @@ double StringToDoubleConverter::StringToIeee(
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
}
octal = octal && *current < '8';
++current;
if (current == end) goto parsing_done;
if (Advance(&current, separator_, 10, end)) goto parsing_done;
}
if (significant_digits == 0) {
@@ -763,8 +963,7 @@ double StringToDoubleConverter::StringToIeee(
if (octal && !allow_trailing_junk) return junk_string_value_;
if (octal) goto parsing_done;
++current;
if (current == end) {
if (Advance(&current, separator_, 10, end)) {
if (significant_digits == 0 && !leading_zero) {
return junk_string_value_;
} else {
@@ -777,8 +976,7 @@ double StringToDoubleConverter::StringToIeee(
// Integer part consists of 0 or is absent. Significant digits start after
// leading zeros (if any).
while (*current == '0') {
++current;
if (current == end) {
if (Advance(&current, separator_, 10, end)) {
*processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -798,8 +996,7 @@ double StringToDoubleConverter::StringToIeee(
// Ignore insignificant digits in the fractional part.
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
}
++current;
if (current == end) goto parsing_done;
if (Advance(&current, separator_, 10, end)) goto parsing_done;
}
}
@@ -815,20 +1012,23 @@ double StringToDoubleConverter::StringToIeee(
if (*current == 'e' || *current == 'E') {
if (octal && !allow_trailing_junk) return junk_string_value_;
if (octal) goto parsing_done;
Iterator junk_begin = current;
++current;
if (current == end) {
if (allow_trailing_junk) {
current = junk_begin;
goto parsing_done;
} else {
return junk_string_value_;
}
}
char sign = '+';
char exponen_sign = '+';
if (*current == '+' || *current == '-') {
sign = static_cast<char>(*current);
exponen_sign = static_cast<char>(*current);
++current;
if (current == end) {
if (allow_trailing_junk) {
current = junk_begin;
goto parsing_done;
} else {
return junk_string_value_;
@@ -838,6 +1038,7 @@ double StringToDoubleConverter::StringToIeee(
if (current == end || *current < '0' || *current > '9') {
if (allow_trailing_junk) {
current = junk_begin;
goto parsing_done;
} else {
return junk_string_value_;
@@ -859,7 +1060,7 @@ double StringToDoubleConverter::StringToIeee(
++current;
} while (current != end && *current >= '0' && *current <= '9');
exponent += (sign == '-' ? -num : num);
exponent += (exponen_sign == '-' ? -num : num);
}
if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
@@ -877,15 +1078,18 @@ double StringToDoubleConverter::StringToIeee(
if (octal) {
double result;
const char* tail_pointer = NULL;
result = RadixStringToIeee<3>(buffer,
bool result_is_junk;
char* start = buffer;
result = RadixStringToIeee<3>(&start,
buffer + buffer_pos,
sign,
separator_,
false, // Don't parse as hex_float.
allow_trailing_junk,
junk_string_value_,
read_as_double,
&tail_pointer);
ASSERT(tail_pointer != NULL);
&result_is_junk);
ASSERT(!result_is_junk);
*processed_characters_count = static_cast<int>(current - input);
return result;
}
@@ -908,4 +1112,38 @@ double StringToDoubleConverter::StringToIeee(
return sign? -converted: converted;
}
double StringToDoubleConverter::StringToDouble(
const char* buffer,
int length,
int* processed_characters_count) const {
return StringToIeee(buffer, length, true, processed_characters_count);
}
double StringToDoubleConverter::StringToDouble(
const uc16* buffer,
int length,
int* processed_characters_count) const {
return StringToIeee(buffer, length, true, processed_characters_count);
}
float StringToDoubleConverter::StringToFloat(
const char* buffer,
int length,
int* processed_characters_count) const {
return static_cast<float>(StringToIeee(buffer, length, false,
processed_characters_count));
}
float StringToDoubleConverter::StringToFloat(
const uc16* buffer,
int length,
int* processed_characters_count) const {
return static_cast<float>(StringToIeee(buffer, length, false,
processed_characters_count));
}
} // namespace double_conversion

View File

@@ -294,13 +294,18 @@ class DoubleToStringConverter {
// should be at least kBase10MaximalLength + 1 characters long.
static const int kBase10MaximalLength = 17;
// Converts the given double 'v' to ascii. 'v' must not be NaN, +Infinity, or
// -Infinity. In SHORTEST_SINGLE-mode this restriction also applies to 'v'
// after it has been casted to a single-precision float. That is, in this
// mode static_cast<float>(v) must not be NaN, +Infinity or -Infinity.
// Converts the given double 'v' to digit characters. 'v' must not be NaN,
// +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also
// applies to 'v' after it has been casted to a single-precision float. That
// is, in this mode static_cast<float>(v) must not be NaN, +Infinity or
// -Infinity.
//
// The result should be interpreted as buffer * 10^(point-length).
//
// The digits are written to the buffer in the platform's charset, which is
// often UTF-8 (with ASCII-range digits) but may be another charset, such
// as EBCDIC.
//
// The output depends on the given mode:
// - SHORTEST: produce the least amount of digits for which the internal
// identity requirement is still satisfied. If the digits are printed
@@ -374,7 +379,7 @@ class DoubleToStringConverter {
const int max_leading_padding_zeroes_in_precision_mode_;
const int max_trailing_padding_zeroes_in_precision_mode_;
DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
DC_DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
};
@@ -389,9 +394,13 @@ class StringToDoubleConverter {
ALLOW_TRAILING_JUNK = 4,
ALLOW_LEADING_SPACES = 8,
ALLOW_TRAILING_SPACES = 16,
ALLOW_SPACES_AFTER_SIGN = 32
ALLOW_SPACES_AFTER_SIGN = 32,
ALLOW_CASE_INSENSIBILITY = 64,
ALLOW_HEX_FLOATS = 128,
};
static const uc16 kNoSeparator = '\0';
// Flags should be a bit-or combination of the possible Flags-enum.
// - NO_FLAGS: no special flags.
// - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.
@@ -415,11 +424,19 @@ class StringToDoubleConverter {
// junk, too.
// - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of
// a double literal.
// - ALLOW_LEADING_SPACES: skip over leading spaces.
// - ALLOW_TRAILING_SPACES: ignore trailing spaces.
// - ALLOW_SPACES_AFTER_SIGN: ignore spaces after the sign.
// - ALLOW_LEADING_SPACES: skip over leading whitespace, including spaces,
// new-lines, and tabs.
// - ALLOW_TRAILING_SPACES: ignore trailing whitespace.
// - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign.
// Ex: StringToDouble("- 123.2") -> -123.2.
// StringToDouble("+ 123.2") -> 123.2
// - ALLOW_CASE_INSENSIBILITY: ignore case of characters for special values:
// infinity and nan.
// - ALLOW_HEX_FLOATS: allows hexadecimal float literals.
// This *must* start with "0x" and separate the exponent with "p".
// Examples: 0x1.2p3 == 9.0
// 0x10.1p0 == 16.0625
// ALLOW_HEX and ALLOW_HEX_FLOATS are indendent.
//
// empty_string_value is returned when an empty string is given as input.
// If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
@@ -444,6 +461,12 @@ class StringToDoubleConverter {
// - they must not have the same first character.
// - they must not start with digits.
//
// If the separator character is not kNoSeparator, then that specific
// character is ignored when in between two valid digits of the significant.
// It is not allowed to appear in the exponent.
// It is not allowed to lead or trail the number.
// It is not allowed to appear twice next to each other.
//
// Examples:
// flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,
// empty_string_value = 0.0,
@@ -483,16 +506,26 @@ class StringToDoubleConverter {
// StringToDouble("01239E45") -> 1239e45.
// StringToDouble("-infinity") -> NaN // junk_string_value.
// StringToDouble("NaN") -> NaN // junk_string_value.
//
// flags = NO_FLAGS,
// separator = ' ':
// StringToDouble("1 2 3 4") -> 1234.0
// StringToDouble("1 2") -> NaN // junk_string_value
// StringToDouble("1 000 000.0") -> 1000000.0
// StringToDouble("1.000 000") -> 1.0
// StringToDouble("1.0e1 000") -> NaN // junk_string_value
StringToDoubleConverter(int flags,
double empty_string_value,
double junk_string_value,
const char* infinity_symbol,
const char* nan_symbol)
const char* nan_symbol,
uc16 separator = kNoSeparator)
: flags_(flags),
empty_string_value_(empty_string_value),
junk_string_value_(junk_string_value),
infinity_symbol_(infinity_symbol),
nan_symbol_(nan_symbol) {
nan_symbol_(nan_symbol),
separator_(separator) {
}
// Performs the conversion.
@@ -502,19 +535,24 @@ class StringToDoubleConverter {
// in the 'processed_characters_count'. Trailing junk is never included.
double StringToDouble(const char* buffer,
int length,
int* processed_characters_count) const {
return StringToIeee(buffer, length, processed_characters_count, true);
}
int* processed_characters_count) const;
// Same as StringToDouble above but for 16 bit characters.
double StringToDouble(const uc16* buffer,
int length,
int* processed_characters_count) const;
// Same as StringToDouble but reads a float.
// Note that this is not equivalent to static_cast<float>(StringToDouble(...))
// due to potential double-rounding.
float StringToFloat(const char* buffer,
int length,
int* processed_characters_count) const {
return static_cast<float>(StringToIeee(buffer, length,
processed_characters_count, false));
}
int* processed_characters_count) const;
// Same as StringToFloat above but for 16 bit characters.
float StringToFloat(const uc16* buffer,
int length,
int* processed_characters_count) const;
private:
const int flags_;
@@ -522,13 +560,15 @@ class StringToDoubleConverter {
const double junk_string_value_;
const char* const infinity_symbol_;
const char* const nan_symbol_;
const uc16 separator_;
double StringToIeee(const char* buffer,
template <class Iterator>
double StringToIeee(Iterator start_pointer,
int length,
int* processed_characters_count,
bool read_as_double) const;
bool read_as_double,
int* processed_characters_count) const;
DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
};
} // namespace double_conversion

View File

@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <math.h>
#include <cmath>
#include "fixed-dtoa.h"
#include "ieee.h"
@@ -98,7 +98,7 @@ class UInt128 {
return high_bits_ == 0 && low_bits_ == 0;
}
int BitAt(int position) {
int BitAt(int position) const {
if (position >= 64) {
return static_cast<int>(high_bits_ >> (position - 64)) & 1;
} else {
@@ -259,7 +259,8 @@ static void FillFractionals(uint64_t fractionals, int exponent,
fractionals -= static_cast<uint64_t>(digit) << point;
}
// If the first bit after the point is set we have to round up.
if (((fractionals >> (point - 1)) & 1) == 1) {
ASSERT(fractionals == 0 || point - 1 >= 0);
if ((fractionals != 0) && ((fractionals >> (point - 1)) & 1) == 1) {
RoundUp(buffer, length, decimal_point);
}
} else { // We need 128 bits.

View File

@@ -47,6 +47,8 @@ class Double {
static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000);
static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit.
static const int kSignificandSize = 53;
static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
static const int kMaxExponent = 0x7FF - kExponentBias;
Double() : d64_(0) {}
explicit Double(double d) : d64_(double_to_uint64(d)) {}
@@ -99,7 +101,7 @@ class Double {
}
double PreviousDouble() const {
if (d64_ == (kInfinity | kSignMask)) return -Double::Infinity();
if (d64_ == (kInfinity | kSignMask)) return -Infinity();
if (Sign() < 0) {
return Double(d64_ + 1).value();
} else {
@@ -222,9 +224,7 @@ class Double {
}
private:
static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
static const int kDenormalExponent = -kExponentBias + 1;
static const int kMaxExponent = 0x7FF - kExponentBias;
static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000);
static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000);
@@ -257,7 +257,7 @@ class Double {
(biased_exponent << kPhysicalSignificandSize);
}
DISALLOW_COPY_AND_ASSIGN(Double);
DC_DISALLOW_COPY_AND_ASSIGN(Double);
};
class Single {
@@ -394,7 +394,7 @@ class Single {
const uint32_t d32_;
DISALLOW_COPY_AND_ASSIGN(Single);
DC_DISALLOW_COPY_AND_ASSIGN(Single);
};
} // namespace double_conversion

View File

@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE_MAJOR 8
#define PCRE_MINOR 43
#define PCRE_MINOR 44
#define PCRE_PRERELEASE
#define PCRE_DATE 2019-02-23
#define PCRE_DATE 020-02-12
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate

View File

@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Copyright (c) 1997-2018 University of Cambridge
Copyright (c) 1997-2020 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -70,7 +70,7 @@ COMPILE_PCREx macro will already be appropriately set. */
/* Macro for setting individual bits in class bitmaps. */
#define SETBIT(a,b) a[(b)/8] |= (1 << ((b)&7))
#define SETBIT(a,b) a[(b)/8] |= (1U << ((b)&7))
/* Maximum length value to check against when making sure that the integer that
holds the compiled pattern length does not overflow. We make it a bit less than
@@ -131,8 +131,8 @@ overrun before it actually does run off the end of the data block. */
/* Private flags added to firstchar and reqchar. */
#define REQ_CASELESS (1 << 0) /* Indicates caselessness */
#define REQ_VARY (1 << 1) /* Reqchar followed non-literal item */
#define REQ_CASELESS (1U << 0) /* Indicates caselessness */
#define REQ_VARY (1U << 1) /* Reqchar followed non-literal item */
/* Negative values for the firstchar and reqchar flags */
#define REQ_UNSET (-2)
#define REQ_NONE (-1)
@@ -3301,7 +3301,7 @@ for(;;)
if ((*xclass_flags & XCL_MAP) == 0)
{
/* No bits are set for characters < 256. */
if (list[1] == 0) return TRUE;
if (list[1] == 0) return (*xclass_flags & XCL_NOT) == 0;
/* Might be an empty repeat. */
continue;
}
@@ -3613,7 +3613,7 @@ for(;;)
if (chr > 255) break;
class_bitset = (pcre_uint8 *)
((list_ptr == list ? code : base_end) - list_ptr[2]);
if ((class_bitset[chr >> 3] & (1 << (chr & 7))) != 0) return FALSE;
if ((class_bitset[chr >> 3] & (1U << (chr & 7))) != 0) return FALSE;
break;
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
@@ -7132,17 +7132,19 @@ for (;; ptr++)
int n = 0;
ptr++;
while(IS_DIGIT(*ptr))
{
n = n * 10 + *ptr++ - CHAR_0;
if (n > 255)
{
*errorcodeptr = ERR38;
goto FAILED;
}
}
if (*ptr != CHAR_RIGHT_PARENTHESIS)
{
*errorcodeptr = ERR39;
goto FAILED;
}
if (n > 255)
{
*errorcodeptr = ERR38;
goto FAILED;
}
*code++ = n;
PUT(code, 0, (int)(ptr - cd->start_pattern + 1)); /* Pattern offset */
PUT(code, LINK_SIZE, 0); /* Default length */
@@ -7458,7 +7460,7 @@ for (;; ptr++)
{
open_capitem *oc;
recno = GET2(slot, 0);
cd->backref_map |= (recno < 32)? (1 << recno) : 1;
cd->backref_map |= (recno < 32)? (1U << recno) : 1;
if (recno > cd->top_backref) cd->top_backref = recno;
/* Check to see if this back reference is recursive, that it, it
@@ -7644,8 +7646,8 @@ for (;; ptr++)
/* Can't determine a first byte now */
if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
zerofirstchar = firstchar;
zerofirstcharflags = firstcharflags;
zerofirstchar = firstchar;
zerofirstcharflags = firstcharflags;
continue;
@@ -8069,7 +8071,7 @@ for (;; ptr++)
item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF;
PUT2INC(code, 0, recno);
cd->backref_map |= (recno < 32)? (1 << recno) : 1;
cd->backref_map |= (recno < 32)? (1U << recno) : 1;
if (recno > cd->top_backref) cd->top_backref = recno;
/* Check to see if this back reference is recursive, that it, it
@@ -8682,7 +8684,7 @@ do {
op == OP_SCBRA || op == OP_SCBRAPOS)
{
int n = GET2(scode, 1+LINK_SIZE);
int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
int new_map = bracket_map | ((n < 32)? (1U << n) : 1);
if (!is_anchored(scode, new_map, cd, atomcount)) return FALSE;
}
@@ -8694,6 +8696,7 @@ do {
}
/* Condition; not anchored if no second branch */
else if (op == OP_COND)
{
if (scode[GET(scode,1)] != OP_ALT) return FALSE;
@@ -8809,7 +8812,7 @@ do {
op == OP_SCBRA || op == OP_SCBRAPOS)
{
int n = GET2(scode, 1+LINK_SIZE);
int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
int new_map = bracket_map | ((n < 32)? (1U << n) : 1);
if (!is_startline(scode, new_map, cd, atomcount, inassert)) return FALSE;
}

View File

@@ -289,7 +289,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_NAME "PCRE"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "PCRE 8.43"
#define PACKAGE_STRING "PCRE 8.44"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcre"
@@ -298,7 +298,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "8.43"
#define PACKAGE_VERSION "8.44"
/* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested
parentheses (of any kind) in a pattern. This limits the amount of system
@@ -400,7 +400,7 @@ sure both macros are undefined; an emulation function will then be used. */
/* #undef SUPPORT_VALGRIND */
/* Version number of package */
#define VERSION "8.43"
#define VERSION "8.44"
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */

View File

@@ -3937,10 +3937,10 @@ static sljit_s32 character_to_int32(pcre_uchar chr)
sljit_s32 value = (sljit_s32)chr;
#if defined COMPILE_PCRE8
#define SSE2_COMPARE_TYPE_INDEX 0
return (value << 24) | (value << 16) | (value << 8) | value;
return ((unsigned int)value << 24) | ((unsigned int)value << 16) | ((unsigned int)value << 8) | (unsigned int)value;
#elif defined COMPILE_PCRE16
#define SSE2_COMPARE_TYPE_INDEX 1
return (value << 16) | value;
return ((unsigned int)value << 16) | value;
#elif defined COMPILE_PCRE32
#define SSE2_COMPARE_TYPE_INDEX 2
return value;
@@ -8506,7 +8506,7 @@ if (opcode == OP_ONCE)
/* We temporarily encode the needs_control_head in the lowest bit.
Note: on the target architectures of SLJIT the ((x << 1) >> 1) returns
the same value for small signed numbers (including negative numbers). */
BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
BACKTRACK_AS(bracket_backtrack)->u.framesize = ((unsigned int)BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
}
return cc + repeat_length;
}
@@ -9001,7 +9001,7 @@ if (exact > 1)
#ifdef SUPPORT_UTF
&& !common->utf
#endif
)
&& type != OP_ANYNL && type != OP_EXTUNI)
{
OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact));
add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER, TMP1, 0, STR_END, 0));

View File

@@ -25,13 +25,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h>
#include <limits.h>
#include <climits>
#include <cstdarg>
#include "strtod.h"
#include "bignum.h"
#include "cached-powers.h"
#include "ieee.h"
#include "strtod.h"
namespace double_conversion {
@@ -205,7 +205,7 @@ static bool DoubleStrtod(Vector<const char> trimmed,
// Note that the ARM simulator is compiled for 32bits. It therefore exhibits
// the same problem.
return false;
#endif
#else
if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
int read_digits;
// The trimmed input fits into a double.
@@ -243,6 +243,7 @@ static bool DoubleStrtod(Vector<const char> trimmed,
}
}
return false;
#endif
}
@@ -264,7 +265,6 @@ static DiyFp AdjustmentPowerOfTen(int exponent) {
case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40);
default:
UNREACHABLE();
return DiyFp(0, 0);
}
}
@@ -287,7 +287,7 @@ static bool DiyFpStrtod(Vector<const char> buffer,
const int kDenominator = 1 << kDenominatorLog;
// Move the remaining decimals into the exponent.
exponent += remaining_decimals;
int error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
uint64_t error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
int old_e = input.e();
input.Normalize();
@@ -472,6 +472,30 @@ double Strtod(Vector<const char> buffer, int exponent) {
}
}
static float SanitizedDoubletof(double d) {
ASSERT(d >= 0.0);
// ASAN has a sanitize check that disallows casting doubles to floats if
// they are too big.
// https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks
// The behavior should be covered by IEEE 754, but some projects use this
// flag, so work around it.
float max_finite = 3.4028234663852885981170418348451692544e+38;
// The half-way point between the max-finite and infinity value.
// Since infinity has an even significand everything equal or greater than
// this value should become infinity.
double half_max_finite_infinity =
3.40282356779733661637539395458142568448e+38;
if (d >= max_finite) {
if (d >= half_max_finite_infinity) {
return Single::Infinity();
} else {
return max_finite;
}
} else {
return static_cast<float>(d);
}
}
float Strtof(Vector<const char> buffer, int exponent) {
char copy_buffer[kMaxSignificantDecimalDigits];
Vector<const char> trimmed;
@@ -483,7 +507,7 @@ float Strtof(Vector<const char> buffer, int exponent) {
double double_guess;
bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
float float_guess = static_cast<float>(double_guess);
float float_guess = SanitizedDoubletof(double_guess);
if (float_guess == double_guess) {
// This shortcut triggers for integer values.
return float_guess;
@@ -506,15 +530,15 @@ float Strtof(Vector<const char> buffer, int exponent) {
double double_next = Double(double_guess).NextDouble();
double double_previous = Double(double_guess).PreviousDouble();
float f1 = static_cast<float>(double_previous);
float f1 = SanitizedDoubletof(double_previous);
float f2 = float_guess;
float f3 = static_cast<float>(double_next);
float f3 = SanitizedDoubletof(double_next);
float f4;
if (is_correct) {
f4 = f3;
} else {
double double_next2 = Double(double_next).NextDouble();
f4 = static_cast<float>(double_next2);
f4 = SanitizedDoubletof(double_next2);
}
(void) f2; // Mark variable as used.
ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4);
@@ -529,7 +553,7 @@ float Strtof(Vector<const char> buffer, int exponent) {
(f1 == f2 && f2 != f3 && f3 == f4) ||
(f1 == f2 && f2 == f3 && f3 != f4));
// guess and next are the two possible canditates (in the same way that
// guess and next are the two possible candidates (in the same way that
// double_guess was the lower candidate for a double-precision guess).
float guess = f1;
float next = f4;

View File

@@ -28,10 +28,10 @@
#ifndef DOUBLE_CONVERSION_UTILS_H_
#define DOUBLE_CONVERSION_UTILS_H_
#include <stdlib.h>
#include <string.h>
#include <cstdlib>
#include <cstring>
#include <assert.h>
#include <cassert>
#ifndef ASSERT
#define ASSERT(condition) \
assert(condition);
@@ -39,9 +39,30 @@
#ifndef UNIMPLEMENTED
#define UNIMPLEMENTED() (abort())
#endif
#ifndef DOUBLE_CONVERSION_NO_RETURN
#ifdef _MSC_VER
#define DOUBLE_CONVERSION_NO_RETURN __declspec(noreturn)
#else
#define DOUBLE_CONVERSION_NO_RETURN __attribute__((noreturn))
#endif
#endif
#ifndef UNREACHABLE
#ifdef _MSC_VER
void DOUBLE_CONVERSION_NO_RETURN abort_noreturn();
inline void abort_noreturn() { abort(); }
#define UNREACHABLE() (abort_noreturn())
#else
#define UNREACHABLE() (abort())
#endif
#endif
#ifndef DOUBLE_CONVERSION_UNUSED
#ifdef __GNUC__
#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
#else
#define DOUBLE_CONVERSION_UNUSED
#endif
#endif
// Double operations detection based on target architecture.
// Linux uses a 80bit wide floating point stack on x86. This induces double
@@ -53,19 +74,39 @@
// the output of the division with the expected result. (Inlining must be
// disabled.)
// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
//
// For example:
/*
// -- in div.c
double Div_double(double x, double y) { return x / y; }
// -- in main.c
double Div_double(double x, double y); // Forward declaration.
int main(int argc, char** argv) {
return Div_double(89255.0, 1e22) == 89255e-22;
}
*/
// Run as follows ./main || echo "correct"
//
// If it prints "correct" then the architecture should be here, in the "correct" section.
#if defined(_M_X64) || defined(__x86_64__) || \
defined(__ARMEL__) || defined(_M_ARM) || defined(__arm__) || defined(__arm64__) || \
defined(__avr32__) || \
defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
defined(__hppa__) || defined(__ia64__) || \
defined(__mips__) || \
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
defined(__SH4__) || defined(__alpha__) || \
defined(_MIPS_ARCH_MIPS32R2) || \
defined(_MIPS_ARCH_MIPS32R2) || defined(__ARMEB__) ||\
defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \
defined(__riscv) || \
defined(__AARCH64EL__) || \
defined(nios2) || defined(__nios2) || defined(__nios2__)
defined(__or1k__) || defined(__arc__) || \
defined(__EMSCRIPTEN__)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
#elif defined(__mc68000__) || \
defined(__pnacl__) || defined(__native_client__)
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
#if defined(_WIN32)
// Windows uses a 64bit wide floating point stack.
@@ -77,12 +118,6 @@
#error Target architecture was not detected as supported by Double-Conversion.
#endif
#if defined(__GNUC__)
#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
#else
#define DOUBLE_CONVERSION_UNUSED
#endif
#if defined(_WIN32) && !defined(__MINGW32__)
typedef signed char int8_t;
@@ -101,6 +136,8 @@ typedef unsigned __int64 uint64_t;
#endif
typedef uint16_t uc16;
// The following macro works on both 32 and 64-bit platforms.
// Usage: instead of writing 0x1234567890123456
// write UINT64_2PART_C(0x12345678,90123456);
@@ -119,8 +156,8 @@ typedef unsigned __int64 uint64_t;
// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
#ifndef DISALLOW_COPY_AND_ASSIGN
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
#ifndef DC_DISALLOW_COPY_AND_ASSIGN
#define DC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
#endif
@@ -131,10 +168,10 @@ typedef unsigned __int64 uint64_t;
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
#ifndef DC_DISALLOW_IMPLICIT_CONSTRUCTORS
#define DC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName(); \
DISALLOW_COPY_AND_ASSIGN(TypeName)
DC_DISALLOW_COPY_AND_ASSIGN(TypeName)
#endif
namespace double_conversion {
@@ -166,8 +203,8 @@ template <typename T>
class Vector {
public:
Vector() : start_(NULL), length_(0) {}
Vector(T* data, int length) : start_(data), length_(length) {
ASSERT(length == 0 || (length > 0 && data != NULL));
Vector(T* data, int len) : start_(data), length_(len) {
ASSERT(len == 0 || (len > 0 && data != NULL));
}
// Returns a vector using the same backing storage as this one,
@@ -209,8 +246,8 @@ class Vector {
// buffer bounds on all operations in debug mode.
class StringBuilder {
public:
StringBuilder(char* buffer, int size)
: buffer_(buffer, size), position_(0) { }
StringBuilder(char* buffer, int buffer_size)
: buffer_(buffer, buffer_size), position_(0) { }
~StringBuilder() { if (!is_finalized()) Finalize(); }
@@ -276,7 +313,7 @@ class StringBuilder {
bool is_finalized() const { return position_ < 0; }
DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
};
// The type-based aliasing rule allows the compiler to assume that pointers of
@@ -307,8 +344,13 @@ template <class Dest, class Source>
inline Dest BitCast(const Source& source) {
// Compile time assertion: sizeof(Dest) == sizeof(Source)
// A compile error here means your Dest and Source have different sizes.
#if __cplusplus >= 201103L
static_assert(sizeof(Dest) == sizeof(Source),
"source and destination size mismatch");
#else
DOUBLE_CONVERSION_UNUSED
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
#endif
Dest dest;
memmove(&dest, &source, sizeof(dest));