xref: /aosp_15_r20/external/lzma/CPP/Common/StringToInt.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Common/StringToInt.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include <limits.h>
6*f6dc9357SAndroid Build Coastguard Worker #if defined(_MSC_VER) && (_MSC_VER >= 1600)
7*f6dc9357SAndroid Build Coastguard Worker #include <stdint.h> // for WCHAR_MAX in vs2022
8*f6dc9357SAndroid Build Coastguard Worker #endif
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker #include "StringToInt.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_UInt32_max = 0xFFFFFFFF;
13*f6dc9357SAndroid Build Coastguard Worker static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF);
14*f6dc9357SAndroid Build Coastguard Worker // static const UInt64 k_UInt64_max = (UInt64)(Int64)-1;
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker #define DIGIT_TO_VALUE(charTypeUnsigned, digit)   ((unsigned)(charTypeUnsigned)digit - '0')
17*f6dc9357SAndroid Build Coastguard Worker // #define DIGIT_TO_VALUE(charTypeUnsigned, digit)   ((unsigned)digit - '0')
18*f6dc9357SAndroid Build Coastguard Worker // #define DIGIT_TO_VALUE(charTypeUnsigned, digit)   ((unsigned)(digit - '0'))
19*f6dc9357SAndroid Build Coastguard Worker 
20*f6dc9357SAndroid Build Coastguard Worker #define CONVERT_STRING_TO_UINT_FUNC(uintType, charType, charTypeUnsigned) \
21*f6dc9357SAndroid Build Coastguard Worker uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \
22*f6dc9357SAndroid Build Coastguard Worker     if (end) *end = s; \
23*f6dc9357SAndroid Build Coastguard Worker     uintType res = 0; \
24*f6dc9357SAndroid Build Coastguard Worker     for (;; s++) { \
25*f6dc9357SAndroid Build Coastguard Worker       const unsigned v = DIGIT_TO_VALUE(charTypeUnsigned, *s); \
26*f6dc9357SAndroid Build Coastguard Worker       if (v > 9) { if (end) *end = s; return res; } \
27*f6dc9357SAndroid Build Coastguard Worker       if (res > (k_ ## uintType ## _max) / 10) return 0; \
28*f6dc9357SAndroid Build Coastguard Worker       res *= 10; \
29*f6dc9357SAndroid Build Coastguard Worker       if (res > (k_ ## uintType ## _max) - v) return 0; \
30*f6dc9357SAndroid Build Coastguard Worker       res += v; }}
31*f6dc9357SAndroid Build Coastguard Worker 
32*f6dc9357SAndroid Build Coastguard Worker // arm-linux-gnueabi GCC compilers give (WCHAR_MAX > UINT_MAX) by some unknown reason
33*f6dc9357SAndroid Build Coastguard Worker // so we don't use this branch
34*f6dc9357SAndroid Build Coastguard Worker #if 0 && WCHAR_MAX > UINT_MAX
35*f6dc9357SAndroid Build Coastguard Worker /*
36*f6dc9357SAndroid Build Coastguard Worker    if (sizeof(wchar_t) > sizeof(unsigned)
37*f6dc9357SAndroid Build Coastguard Worker       we must use CONVERT_STRING_TO_UINT_FUNC_SLOW
38*f6dc9357SAndroid Build Coastguard Worker    But we just stop compiling instead.
39*f6dc9357SAndroid Build Coastguard Worker    We need some real cases to test this code.
40*f6dc9357SAndroid Build Coastguard Worker */
41*f6dc9357SAndroid Build Coastguard Worker #error Stop_Compiling_WCHAR_MAX_IS_LARGER_THAN_UINT_MAX
42*f6dc9357SAndroid Build Coastguard Worker #define CONVERT_STRING_TO_UINT_FUNC_SLOW(uintType, charType, charTypeUnsigned) \
43*f6dc9357SAndroid Build Coastguard Worker uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \
44*f6dc9357SAndroid Build Coastguard Worker     if (end) *end = s; \
45*f6dc9357SAndroid Build Coastguard Worker     uintType res = 0; \
46*f6dc9357SAndroid Build Coastguard Worker     for (;; s++) { \
47*f6dc9357SAndroid Build Coastguard Worker       const charTypeUnsigned c = (charTypeUnsigned)*s; \
48*f6dc9357SAndroid Build Coastguard Worker       if (c < '0' || c > '9') { if (end) *end = s; return res; } \
49*f6dc9357SAndroid Build Coastguard Worker       if (res > (k_ ## uintType ## _max) / 10) return 0; \
50*f6dc9357SAndroid Build Coastguard Worker       res *= 10; \
51*f6dc9357SAndroid Build Coastguard Worker       const unsigned v = (unsigned)(c - '0'); \
52*f6dc9357SAndroid Build Coastguard Worker       if (res > (k_ ## uintType ## _max) - v) return 0; \
53*f6dc9357SAndroid Build Coastguard Worker       res += v; }}
54*f6dc9357SAndroid Build Coastguard Worker #endif
55*f6dc9357SAndroid Build Coastguard Worker 
56*f6dc9357SAndroid Build Coastguard Worker 
CONVERT_STRING_TO_UINT_FUNC(UInt32,char,Byte)57*f6dc9357SAndroid Build Coastguard Worker CONVERT_STRING_TO_UINT_FUNC(UInt32, char, Byte)
58*f6dc9357SAndroid Build Coastguard Worker CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t)
59*f6dc9357SAndroid Build Coastguard Worker CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte)
60*f6dc9357SAndroid Build Coastguard Worker CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t)
61*f6dc9357SAndroid Build Coastguard Worker 
62*f6dc9357SAndroid Build Coastguard Worker Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw()
63*f6dc9357SAndroid Build Coastguard Worker {
64*f6dc9357SAndroid Build Coastguard Worker   if (end)
65*f6dc9357SAndroid Build Coastguard Worker     *end = s;
66*f6dc9357SAndroid Build Coastguard Worker   const wchar_t *s2 = s;
67*f6dc9357SAndroid Build Coastguard Worker   if (*s == '-')
68*f6dc9357SAndroid Build Coastguard Worker     s2++;
69*f6dc9357SAndroid Build Coastguard Worker   const wchar_t *end2;
70*f6dc9357SAndroid Build Coastguard Worker   UInt32 res = ConvertStringToUInt32(s2, &end2);
71*f6dc9357SAndroid Build Coastguard Worker   if (s2 == end2)
72*f6dc9357SAndroid Build Coastguard Worker     return 0;
73*f6dc9357SAndroid Build Coastguard Worker   if (s != s2)
74*f6dc9357SAndroid Build Coastguard Worker   {
75*f6dc9357SAndroid Build Coastguard Worker     if (res > (UInt32)1 << (32 - 1))
76*f6dc9357SAndroid Build Coastguard Worker       return 0;
77*f6dc9357SAndroid Build Coastguard Worker     res = 0 - res;
78*f6dc9357SAndroid Build Coastguard Worker   }
79*f6dc9357SAndroid Build Coastguard Worker   else
80*f6dc9357SAndroid Build Coastguard Worker   {
81*f6dc9357SAndroid Build Coastguard Worker     if (res & (UInt32)1 << (32 - 1))
82*f6dc9357SAndroid Build Coastguard Worker       return 0;
83*f6dc9357SAndroid Build Coastguard Worker   }
84*f6dc9357SAndroid Build Coastguard Worker   if (end)
85*f6dc9357SAndroid Build Coastguard Worker     *end = end2;
86*f6dc9357SAndroid Build Coastguard Worker   return (Int32)res;
87*f6dc9357SAndroid Build Coastguard Worker }
88*f6dc9357SAndroid Build Coastguard Worker 
89*f6dc9357SAndroid Build Coastguard Worker 
90*f6dc9357SAndroid Build Coastguard Worker #define CONVERT_OCT_STRING_TO_UINT_FUNC(uintType) \
91*f6dc9357SAndroid Build Coastguard Worker uintType ConvertOctStringTo ## uintType(const char *s, const char **end) throw() \
92*f6dc9357SAndroid Build Coastguard Worker { \
93*f6dc9357SAndroid Build Coastguard Worker   if (end) *end = s; \
94*f6dc9357SAndroid Build Coastguard Worker   uintType res = 0; \
95*f6dc9357SAndroid Build Coastguard Worker   for (;; s++) { \
96*f6dc9357SAndroid Build Coastguard Worker     const unsigned c = (unsigned)(Byte)*s - '0'; \
97*f6dc9357SAndroid Build Coastguard Worker     if (c > 7) { \
98*f6dc9357SAndroid Build Coastguard Worker       if (end) \
99*f6dc9357SAndroid Build Coastguard Worker         *end = s; \
100*f6dc9357SAndroid Build Coastguard Worker       return res; \
101*f6dc9357SAndroid Build Coastguard Worker     } \
102*f6dc9357SAndroid Build Coastguard Worker     if (res & (uintType)7 << (sizeof(uintType) * 8 - 3)) \
103*f6dc9357SAndroid Build Coastguard Worker       return 0; \
104*f6dc9357SAndroid Build Coastguard Worker     res <<= 3; \
105*f6dc9357SAndroid Build Coastguard Worker     res |= c; \
106*f6dc9357SAndroid Build Coastguard Worker   } \
107*f6dc9357SAndroid Build Coastguard Worker }
108*f6dc9357SAndroid Build Coastguard Worker 
109*f6dc9357SAndroid Build Coastguard Worker CONVERT_OCT_STRING_TO_UINT_FUNC(UInt32)
CONVERT_OCT_STRING_TO_UINT_FUNC(UInt64)110*f6dc9357SAndroid Build Coastguard Worker CONVERT_OCT_STRING_TO_UINT_FUNC(UInt64)
111*f6dc9357SAndroid Build Coastguard Worker 
112*f6dc9357SAndroid Build Coastguard Worker 
113*f6dc9357SAndroid Build Coastguard Worker #define CONVERT_HEX_STRING_TO_UINT_FUNC(uintType) \
114*f6dc9357SAndroid Build Coastguard Worker uintType ConvertHexStringTo ## uintType(const char *s, const char **end) throw() \
115*f6dc9357SAndroid Build Coastguard Worker { \
116*f6dc9357SAndroid Build Coastguard Worker   if (end) *end = s; \
117*f6dc9357SAndroid Build Coastguard Worker   uintType res = 0; \
118*f6dc9357SAndroid Build Coastguard Worker   for (;; s++) { \
119*f6dc9357SAndroid Build Coastguard Worker     unsigned c = (unsigned)(Byte)*s; \
120*f6dc9357SAndroid Build Coastguard Worker     Z7_PARSE_HEX_DIGIT(c, { if (end) *end = s;  return res; }) \
121*f6dc9357SAndroid Build Coastguard Worker     if (res & (uintType)0xF << (sizeof(uintType) * 8 - 4)) \
122*f6dc9357SAndroid Build Coastguard Worker       return 0; \
123*f6dc9357SAndroid Build Coastguard Worker     res <<= 4; \
124*f6dc9357SAndroid Build Coastguard Worker     res |= c; \
125*f6dc9357SAndroid Build Coastguard Worker   } \
126*f6dc9357SAndroid Build Coastguard Worker }
127*f6dc9357SAndroid Build Coastguard Worker 
128*f6dc9357SAndroid Build Coastguard Worker CONVERT_HEX_STRING_TO_UINT_FUNC(UInt32)
129*f6dc9357SAndroid Build Coastguard Worker CONVERT_HEX_STRING_TO_UINT_FUNC(UInt64)
130*f6dc9357SAndroid Build Coastguard Worker 
131*f6dc9357SAndroid Build Coastguard Worker const char *FindNonHexChar(const char *s) throw()
132*f6dc9357SAndroid Build Coastguard Worker {
133*f6dc9357SAndroid Build Coastguard Worker   for (;;)
134*f6dc9357SAndroid Build Coastguard Worker   {
135*f6dc9357SAndroid Build Coastguard Worker     unsigned c = (Byte)*s++; // pointer can go 1 byte after end
136*f6dc9357SAndroid Build Coastguard Worker     c -= '0';
137*f6dc9357SAndroid Build Coastguard Worker     if (c <= 9)
138*f6dc9357SAndroid Build Coastguard Worker       continue;
139*f6dc9357SAndroid Build Coastguard Worker     c -= 'A' - '0';
140*f6dc9357SAndroid Build Coastguard Worker     c &= ~0x20u;
141*f6dc9357SAndroid Build Coastguard Worker     if (c > 5)
142*f6dc9357SAndroid Build Coastguard Worker       return s - 1;
143*f6dc9357SAndroid Build Coastguard Worker   }
144*f6dc9357SAndroid Build Coastguard Worker }
145*f6dc9357SAndroid Build Coastguard Worker 
ParseHexString(const char * s,Byte * dest)146*f6dc9357SAndroid Build Coastguard Worker Byte *ParseHexString(const char *s, Byte *dest) throw()
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker   for (;;)
149*f6dc9357SAndroid Build Coastguard Worker   {
150*f6dc9357SAndroid Build Coastguard Worker     unsigned v0 = (Byte)s[0];         Z7_PARSE_HEX_DIGIT(v0, return dest;)
151*f6dc9357SAndroid Build Coastguard Worker     unsigned v1 = (Byte)s[1]; s += 2; Z7_PARSE_HEX_DIGIT(v1, return dest;)
152*f6dc9357SAndroid Build Coastguard Worker     *dest++ = (Byte)(v1 | (v0 << 4));
153*f6dc9357SAndroid Build Coastguard Worker   }
154*f6dc9357SAndroid Build Coastguard Worker }
155