diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/poco/Foundation/src/NumericString.cpp | |
parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
download | ydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/poco/Foundation/src/NumericString.cpp')
-rw-r--r-- | contrib/libs/poco/Foundation/src/NumericString.cpp | 640 |
1 files changed, 320 insertions, 320 deletions
diff --git a/contrib/libs/poco/Foundation/src/NumericString.cpp b/contrib/libs/poco/Foundation/src/NumericString.cpp index f047c5db72..02171ab7cf 100644 --- a/contrib/libs/poco/Foundation/src/NumericString.cpp +++ b/contrib/libs/poco/Foundation/src/NumericString.cpp @@ -1,320 +1,320 @@ -// -// NumericString.h -// -// Library: Foundation -// Package: Core -// Module: NumericString -// -// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/NumericString.h" - - -#if defined(POCO_UNBUNDLED) -#include <double-conversion/double-conversion.h> -#include <double-conversion/ieee.h> -#else -#include "Poco/Bugcheck.h" -// +++ double conversion +++ -#define UNREACHABLE poco_bugcheck -#define UNIMPLEMENTED poco_bugcheck -#error #include "diy-fp.cc" -#error #include "cached-powers.cc" -#error #include "bignum-dtoa.cc" -#error #include "bignum.cc" -#error #include "fast-dtoa.cc" -#error #include "fixed-dtoa.cc" -#error #include "strtod.cc" -#error #include "double-conversion.cc" -// --- double conversion --- -poco_static_assert(POCO_MAX_FLT_STRING_LEN == double_conversion::kMaxSignificantDecimalDigits); -#endif - -#include "Poco/String.h" -#include <memory> -#include <cctype> - - -namespace { - - -void pad(std::string& str, int precision, int width, char prefix = ' ', char decSep = '.') - /// Pads the string with prefix space and postfix 0. - /// Alternative prefix (e.g. zero instead of space) can be supplied by caller. - /// Used only internally. -{ - // these cases should never happen, if they do, it's a library bug - poco_assert_dbg (precision > 0); - poco_assert_dbg (str.length()); - - std::string::size_type decSepPos = str.find(decSep); - if (decSepPos == std::string::npos) - { - str.append(1, '.'); - decSepPos = str.size() - 1; - } - - std::string::size_type frac = str.length() - decSepPos - 1; - - std::string::size_type ePos = str.find_first_of("eE"); -#ifndef POCO_ENABLE_CPP11 - std::auto_ptr<std::string> eStr; -#else - std::unique_ptr<std::string> eStr; -#endif // POCO_ENABLE_CPP11 - if (ePos != std::string::npos) - { - eStr.reset(new std::string(str.substr(ePos, std::string::npos))); - frac -= eStr->length(); - str = str.substr(0, str.length() - eStr->length()); - } - - if (frac != precision) - { - if (frac < precision) - str.append(precision - frac, '0'); - else if ((frac > precision) && (decSepPos != std::string::npos)) - str = str.substr(0, decSepPos + 1 + precision); - } - - if (eStr.get()) str += *eStr; - - if (width && (str.length() < width)) str.insert(str.begin(), width - str.length(), prefix); -} - - -void insertThousandSep(std::string& str, char thSep, char decSep = '.') - /// Inserts thousand separators. - /// Used only internally. -{ - poco_assert (decSep != thSep); - if (str.size() == 0) return; - - std::string::size_type exPos = str.find('e'); - if (exPos == std::string::npos) exPos = str.find('E'); - std::string::size_type decPos = str.find(decSep); - // there's no rinsert, using forward iterator to go backwards - std::string::iterator it = str.end(); - if (exPos != std::string::npos) it -= str.size() - exPos; - - if (decPos != std::string::npos) - { - while (it != str.begin()) - { - --it; - if (*it == decSep) break; - } - } - int thCount = 0; - if (it == str.end()) --it; - for (; it != str.begin();) - { - std::string::iterator pos = it; - std::string::value_type chr = *it; - std::string::value_type prevChr = *--it; - - if (!std::isdigit(chr)) continue; - - if (++thCount == 3 && std::isdigit(prevChr)) - it = str.insert(pos, thSep); - - if (thCount == 3) thCount = 0; - } -} - - -} // namespace - - -namespace Poco { - - -void floatToStr(char* buffer, int bufferSize, float value, int lowDec, int highDec) -{ - using namespace double_conversion; - - StringBuilder builder(buffer, bufferSize); - int flags = DoubleToStringConverter::UNIQUE_ZERO | - DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; - DoubleToStringConverter dc(flags, POCO_FLT_INF, POCO_FLT_NAN, POCO_FLT_EXP, lowDec, highDec, 0, 0); - dc.ToShortestSingle(value, &builder); - builder.Finalize(); -} - - -void floatToFixedStr(char* buffer, int bufferSize, float value, int precision) -{ - using namespace double_conversion; - - StringBuilder builder(buffer, bufferSize); - int flags = DoubleToStringConverter::UNIQUE_ZERO | - DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; - DoubleToStringConverter dc(flags, POCO_FLT_INF, POCO_FLT_NAN, POCO_FLT_EXP, -std::numeric_limits<float>::digits10, std::numeric_limits<float>::digits10, 0, 0); - dc.ToFixed(value, precision, &builder); - builder.Finalize(); -} - - -std::string& floatToStr(std::string& str, float value, int precision, int width, char thSep, char decSep) -{ - if (!decSep) decSep = '.'; - if (precision == 0) value = std::floor(value); - - char buffer[POCO_MAX_FLT_STRING_LEN]; - floatToStr(buffer, POCO_MAX_FLT_STRING_LEN, value); - str = buffer; - - if (decSep && (decSep != '.') && (str.find('.') != std::string::npos)) - replaceInPlace(str, '.', decSep); - - if (thSep) insertThousandSep(str, thSep, decSep); - if (precision > 0 || width) pad(str, precision, width, ' ', decSep ? decSep : '.'); - return str; -} - - -std::string& floatToFixedStr(std::string& str, float value, int precision, int width, char thSep, char decSep) -{ - if (!decSep) decSep = '.'; - if (precision == 0) value = std::floor(value); - - char buffer[POCO_MAX_FLT_STRING_LEN]; - floatToFixedStr(buffer, POCO_MAX_FLT_STRING_LEN, value, precision); - str = buffer; - - if (decSep && (decSep != '.') && (str.find('.') != std::string::npos)) - replaceInPlace(str, '.', decSep); - - if (thSep) insertThousandSep(str, thSep, decSep); - if (precision > 0 || width) pad(str, precision, width, ' ', decSep ? decSep : '.'); - return str; -} - - -void doubleToStr(char* buffer, int bufferSize, double value, int lowDec, int highDec) -{ - using namespace double_conversion; - - StringBuilder builder(buffer, bufferSize); - int flags = DoubleToStringConverter::UNIQUE_ZERO | - DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; - DoubleToStringConverter dc(flags, POCO_FLT_INF, POCO_FLT_NAN, POCO_FLT_EXP, lowDec, highDec, 0, 0); - dc.ToShortest(value, &builder); - builder.Finalize(); -} - - -void doubleToFixedStr(char* buffer, int bufferSize, double value, int precision) -{ - using namespace double_conversion; - - StringBuilder builder(buffer, bufferSize); - int flags = DoubleToStringConverter::UNIQUE_ZERO | - DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; - DoubleToStringConverter dc(flags, POCO_FLT_INF, POCO_FLT_NAN, POCO_FLT_EXP, -std::numeric_limits<double>::digits10, std::numeric_limits<double>::digits10, 0, 0); - dc.ToFixed(value, precision, &builder); - builder.Finalize(); -} - - -std::string& doubleToStr(std::string& str, double value, int precision, int width, char thSep, char decSep) -{ - if (!decSep) decSep = '.'; - if (precision == 0) value = std::floor(value); - - char buffer[POCO_MAX_FLT_STRING_LEN]; - doubleToStr(buffer, POCO_MAX_FLT_STRING_LEN, value); - - str = buffer; - - if (decSep && (decSep != '.') && (str.find('.') != std::string::npos)) - replaceInPlace(str, '.', decSep); - - if (thSep) insertThousandSep(str, thSep, decSep); - if (precision > 0 || width) pad(str, precision, width, ' ', decSep ? decSep : '.'); - return str; -} - - -std::string& doubleToFixedStr(std::string& str, double value, int precision, int width, char thSep, char decSep) -{ - if (!decSep) decSep = '.'; - if (precision == 0) value = std::floor(value); - - char buffer[POCO_MAX_FLT_STRING_LEN]; - doubleToFixedStr(buffer, POCO_MAX_FLT_STRING_LEN, value, precision); - - str = buffer; - - if (decSep && (decSep != '.') && (str.find('.') != std::string::npos)) - replaceInPlace(str, '.', decSep); - - if (thSep) insertThousandSep(str, thSep, decSep); - if (precision > 0 || width) pad(str, precision, width, ' ', decSep ? decSep : '.'); - return str; -} - - -float strToFloat(const char* str) -{ - using namespace double_conversion; - - int processed; - int flags = StringToDoubleConverter::ALLOW_LEADING_SPACES | - StringToDoubleConverter::ALLOW_TRAILING_SPACES; - StringToDoubleConverter converter(flags, 0.0, Single::NaN(), POCO_FLT_INF, POCO_FLT_NAN); - float result = converter.StringToFloat(str, static_cast<int>(strlen(str)), &processed); - return result; -} - - -double strToDouble(const char* str) -{ - using namespace double_conversion; - int processed; - int flags = StringToDoubleConverter::ALLOW_LEADING_SPACES | - StringToDoubleConverter::ALLOW_TRAILING_SPACES; - StringToDoubleConverter converter(flags, 0.0, Double::NaN(), POCO_FLT_INF, POCO_FLT_NAN); - double result = converter.StringToDouble(str, static_cast<int>(strlen(str)), &processed); - return result; -} - - -bool strToFloat(const std::string& str, float& result, char decSep, char thSep) -{ - using namespace double_conversion; - - std::string tmp(str); - trimInPlace(tmp); - removeInPlace(tmp, thSep); - removeInPlace(tmp, 'f'); - replaceInPlace(tmp, decSep, '.'); - result = strToFloat(tmp.c_str()); - return !FPEnvironment::isInfinite(result) && - !FPEnvironment::isNaN(result); -} - - -bool strToDouble(const std::string& str, double& result, char decSep, char thSep) -{ - if (str.empty()) return false; - - using namespace double_conversion; - - std::string tmp(str); - trimInPlace(tmp); - removeInPlace(tmp, thSep); - replaceInPlace(tmp, decSep, '.'); - removeInPlace(tmp, 'f'); - result = strToDouble(tmp.c_str()); - return !FPEnvironment::isInfinite(result) && - !FPEnvironment::isNaN(result); -} - - -} // namespace Poco +// +// NumericString.h +// +// Library: Foundation +// Package: Core +// Module: NumericString +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/NumericString.h" + + +#if defined(POCO_UNBUNDLED) +#include <double-conversion/double-conversion.h> +#include <double-conversion/ieee.h> +#else +#include "Poco/Bugcheck.h" +// +++ double conversion +++ +#define UNREACHABLE poco_bugcheck +#define UNIMPLEMENTED poco_bugcheck +#error #include "diy-fp.cc" +#error #include "cached-powers.cc" +#error #include "bignum-dtoa.cc" +#error #include "bignum.cc" +#error #include "fast-dtoa.cc" +#error #include "fixed-dtoa.cc" +#error #include "strtod.cc" +#error #include "double-conversion.cc" +// --- double conversion --- +poco_static_assert(POCO_MAX_FLT_STRING_LEN == double_conversion::kMaxSignificantDecimalDigits); +#endif + +#include "Poco/String.h" +#include <memory> +#include <cctype> + + +namespace { + + +void pad(std::string& str, int precision, int width, char prefix = ' ', char decSep = '.') + /// Pads the string with prefix space and postfix 0. + /// Alternative prefix (e.g. zero instead of space) can be supplied by caller. + /// Used only internally. +{ + // these cases should never happen, if they do, it's a library bug + poco_assert_dbg (precision > 0); + poco_assert_dbg (str.length()); + + std::string::size_type decSepPos = str.find(decSep); + if (decSepPos == std::string::npos) + { + str.append(1, '.'); + decSepPos = str.size() - 1; + } + + std::string::size_type frac = str.length() - decSepPos - 1; + + std::string::size_type ePos = str.find_first_of("eE"); +#ifndef POCO_ENABLE_CPP11 + std::auto_ptr<std::string> eStr; +#else + std::unique_ptr<std::string> eStr; +#endif // POCO_ENABLE_CPP11 + if (ePos != std::string::npos) + { + eStr.reset(new std::string(str.substr(ePos, std::string::npos))); + frac -= eStr->length(); + str = str.substr(0, str.length() - eStr->length()); + } + + if (frac != precision) + { + if (frac < precision) + str.append(precision - frac, '0'); + else if ((frac > precision) && (decSepPos != std::string::npos)) + str = str.substr(0, decSepPos + 1 + precision); + } + + if (eStr.get()) str += *eStr; + + if (width && (str.length() < width)) str.insert(str.begin(), width - str.length(), prefix); +} + + +void insertThousandSep(std::string& str, char thSep, char decSep = '.') + /// Inserts thousand separators. + /// Used only internally. +{ + poco_assert (decSep != thSep); + if (str.size() == 0) return; + + std::string::size_type exPos = str.find('e'); + if (exPos == std::string::npos) exPos = str.find('E'); + std::string::size_type decPos = str.find(decSep); + // there's no rinsert, using forward iterator to go backwards + std::string::iterator it = str.end(); + if (exPos != std::string::npos) it -= str.size() - exPos; + + if (decPos != std::string::npos) + { + while (it != str.begin()) + { + --it; + if (*it == decSep) break; + } + } + int thCount = 0; + if (it == str.end()) --it; + for (; it != str.begin();) + { + std::string::iterator pos = it; + std::string::value_type chr = *it; + std::string::value_type prevChr = *--it; + + if (!std::isdigit(chr)) continue; + + if (++thCount == 3 && std::isdigit(prevChr)) + it = str.insert(pos, thSep); + + if (thCount == 3) thCount = 0; + } +} + + +} // namespace + + +namespace Poco { + + +void floatToStr(char* buffer, int bufferSize, float value, int lowDec, int highDec) +{ + using namespace double_conversion; + + StringBuilder builder(buffer, bufferSize); + int flags = DoubleToStringConverter::UNIQUE_ZERO | + DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; + DoubleToStringConverter dc(flags, POCO_FLT_INF, POCO_FLT_NAN, POCO_FLT_EXP, lowDec, highDec, 0, 0); + dc.ToShortestSingle(value, &builder); + builder.Finalize(); +} + + +void floatToFixedStr(char* buffer, int bufferSize, float value, int precision) +{ + using namespace double_conversion; + + StringBuilder builder(buffer, bufferSize); + int flags = DoubleToStringConverter::UNIQUE_ZERO | + DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; + DoubleToStringConverter dc(flags, POCO_FLT_INF, POCO_FLT_NAN, POCO_FLT_EXP, -std::numeric_limits<float>::digits10, std::numeric_limits<float>::digits10, 0, 0); + dc.ToFixed(value, precision, &builder); + builder.Finalize(); +} + + +std::string& floatToStr(std::string& str, float value, int precision, int width, char thSep, char decSep) +{ + if (!decSep) decSep = '.'; + if (precision == 0) value = std::floor(value); + + char buffer[POCO_MAX_FLT_STRING_LEN]; + floatToStr(buffer, POCO_MAX_FLT_STRING_LEN, value); + str = buffer; + + if (decSep && (decSep != '.') && (str.find('.') != std::string::npos)) + replaceInPlace(str, '.', decSep); + + if (thSep) insertThousandSep(str, thSep, decSep); + if (precision > 0 || width) pad(str, precision, width, ' ', decSep ? decSep : '.'); + return str; +} + + +std::string& floatToFixedStr(std::string& str, float value, int precision, int width, char thSep, char decSep) +{ + if (!decSep) decSep = '.'; + if (precision == 0) value = std::floor(value); + + char buffer[POCO_MAX_FLT_STRING_LEN]; + floatToFixedStr(buffer, POCO_MAX_FLT_STRING_LEN, value, precision); + str = buffer; + + if (decSep && (decSep != '.') && (str.find('.') != std::string::npos)) + replaceInPlace(str, '.', decSep); + + if (thSep) insertThousandSep(str, thSep, decSep); + if (precision > 0 || width) pad(str, precision, width, ' ', decSep ? decSep : '.'); + return str; +} + + +void doubleToStr(char* buffer, int bufferSize, double value, int lowDec, int highDec) +{ + using namespace double_conversion; + + StringBuilder builder(buffer, bufferSize); + int flags = DoubleToStringConverter::UNIQUE_ZERO | + DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; + DoubleToStringConverter dc(flags, POCO_FLT_INF, POCO_FLT_NAN, POCO_FLT_EXP, lowDec, highDec, 0, 0); + dc.ToShortest(value, &builder); + builder.Finalize(); +} + + +void doubleToFixedStr(char* buffer, int bufferSize, double value, int precision) +{ + using namespace double_conversion; + + StringBuilder builder(buffer, bufferSize); + int flags = DoubleToStringConverter::UNIQUE_ZERO | + DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN; + DoubleToStringConverter dc(flags, POCO_FLT_INF, POCO_FLT_NAN, POCO_FLT_EXP, -std::numeric_limits<double>::digits10, std::numeric_limits<double>::digits10, 0, 0); + dc.ToFixed(value, precision, &builder); + builder.Finalize(); +} + + +std::string& doubleToStr(std::string& str, double value, int precision, int width, char thSep, char decSep) +{ + if (!decSep) decSep = '.'; + if (precision == 0) value = std::floor(value); + + char buffer[POCO_MAX_FLT_STRING_LEN]; + doubleToStr(buffer, POCO_MAX_FLT_STRING_LEN, value); + + str = buffer; + + if (decSep && (decSep != '.') && (str.find('.') != std::string::npos)) + replaceInPlace(str, '.', decSep); + + if (thSep) insertThousandSep(str, thSep, decSep); + if (precision > 0 || width) pad(str, precision, width, ' ', decSep ? decSep : '.'); + return str; +} + + +std::string& doubleToFixedStr(std::string& str, double value, int precision, int width, char thSep, char decSep) +{ + if (!decSep) decSep = '.'; + if (precision == 0) value = std::floor(value); + + char buffer[POCO_MAX_FLT_STRING_LEN]; + doubleToFixedStr(buffer, POCO_MAX_FLT_STRING_LEN, value, precision); + + str = buffer; + + if (decSep && (decSep != '.') && (str.find('.') != std::string::npos)) + replaceInPlace(str, '.', decSep); + + if (thSep) insertThousandSep(str, thSep, decSep); + if (precision > 0 || width) pad(str, precision, width, ' ', decSep ? decSep : '.'); + return str; +} + + +float strToFloat(const char* str) +{ + using namespace double_conversion; + + int processed; + int flags = StringToDoubleConverter::ALLOW_LEADING_SPACES | + StringToDoubleConverter::ALLOW_TRAILING_SPACES; + StringToDoubleConverter converter(flags, 0.0, Single::NaN(), POCO_FLT_INF, POCO_FLT_NAN); + float result = converter.StringToFloat(str, static_cast<int>(strlen(str)), &processed); + return result; +} + + +double strToDouble(const char* str) +{ + using namespace double_conversion; + int processed; + int flags = StringToDoubleConverter::ALLOW_LEADING_SPACES | + StringToDoubleConverter::ALLOW_TRAILING_SPACES; + StringToDoubleConverter converter(flags, 0.0, Double::NaN(), POCO_FLT_INF, POCO_FLT_NAN); + double result = converter.StringToDouble(str, static_cast<int>(strlen(str)), &processed); + return result; +} + + +bool strToFloat(const std::string& str, float& result, char decSep, char thSep) +{ + using namespace double_conversion; + + std::string tmp(str); + trimInPlace(tmp); + removeInPlace(tmp, thSep); + removeInPlace(tmp, 'f'); + replaceInPlace(tmp, decSep, '.'); + result = strToFloat(tmp.c_str()); + return !FPEnvironment::isInfinite(result) && + !FPEnvironment::isNaN(result); +} + + +bool strToDouble(const std::string& str, double& result, char decSep, char thSep) +{ + if (str.empty()) return false; + + using namespace double_conversion; + + std::string tmp(str); + trimInPlace(tmp); + removeInPlace(tmp, thSep); + replaceInPlace(tmp, decSep, '.'); + removeInPlace(tmp, 'f'); + result = strToDouble(tmp.c_str()); + return !FPEnvironment::isInfinite(result) && + !FPEnvironment::isNaN(result); +} + + +} // namespace Poco |