aboutsummaryrefslogtreecommitdiffstats
path: root/util/string/cast.cpp
diff options
context:
space:
mode:
authorAnton Samokhvalov <pg83@yandex.ru>2022-02-10 16:45:17 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:17 +0300
commitd3a398281c6fd1d3672036cb2d63f842d2cb28c5 (patch)
treedd4bd3ca0f36b817e96812825ffaf10d645803f2 /util/string/cast.cpp
parent72cb13b4aff9bc9cf22e49251bc8fd143f82538f (diff)
downloadydb-d3a398281c6fd1d3672036cb2d63f842d2cb28c5.tar.gz
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 2 of 2.
Diffstat (limited to 'util/string/cast.cpp')
-rw-r--r--util/string/cast.cpp774
1 files changed, 387 insertions, 387 deletions
diff --git a/util/string/cast.cpp b/util/string/cast.cpp
index 3b1e050e53..aa1e65a8e9 100644
--- a/util/string/cast.cpp
+++ b/util/string/cast.cpp
@@ -1,41 +1,41 @@
#include <util/system/defaults.h>
-
-#if defined(_freebsd_) && !defined(__LONG_LONG_SUPPORTED)
- #define __LONG_LONG_SUPPORTED
-#endif
-
-#include <cstdio>
-#include <string>
+
+#if defined(_freebsd_) && !defined(__LONG_LONG_SUPPORTED)
+ #define __LONG_LONG_SUPPORTED
+#endif
+
+#include <cstdio>
+#include <string>
#include <cmath>
-
+
#include <util/string/type.h>
#include <util/string/cast.h>
#include <util/string/escape.h>
-
-#include <contrib/libs/double-conversion/double-conversion.h>
-
+
+#include <contrib/libs/double-conversion/double-conversion.h>
+
#include <util/generic/string.h>
#include <util/system/yassert.h>
#include <util/generic/yexception.h>
-#include <util/generic/typetraits.h>
+#include <util/generic/typetraits.h>
#include <util/generic/ylimits.h>
-#include <util/generic/singleton.h>
-#include <util/generic/utility.h>
-
-using double_conversion::DoubleToStringConverter;
-using double_conversion::StringBuilder;
-using double_conversion::StringToDoubleConverter;
-
-/*
- * ------------------------------ formatters ------------------------------
- */
+#include <util/generic/singleton.h>
+#include <util/generic/utility.h>
+
+using double_conversion::DoubleToStringConverter;
+using double_conversion::StringBuilder;
+using double_conversion::StringToDoubleConverter;
+
+/*
+ * ------------------------------ formatters ------------------------------
+ */
namespace {
constexpr char IntToChar[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
static_assert(Y_ARRAY_SIZE(IntToChar) == 16, "expect Y_ARRAY_SIZE(IntToChar) == 16");
- // clang-format off
+ // clang-format off
constexpr int LetterToIntMap[] = {
20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
@@ -49,23 +49,23 @@ namespace {
20, 20, 20, 20, 20, 20, 20, 10, 11, 12,
13, 14, 15,
};
- // clang-format on
+ // clang-format on
template <class T>
std::enable_if_t<std::is_signed<T>::value, std::make_unsigned_t<T>> NegateNegativeSigned(T value) noexcept {
- return std::make_unsigned_t<T>(-(value + 1)) + std::make_unsigned_t<T>(1);
+ return std::make_unsigned_t<T>(-(value + 1)) + std::make_unsigned_t<T>(1);
}
template <class T>
std::enable_if_t<std::is_unsigned<T>::value, std::make_unsigned_t<T>> NegateNegativeSigned(T) noexcept {
- Y_UNREACHABLE();
+ Y_UNREACHABLE();
}
- template <class T>
+ template <class T>
std::make_signed_t<T> NegatePositiveSigned(T value) noexcept {
- return value > 0 ? (-std::make_signed_t<T>(value - 1) - 1) : 0;
- }
-
+ return value > 0 ? (-std::make_signed_t<T>(value - 1) - 1) : 0;
+ }
+
template <class T, unsigned base, class TChar>
struct TBasicIntFormatter {
static_assert(1 < base && base < 17, "expect 1 < base && base < 17");
@@ -73,7 +73,7 @@ namespace {
static inline size_t Format(T value, TChar* buf, size_t len) {
Y_ENSURE(len, TStringBuf("zero length"));
-
+
TChar* tmp = buf;
do {
@@ -99,46 +99,46 @@ namespace {
}
return result;
- }
+ }
};
-
+
template <class T, unsigned base, class TChar>
struct TIntFormatter {
static_assert(1 < base && base < 17, "expect 1 < base && base < 17");
static_assert(std::is_integral<T>::value, "T must be an integral type.");
-
+
static inline size_t Format(T value, TChar* buf, size_t len) {
- using TUFmt = TBasicIntFormatter<std::make_unsigned_t<T>, base, TChar>;
+ using TUFmt = TBasicIntFormatter<std::make_unsigned_t<T>, base, TChar>;
- if (std::is_signed<T>::value && value < 0) {
+ if (std::is_signed<T>::value && value < 0) {
Y_ENSURE(len >= 2, TStringBuf("not enough room in buffer"));
*buf = '-';
-
- return 1 + TUFmt::Format(NegateNegativeSigned(value), buf + 1, len - 1);
+
+ return 1 + TUFmt::Format(NegateNegativeSigned(value), buf + 1, len - 1);
}
- return TUFmt::Format(value, buf, len);
- }
+ return TUFmt::Format(value, buf, len);
+ }
};
-
+
template <class T>
struct TFltModifiers;
-
+
template <class T, int base, class TChar>
Y_NO_INLINE size_t FormatInt(T value, TChar* buf, size_t len) {
return TIntFormatter<T, base, TChar>::Format(value, buf, len);
}
-
+
template <class T>
inline size_t FormatFlt(T t, char* buf, size_t len) {
const int ret = snprintf(buf, len, TFltModifiers<T>::ModifierWrite, t);
-
+
Y_ENSURE(ret >= 0 && (size_t)ret <= len, TStringBuf("cannot format float"));
-
+
return (size_t)ret;
- }
-
+ }
+
enum EParseStatus {
PS_OK = 0,
PS_EMPTY_STRING,
@@ -147,97 +147,97 @@ namespace {
PS_BAD_SYMBOL,
PS_OVERFLOW,
};
-
+
constexpr ui8 SAFE_LENS[4][17] = {
- {0, 0, 7, 5, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1},
- {0, 0, 15, 10, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3},
- {0, 0, 31, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 7},
- {0, 0, 63, 40, 31, 27, 24, 22, 21, 20, 19, 18, 17, 17, 16, 16, 15},
- };
-
- inline constexpr ui8 ConstLog2(ui8 x) noexcept {
- return x == 1 ? 0 : 1 + ConstLog2(x / 2);
- }
-
- template <unsigned BASE, class TChar, class T>
+ {0, 0, 7, 5, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1},
+ {0, 0, 15, 10, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3},
+ {0, 0, 31, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 7},
+ {0, 0, 63, 40, 31, 27, 24, 22, 21, 20, 19, 18, 17, 17, 16, 16, 15},
+ };
+
+ inline constexpr ui8 ConstLog2(ui8 x) noexcept {
+ return x == 1 ? 0 : 1 + ConstLog2(x / 2);
+ }
+
+ template <unsigned BASE, class TChar, class T>
inline std::enable_if_t<(BASE > 10), bool> CharToDigit(TChar c, T* digit) noexcept {
- unsigned uc = c;
-
- if (uc >= Y_ARRAY_SIZE(LetterToIntMap)) {
- return false;
- }
-
- *digit = LetterToIntMap[uc];
-
- return *digit < BASE;
- }
-
- template <unsigned BASE, class TChar, class T>
+ unsigned uc = c;
+
+ if (uc >= Y_ARRAY_SIZE(LetterToIntMap)) {
+ return false;
+ }
+
+ *digit = LetterToIntMap[uc];
+
+ return *digit < BASE;
+ }
+
+ template <unsigned BASE, class TChar, class T>
inline std::enable_if_t<(BASE <= 10), bool> CharToDigit(TChar c, T* digit) noexcept {
- return (c >= '0') && ((*digit = (c - '0')) < BASE);
- }
-
+ return (c >= '0') && ((*digit = (c - '0')) < BASE);
+ }
+
template <class T, unsigned base, class TChar>
struct TBasicIntParser {
static_assert(1 < base && base < 17, "Expect 1 < base && base < 17.");
static_assert(std::is_unsigned<T>::value, "TBasicIntParser can only handle unsigned integers.");
- enum : unsigned {
- BASE_POW_2 = base * base,
- };
-
- static inline EParseStatus Parse(const TChar** ppos, const TChar* end, T max, T* target) noexcept {
+ enum : unsigned {
+ BASE_POW_2 = base * base,
+ };
+
+ static inline EParseStatus Parse(const TChar** ppos, const TChar* end, T max, T* target) noexcept {
Y_ASSERT(*ppos != end); /* This check should be somewhere up the stack. */
- const size_t maxSafeLen = SAFE_LENS[ConstLog2(sizeof(T))][base];
-
- // can parse without overflow
- if (size_t(end - *ppos) <= maxSafeLen) {
- T result;
-
- if (ParseFast(*ppos, end, &result) && result <= max) {
- *target = result;
-
- return PS_OK;
- }
- }
-
- return ParseSlow(ppos, end, max, target);
- }
-
- static inline bool ParseFast(const TChar* pos, const TChar* end, T* target) noexcept {
+ const size_t maxSafeLen = SAFE_LENS[ConstLog2(sizeof(T))][base];
+
+ // can parse without overflow
+ if (size_t(end - *ppos) <= maxSafeLen) {
+ T result;
+
+ if (ParseFast(*ppos, end, &result) && result <= max) {
+ *target = result;
+
+ return PS_OK;
+ }
+ }
+
+ return ParseSlow(ppos, end, max, target);
+ }
+
+ static inline bool ParseFast(const TChar* pos, const TChar* end, T* target) noexcept {
+ T result = T();
+ T d1;
+ T d2;
+
+ // we have end > pos
+ auto beforeEnd = end - 1;
+
+ while (pos < beforeEnd && CharToDigit<base>(*pos, &d1) && CharToDigit<base>(*(pos + 1), &d2)) {
+ result = result * BASE_POW_2 + d1 * base + d2;
+ pos += 2;
+ }
+
+ while (pos != end && CharToDigit<base>(*pos, &d1)) {
+ result = result * base + d1;
+ ++pos;
+ }
+
+ *target = result;
+
+ return pos == end;
+ }
+
+ static inline EParseStatus ParseSlow(const TChar** ppos, const TChar* end, T max, T* target) noexcept {
T result = T();
- T d1;
- T d2;
-
- // we have end > pos
- auto beforeEnd = end - 1;
-
- while (pos < beforeEnd && CharToDigit<base>(*pos, &d1) && CharToDigit<base>(*(pos + 1), &d2)) {
- result = result * BASE_POW_2 + d1 * base + d2;
- pos += 2;
- }
-
- while (pos != end && CharToDigit<base>(*pos, &d1)) {
- result = result * base + d1;
- ++pos;
- }
-
- *target = result;
-
- return pos == end;
- }
-
- static inline EParseStatus ParseSlow(const TChar** ppos, const TChar* end, T max, T* target) noexcept {
- T result = T();
T preMulMax = max / base;
const TChar* pos = *ppos;
while (pos != end) {
T digit;
-
- if (!CharToDigit<base>(*pos, &digit)) {
+
+ if (!CharToDigit<base>(*pos, &digit)) {
*ppos = pos;
-
+
return PS_BAD_SYMBOL;
}
@@ -256,7 +256,7 @@ namespace {
}
*target = result;
-
+
return PS_OK;
}
};
@@ -282,8 +282,8 @@ namespace {
const TChar* pos = *ppos;
if (pos == end) {
return PS_EMPTY_STRING;
- }
-
+ }
+
bool negative = false;
TUnsigned max;
if (*pos == '+') {
@@ -313,14 +313,14 @@ namespace {
}
if (IsSigned) {
- *target = negative ? NegatePositiveSigned(result) : static_cast<T>(result);
+ *target = negative ? NegatePositiveSigned(result) : static_cast<T>(result);
} else {
*target = result;
}
return PS_OK;
- }
+ }
};
-
+
template <class TChar>
[[noreturn]] static Y_NO_INLINE void ThrowParseError(EParseStatus status, const TChar* data, size_t len, const TChar* pos) {
Y_ASSERT(status != PS_OK);
@@ -341,21 +341,21 @@ namespace {
default:
ythrow yexception() << TStringBuf("Unknown error code in string converter. ");
}
- }
-
+ }
+
template <typename T, typename TUnsigned, int base, typename TChar>
Y_NO_INLINE T ParseInt(const TChar* data, size_t len, const TBounds<TUnsigned>& bounds) {
T result;
const TChar* pos = data;
EParseStatus status = TIntParser<T, base, TChar>::Parse(&pos, pos + len, bounds, &result);
-
+
if (status == PS_OK) {
return result;
} else {
ThrowParseError(status, data, len, pos);
}
}
-
+
template <typename T, typename TUnsigned, int base, typename TChar>
Y_NO_INLINE bool TryParseInt(const TChar* data, size_t len, const TBounds<TUnsigned>& bounds, T* result) {
return TIntParser<T, base, TChar>::Parse(&data, data + len, bounds, result) == PS_OK;
@@ -387,20 +387,20 @@ namespace {
ythrow TFromStringException() << TStringBuf("cannot parse float(") << TStringBuf(data, len) << TStringBuf(")");
}
-#define DEF_FLT_MOD(type, modifierWrite, modifierRead) \
- template <> \
- struct TFltModifiers<type> { \
- static const char* const ModifierWrite; \
- static const char* const ModifierReadAndChar; \
- }; \
- \
- const char* const TFltModifiers<type>::ModifierWrite = modifierWrite; \
- const char* const TFltModifiers<type>::ModifierReadAndChar = modifierRead "%c";
-
+#define DEF_FLT_MOD(type, modifierWrite, modifierRead) \
+ template <> \
+ struct TFltModifiers<type> { \
+ static const char* const ModifierWrite; \
+ static const char* const ModifierReadAndChar; \
+ }; \
+ \
+ const char* const TFltModifiers<type>::ModifierWrite = modifierWrite; \
+ const char* const TFltModifiers<type>::ModifierReadAndChar = modifierRead "%c";
+
DEF_FLT_MOD(long double, "%.10Lg", "%Lg")
-
-#undef DEF_FLT_MOD
-
+
+#undef DEF_FLT_MOD
+
/* The following constants are initialized in terms of <climits> constants to make
* sure they go into binary as actual values and there is no associated
* initialization code.
@@ -415,34 +415,34 @@ namespace {
constexpr TBounds<ui64> lUBounds = {static_cast<ui64>(ULONG_MAX), 0};
constexpr TBounds<ui64> llSBounds = {static_cast<ui64>(LLONG_MAX), static_cast<ui64>(ULLONG_MAX - LLONG_MAX)};
constexpr TBounds<ui64> llUBounds = {static_cast<ui64>(ULLONG_MAX), 0};
-}
-
-#define DEF_INT_SPEC_II(TYPE, ITYPE, BASE) \
- template <> \
- size_t IntToString<BASE, TYPE>(TYPE value, char* buf, size_t len) { \
- return FormatInt<ITYPE, BASE, char>(value, buf, len); \
- }
-
-#define DEF_INT_SPEC_I(TYPE, ITYPE) \
- template <> \
- size_t ToStringImpl<TYPE>(TYPE value, char* buf, size_t len) { \
- return FormatInt<ITYPE, 10, char>(value, buf, len); \
- } \
- DEF_INT_SPEC_II(TYPE, ITYPE, 2) \
- DEF_INT_SPEC_II(TYPE, ITYPE, 8) \
- DEF_INT_SPEC_II(TYPE, ITYPE, 10) \
+}
+
+#define DEF_INT_SPEC_II(TYPE, ITYPE, BASE) \
+ template <> \
+ size_t IntToString<BASE, TYPE>(TYPE value, char* buf, size_t len) { \
+ return FormatInt<ITYPE, BASE, char>(value, buf, len); \
+ }
+
+#define DEF_INT_SPEC_I(TYPE, ITYPE) \
+ template <> \
+ size_t ToStringImpl<TYPE>(TYPE value, char* buf, size_t len) { \
+ return FormatInt<ITYPE, 10, char>(value, buf, len); \
+ } \
+ DEF_INT_SPEC_II(TYPE, ITYPE, 2) \
+ DEF_INT_SPEC_II(TYPE, ITYPE, 8) \
+ DEF_INT_SPEC_II(TYPE, ITYPE, 10) \
DEF_INT_SPEC_II(TYPE, ITYPE, 16)
-
-#define DEF_INT_SPEC(TYPE) \
- DEF_INT_SPEC_I(signed TYPE, i64) \
+
+#define DEF_INT_SPEC(TYPE) \
+ DEF_INT_SPEC_I(signed TYPE, i64) \
DEF_INT_SPEC_I(unsigned TYPE, ui64)
-
-DEF_INT_SPEC(char)
-DEF_INT_SPEC(short)
-DEF_INT_SPEC(int)
-DEF_INT_SPEC(long)
-DEF_INT_SPEC(long long)
-
+
+DEF_INT_SPEC(char)
+DEF_INT_SPEC(short)
+DEF_INT_SPEC(int)
+DEF_INT_SPEC(long)
+DEF_INT_SPEC(long long)
+
#ifdef __cpp_char8_t
template <>
size_t ToStringImpl<char8_t>(char8_t value, char* buf, size_t len) {
@@ -458,20 +458,20 @@ DEF_INT_SPEC_I(wchar_t, TWCharIType)
DEF_INT_SPEC_I(wchar16, ui64) // wchar16 is always unsigned
DEF_INT_SPEC_I(wchar32, ui64) // wchar32 is always unsigned
-#undef DEF_INT_SPEC
+#undef DEF_INT_SPEC
#undef DEF_INT_SPEC_I
#undef DEF_INT_SPEC_II
-
-#define DEF_FLT_SPEC(type) \
- template <> \
- size_t ToStringImpl<type>(type t, char* buf, size_t len) { \
- return FormatFlt<type>(t, buf, len); \
- }
-
+
+#define DEF_FLT_SPEC(type) \
+ template <> \
+ size_t ToStringImpl<type>(type t, char* buf, size_t len) { \
+ return FormatFlt<type>(t, buf, len); \
+ }
+
DEF_FLT_SPEC(long double)
-#undef DEF_FLT_SPEC
-
+#undef DEF_FLT_SPEC
+
template <>
size_t ToStringImpl<bool>(bool t, char* buf, size_t len) {
Y_ENSURE(len, TStringBuf("zero length"));
@@ -479,9 +479,9 @@ size_t ToStringImpl<bool>(bool t, char* buf, size_t len) {
return 1;
}
-/*
- * ------------------------------ parsers ------------------------------
- */
+/*
+ * ------------------------------ parsers ------------------------------
+ */
template <>
bool TryFromStringImpl<bool>(const char* data, size_t len, bool& result) {
@@ -508,11 +508,11 @@ bool TryFromStringImpl<bool>(const char* data, size_t len, bool& result) {
template <>
bool FromStringImpl<bool>(const char* data, size_t len) {
bool result;
-
- if (!TryFromStringImpl<bool>(data, len, result)) {
+
+ if (!TryFromStringImpl<bool>(data, len, result)) {
ythrow TFromStringException() << TStringBuf("Cannot parse bool(") << TStringBuf(data, len) << TStringBuf("). ");
- }
-
+ }
+
return result;
}
@@ -527,8 +527,8 @@ TStringBuf FromStringImpl<TStringBuf>(const char* data, size_t len) {
}
template <>
-std::string FromStringImpl<std::string>(const char* data, size_t len) {
- return std::string(data, len);
+std::string FromStringImpl<std::string>(const char* data, size_t len) {
+ return std::string(data, len);
}
template <>
@@ -555,7 +555,7 @@ bool TryFromStringImpl<TString>(const char* data, size_t len, TString& result) {
}
template <>
-bool TryFromStringImpl<std::string>(const char* data, size_t len, std::string& result) {
+bool TryFromStringImpl<std::string>(const char* data, size_t len, std::string& result) {
result.assign(data, len);
return true;
}
@@ -572,46 +572,46 @@ bool TryFromStringImpl<TUtf16String>(const wchar16* data, size_t len, TUtf16Stri
return true;
}
-#define DEF_INT_SPEC_III(CHAR, TYPE, ITYPE, BOUNDS, BASE) \
- template <> \
- TYPE IntFromString<TYPE, BASE>(const CHAR* data, size_t len) { \
- return ParseInt<ITYPE, ui64, BASE>(data, len, BOUNDS); \
- } \
- template <> \
- bool TryIntFromString<BASE>(const CHAR* data, size_t len, TYPE& result) { \
- ITYPE tmp; \
- bool status = TryParseInt<ITYPE, ui64, BASE>(data, len, BOUNDS, &tmp); \
- if (status) { \
- result = tmp; \
- } \
- return status; \
- }
-
-#define DEF_INT_SPEC_II(CHAR, TYPE, ITYPE, BOUNDS) \
- template <> \
- TYPE FromStringImpl<TYPE>(const CHAR* data, size_t len) { \
- return ParseInt<ITYPE, ui64, 10>(data, len, BOUNDS); \
- } \
- template <> \
- bool TryFromStringImpl<TYPE>(const CHAR* data, size_t len, TYPE& result) { \
- ITYPE tmp; \
- bool status = TryParseInt<ITYPE, ui64, 10>(data, len, BOUNDS, &tmp); \
- if (status) { \
- result = tmp; \
- } \
- return status; \
- } \
- DEF_INT_SPEC_III(CHAR, TYPE, ITYPE, BOUNDS, 2) \
- DEF_INT_SPEC_III(CHAR, TYPE, ITYPE, BOUNDS, 8) \
- DEF_INT_SPEC_III(CHAR, TYPE, ITYPE, BOUNDS, 10) \
+#define DEF_INT_SPEC_III(CHAR, TYPE, ITYPE, BOUNDS, BASE) \
+ template <> \
+ TYPE IntFromString<TYPE, BASE>(const CHAR* data, size_t len) { \
+ return ParseInt<ITYPE, ui64, BASE>(data, len, BOUNDS); \
+ } \
+ template <> \
+ bool TryIntFromString<BASE>(const CHAR* data, size_t len, TYPE& result) { \
+ ITYPE tmp; \
+ bool status = TryParseInt<ITYPE, ui64, BASE>(data, len, BOUNDS, &tmp); \
+ if (status) { \
+ result = tmp; \
+ } \
+ return status; \
+ }
+
+#define DEF_INT_SPEC_II(CHAR, TYPE, ITYPE, BOUNDS) \
+ template <> \
+ TYPE FromStringImpl<TYPE>(const CHAR* data, size_t len) { \
+ return ParseInt<ITYPE, ui64, 10>(data, len, BOUNDS); \
+ } \
+ template <> \
+ bool TryFromStringImpl<TYPE>(const CHAR* data, size_t len, TYPE& result) { \
+ ITYPE tmp; \
+ bool status = TryParseInt<ITYPE, ui64, 10>(data, len, BOUNDS, &tmp); \
+ if (status) { \
+ result = tmp; \
+ } \
+ return status; \
+ } \
+ DEF_INT_SPEC_III(CHAR, TYPE, ITYPE, BOUNDS, 2) \
+ DEF_INT_SPEC_III(CHAR, TYPE, ITYPE, BOUNDS, 8) \
+ DEF_INT_SPEC_III(CHAR, TYPE, ITYPE, BOUNDS, 10) \
DEF_INT_SPEC_III(CHAR, TYPE, ITYPE, BOUNDS, 16)
-
-#define DEF_INT_SPEC_I(TYPE, ITYPE, BOUNDS) \
- DEF_INT_SPEC_II(char, TYPE, ITYPE, BOUNDS) \
- DEF_INT_SPEC_II(wchar16, TYPE, ITYPE, BOUNDS)
-#define DEF_INT_SPEC(TYPE, ID) \
- DEF_INT_SPEC_I(signed TYPE, i64, ID##SBounds) \
+#define DEF_INT_SPEC_I(TYPE, ITYPE, BOUNDS) \
+ DEF_INT_SPEC_II(char, TYPE, ITYPE, BOUNDS) \
+ DEF_INT_SPEC_II(wchar16, TYPE, ITYPE, BOUNDS)
+
+#define DEF_INT_SPEC(TYPE, ID) \
+ DEF_INT_SPEC_I(signed TYPE, i64, ID##SBounds) \
DEF_INT_SPEC_I(unsigned TYPE, ui64, ID##UBounds)
#define DEF_INT_SPEC_FIXED_WIDTH(TYPE, ID) \
@@ -625,21 +625,21 @@ DEF_INT_SPEC(long, l)
DEF_INT_SPEC(long long, ll)
#undef DEF_INT_SPEC_FIXED_WIDTH
-#undef DEF_INT_SPEC
+#undef DEF_INT_SPEC
#undef DEF_INT_SPEC_I
#undef DEF_INT_SPEC_II
#undef DEF_INT_SPEC_III
-
-#define DEF_FLT_SPEC(type) \
- template <> \
- type FromStringImpl<type>(const char* data, size_t len) { \
- return ParseFlt<type>(data, len); \
- }
-
-DEF_FLT_SPEC(long double)
-
-#undef DEF_FLT_SPEC
-
+
+#define DEF_FLT_SPEC(type) \
+ template <> \
+ type FromStringImpl<type>(const char* data, size_t len) { \
+ return ParseFlt<type>(data, len); \
+ }
+
+DEF_FLT_SPEC(long double)
+
+#undef DEF_FLT_SPEC
+
// Using StrToD for float and double because it is faster than sscanf.
// Exception-free, specialized for float types
template <>
@@ -693,152 +693,152 @@ float FromStringImpl<float>(const char* data, size_t len) {
return static_cast<float>(FromStringImpl<double>(data, len));
}
-double StrToD(const char* b, const char* e, char** se) {
- struct TCvt: public StringToDoubleConverter {
- inline TCvt()
- : StringToDoubleConverter(ALLOW_TRAILING_JUNK | ALLOW_HEX | ALLOW_LEADING_SPACES, 0.0, NAN, nullptr, nullptr)
- {
- }
- };
-
- int out = 0;
-
- const auto res = SingletonWithPriority<TCvt, 0>()->StringToDouble(b, e - b, &out);
-
- if (se) {
- *se = (char*)(b + out);
- }
-
- return res;
-}
-
-double StrToD(const char* b, char** se) {
- return StrToD(b, b + strlen(b), se);
-}
-
-namespace {
- static inline DoubleToStringConverter& ToStringConverterNoPad() noexcept {
- struct TCvt: public DoubleToStringConverter {
- inline TCvt() noexcept
- : DoubleToStringConverter(EMIT_POSITIVE_EXPONENT_SIGN, "inf", "nan", 'e', -10, 21, 4, 0)
- {
- }
- };
-
- return *SingletonWithPriority<TCvt, 0>();
- }
-
- struct TBuilder {
- alignas(StringBuilder) char Store[sizeof(StringBuilder)];
- StringBuilder* SB;
-
- inline TBuilder(char* buf, size_t len) noexcept
- : SB(new (Store) StringBuilder(buf, len))
- {
- }
- };
-
- static inline size_t FixZeros(char* buf, size_t len) noexcept {
- auto end = buf + len;
- auto point = (char*)memchr(buf, '.', len);
-
- if (!point) {
- return len;
- }
-
- auto exp = (char*)memchr(point, 'e', end - point);
-
- if (!exp) {
- exp = end;
- }
-
- auto c = exp;
-
- c -= 1;
-
- while (point < c && *c == '0') {
- --c;
- }
-
- if (*c == '.') {
- --c;
- }
-
- memmove(c + 1, exp, end - exp);
-
- return c - buf + 1 + end - exp;
- }
-
- static inline size_t FixEnd(char* buf, size_t len) noexcept {
- if (len > 2) {
- auto sign = buf[len - 2];
-
- if (sign == '-' || sign == '+') {
- buf[len] = buf[len - 1];
- buf[len - 1] = '0';
- ++len;
- }
- }
-
- buf[len] = 0;
-
- return len;
- }
-
- static inline size_t DoDtoa(double d, char* buf, size_t len, int prec) noexcept {
- TBuilder sb(buf, len);
-
+double StrToD(const char* b, const char* e, char** se) {
+ struct TCvt: public StringToDoubleConverter {
+ inline TCvt()
+ : StringToDoubleConverter(ALLOW_TRAILING_JUNK | ALLOW_HEX | ALLOW_LEADING_SPACES, 0.0, NAN, nullptr, nullptr)
+ {
+ }
+ };
+
+ int out = 0;
+
+ const auto res = SingletonWithPriority<TCvt, 0>()->StringToDouble(b, e - b, &out);
+
+ if (se) {
+ *se = (char*)(b + out);
+ }
+
+ return res;
+}
+
+double StrToD(const char* b, char** se) {
+ return StrToD(b, b + strlen(b), se);
+}
+
+namespace {
+ static inline DoubleToStringConverter& ToStringConverterNoPad() noexcept {
+ struct TCvt: public DoubleToStringConverter {
+ inline TCvt() noexcept
+ : DoubleToStringConverter(EMIT_POSITIVE_EXPONENT_SIGN, "inf", "nan", 'e', -10, 21, 4, 0)
+ {
+ }
+ };
+
+ return *SingletonWithPriority<TCvt, 0>();
+ }
+
+ struct TBuilder {
+ alignas(StringBuilder) char Store[sizeof(StringBuilder)];
+ StringBuilder* SB;
+
+ inline TBuilder(char* buf, size_t len) noexcept
+ : SB(new (Store) StringBuilder(buf, len))
+ {
+ }
+ };
+
+ static inline size_t FixZeros(char* buf, size_t len) noexcept {
+ auto end = buf + len;
+ auto point = (char*)memchr(buf, '.', len);
+
+ if (!point) {
+ return len;
+ }
+
+ auto exp = (char*)memchr(point, 'e', end - point);
+
+ if (!exp) {
+ exp = end;
+ }
+
+ auto c = exp;
+
+ c -= 1;
+
+ while (point < c && *c == '0') {
+ --c;
+ }
+
+ if (*c == '.') {
+ --c;
+ }
+
+ memmove(c + 1, exp, end - exp);
+
+ return c - buf + 1 + end - exp;
+ }
+
+ static inline size_t FixEnd(char* buf, size_t len) noexcept {
+ if (len > 2) {
+ auto sign = buf[len - 2];
+
+ if (sign == '-' || sign == '+') {
+ buf[len] = buf[len - 1];
+ buf[len - 1] = '0';
+ ++len;
+ }
+ }
+
+ buf[len] = 0;
+
+ return len;
+ }
+
+ static inline size_t DoDtoa(double d, char* buf, size_t len, int prec) noexcept {
+ TBuilder sb(buf, len);
+
Y_VERIFY(ToStringConverterNoPad().ToPrecision(d, prec, sb.SB), "conversion failed");
-
- return FixEnd(buf, FixZeros(buf, sb.SB->position()));
- }
-}
-
-template <>
-size_t ToStringImpl<double>(double d, char* buf, size_t len) {
- return DoDtoa(d, buf, len, 10);
-}
-
-template <>
-size_t ToStringImpl<float>(float f, char* buf, size_t len) {
- return DoDtoa(f, buf, len, 6);
-}
-
-size_t FloatToString(float t, char* buf, size_t len, EFloatToStringMode mode, int ndigits) {
- if (mode == PREC_AUTO) {
- TBuilder sb(buf, len);
-
+
+ return FixEnd(buf, FixZeros(buf, sb.SB->position()));
+ }
+}
+
+template <>
+size_t ToStringImpl<double>(double d, char* buf, size_t len) {
+ return DoDtoa(d, buf, len, 10);
+}
+
+template <>
+size_t ToStringImpl<float>(float f, char* buf, size_t len) {
+ return DoDtoa(f, buf, len, 6);
+}
+
+size_t FloatToString(float t, char* buf, size_t len, EFloatToStringMode mode, int ndigits) {
+ if (mode == PREC_AUTO) {
+ TBuilder sb(buf, len);
+
Y_VERIFY(ToStringConverterNoPad().ToShortestSingle(t, sb.SB), "conversion failed");
-
- return FixEnd(buf, sb.SB->position());
- }
-
- return FloatToString((double)t, buf, len, mode, ndigits);
-}
-
-size_t FloatToString(double t, char* buf, size_t len, EFloatToStringMode mode, int ndigits) {
- if (mode == PREC_NDIGITS) {
- auto minDigits = DoubleToStringConverter::kMinPrecisionDigits;
- auto maxDigits = DoubleToStringConverter::kMaxPrecisionDigits;
-
- return DoDtoa(t, buf, len, ClampVal(ndigits, minDigits, maxDigits));
- }
-
- TBuilder sb(buf, len);
-
- if (mode == PREC_AUTO) {
+
+ return FixEnd(buf, sb.SB->position());
+ }
+
+ return FloatToString((double)t, buf, len, mode, ndigits);
+}
+
+size_t FloatToString(double t, char* buf, size_t len, EFloatToStringMode mode, int ndigits) {
+ if (mode == PREC_NDIGITS) {
+ auto minDigits = DoubleToStringConverter::kMinPrecisionDigits;
+ auto maxDigits = DoubleToStringConverter::kMaxPrecisionDigits;
+
+ return DoDtoa(t, buf, len, ClampVal(ndigits, minDigits, maxDigits));
+ }
+
+ TBuilder sb(buf, len);
+
+ if (mode == PREC_AUTO) {
Y_VERIFY(ToStringConverterNoPad().ToShortest(t, sb.SB), "conversion failed");
-
- return FixEnd(buf, sb.SB->position());
- }
-
- if (!ToStringConverterNoPad().ToFixed(t, ndigits, sb.SB)) {
- return FloatToString(t, buf, len, PREC_AUTO);
- }
-
- if (mode == PREC_POINT_DIGITS_STRIP_ZEROES) {
- return FixZeros(buf, sb.SB->position());
- }
-
- return sb.SB->position();
-}
+
+ return FixEnd(buf, sb.SB->position());
+ }
+
+ if (!ToStringConverterNoPad().ToFixed(t, ndigits, sb.SB)) {
+ return FloatToString(t, buf, len, PREC_AUTO);
+ }
+
+ if (mode == PREC_POINT_DIGITS_STRIP_ZEROES) {
+ return FixZeros(buf, sb.SB->position());
+ }
+
+ return sb.SB->position();
+}