From fc662341e6f85da78ada0e443f6116b978f79f22 Mon Sep 17 00:00:00 2001 From: Igor Pavlov <87184205+ip7z@users.noreply.github.com> Date: Tue, 14 May 2024 00:00:00 +0000 Subject: 24.05 --- CPP/Common/StringToInt.cpp | 215 +++++++++++++++++++++------------------------ 1 file changed, 99 insertions(+), 116 deletions(-) (limited to 'CPP/Common/StringToInt.cpp') diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp index bc4926e..ba8a81b 100644 --- a/CPP/Common/StringToInt.cpp +++ b/CPP/Common/StringToInt.cpp @@ -2,57 +2,63 @@ #include "StdAfx.h" +#include +#if defined(_MSC_VER) && (_MSC_VER >= 1600) +#include // for WCHAR_MAX in vs2022 +#endif + #include "StringToInt.h" static const UInt32 k_UInt32_max = 0xFFFFFFFF; static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF); // static const UInt64 k_UInt64_max = (UInt64)(Int64)-1; +#define DIGIT_TO_VALUE(charTypeUnsigned, digit) ((unsigned)(charTypeUnsigned)digit - '0') +// #define DIGIT_TO_VALUE(charTypeUnsigned, digit) ((unsigned)digit - '0') +// #define DIGIT_TO_VALUE(charTypeUnsigned, digit) ((unsigned)(digit - '0')) + #define CONVERT_STRING_TO_UINT_FUNC(uintType, charType, charTypeUnsigned) \ - uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \ +uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \ + if (end) *end = s; \ + uintType res = 0; \ + for (;; s++) { \ + const unsigned v = DIGIT_TO_VALUE(charTypeUnsigned, *s); \ + if (v > 9) { if (end) *end = s; return res; } \ + if (res > (k_ ## uintType ## _max) / 10) return 0; \ + res *= 10; \ + if (res > (k_ ## uintType ## _max) - v) return 0; \ + res += v; }} + +// arm-linux-gnueabi GCC compilers give (WCHAR_MAX > UINT_MAX) by some unknown reason +// so we don't use this branch +#if 0 && WCHAR_MAX > UINT_MAX +/* + if (sizeof(wchar_t) > sizeof(unsigned) + we must use CONVERT_STRING_TO_UINT_FUNC_SLOW + But we just stop compiling instead. + We need some real cases to test this code. +*/ +#error Stop_Compiling_WCHAR_MAX_IS_LARGER_THAN_UINT_MAX +#define CONVERT_STRING_TO_UINT_FUNC_SLOW(uintType, charType, charTypeUnsigned) \ +uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \ if (end) *end = s; \ uintType res = 0; \ for (;; s++) { \ - charTypeUnsigned c = (charTypeUnsigned)*s; \ + const charTypeUnsigned c = (charTypeUnsigned)*s; \ if (c < '0' || c > '9') { if (end) *end = s; return res; } \ if (res > (k_ ## uintType ## _max) / 10) return 0; \ res *= 10; \ - unsigned v = (unsigned)(c - '0'); \ + const unsigned v = (unsigned)(c - '0'); \ if (res > (k_ ## uintType ## _max) - v) return 0; \ res += v; }} +#endif + CONVERT_STRING_TO_UINT_FUNC(UInt32, char, Byte) CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t) CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte) CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t) -/* -Int32 ConvertStringToInt32(const char *s, const char **end) throw() -{ - if (end) - *end = s; - const char *s2 = s; - if (*s == '-') - s2++; - if (*s2 == 0) - return 0; - const char *end2; - UInt32 res = ConvertStringToUInt32(s2, &end2); - if (*s == '-') - { - if (res > ((UInt32)1 << (32 - 1))) - return 0; - } - else if ((res & ((UInt32)1 << (32 - 1))) != 0) - return 0; - if (end) - *end = end2; - if (*s == '-') - return -(Int32)res; - return (Int32)res; -} -*/ - Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw() { if (end) @@ -60,112 +66,89 @@ Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw() const wchar_t *s2 = s; if (*s == '-') s2++; - if (*s2 == 0) - return 0; const wchar_t *end2; UInt32 res = ConvertStringToUInt32(s2, &end2); - if (*s == '-') + if (s2 == end2) + return 0; + if (s != s2) { - if (res > ((UInt32)1 << (32 - 1))) + if (res > (UInt32)1 << (32 - 1)) + return 0; + res = 0 - res; + } + else + { + if (res & (UInt32)1 << (32 - 1)) return 0; } - else if ((res & ((UInt32)1 << (32 - 1))) != 0) - return 0; if (end) *end = end2; - if (*s == '-') - return -(Int32)res; return (Int32)res; } -UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw() -{ - if (end) - *end = s; - UInt32 res = 0; - for (;; s++) - { - unsigned c = (unsigned char)*s; - if (c < '0' || c > '7') - { - if (end) - *end = s; - return res; - } - if ((res & (UInt32)7 << (32 - 3)) != 0) - return 0; - res <<= 3; - res |= (unsigned)(c - '0'); - } + +#define CONVERT_OCT_STRING_TO_UINT_FUNC(uintType) \ +uintType ConvertOctStringTo ## uintType(const char *s, const char **end) throw() \ +{ \ + if (end) *end = s; \ + uintType res = 0; \ + for (;; s++) { \ + const unsigned c = (unsigned)(Byte)*s - '0'; \ + if (c > 7) { \ + if (end) \ + *end = s; \ + return res; \ + } \ + if (res & (uintType)7 << (sizeof(uintType) * 8 - 3)) \ + return 0; \ + res <<= 3; \ + res |= c; \ + } \ } -UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw() -{ - if (end) - *end = s; - UInt64 res = 0; - for (;; s++) - { - unsigned c = (unsigned char)*s; - if (c < '0' || c > '7') - { - if (end) - *end = s; - return res; - } - if ((res & (UInt64)7 << (64 - 3)) != 0) - return 0; - res <<= 3; - res |= (unsigned)(c - '0'); - } +CONVERT_OCT_STRING_TO_UINT_FUNC(UInt32) +CONVERT_OCT_STRING_TO_UINT_FUNC(UInt64) + + +#define CONVERT_HEX_STRING_TO_UINT_FUNC(uintType) \ +uintType ConvertHexStringTo ## uintType(const char *s, const char **end) throw() \ +{ \ + if (end) *end = s; \ + uintType res = 0; \ + for (;; s++) { \ + unsigned c = (unsigned)(Byte)*s; \ + Z7_PARSE_HEX_DIGIT(c, { if (end) *end = s; return res; }) \ + if (res & (uintType)0xF << (sizeof(uintType) * 8 - 4)) \ + return 0; \ + res <<= 4; \ + res |= c; \ + } \ } -UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw() +CONVERT_HEX_STRING_TO_UINT_FUNC(UInt32) +CONVERT_HEX_STRING_TO_UINT_FUNC(UInt64) + +const char *FindNonHexChar(const char *s) throw() { - if (end) - *end = s; - UInt32 res = 0; - for (;; s++) + for (;;) { - unsigned c = (Byte)*s; - unsigned v; - if (c >= '0' && c <= '9') v = (c - '0'); - else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); - else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); - else - { - if (end) - *end = s; - return res; - } - if ((res & (UInt32)0xF << (32 - 4)) != 0) - return 0; - res <<= 4; - res |= v; + unsigned c = (Byte)*s++; // pointer can go 1 byte after end + c -= '0'; + if (c <= 9) + continue; + c -= 'A' - '0'; + c &= ~0x20u; + if (c > 5) + return s - 1; } } -UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw() +Byte *ParseHexString(const char *s, Byte *dest) throw() { - if (end) - *end = s; - UInt64 res = 0; - for (;; s++) + for (;;) { - unsigned c = (Byte)*s; - unsigned v; - if (c >= '0' && c <= '9') v = (c - '0'); - else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); - else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); - else - { - if (end) - *end = s; - return res; - } - if ((res & (UInt64)0xF << (64 - 4)) != 0) - return 0; - res <<= 4; - res |= v; + unsigned v0 = (Byte)s[0]; Z7_PARSE_HEX_DIGIT(v0, return dest;) + unsigned v1 = (Byte)s[1]; s += 2; Z7_PARSE_HEX_DIGIT(v1, return dest;) + *dest++ = (Byte)(v1 | (v0 << 4)); } } -- cgit v1.2.3-55-g6feb