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