@@ -57,138 +57,106 @@ namespace Poco {
5757
5858
5959inline char decimalSeparator ()
60- // / Returns decimal separator from global locale or
61- // / default '.' for platforms where locale is unavailable.
60+ // / Returns decimal separator from global locale or
61+ // / default '.' for platforms where locale is unavailable.
6262{
6363#if !defined(POCO_NO_LOCALE)
64- return std::use_facet<std::numpunct<char > >(std::locale ()).decimal_point ();
64+ return std::use_facet<std::numpunct<char > >(std::locale ()).decimal_point ();
6565#else
66- return ' .' ;
66+ return ' .' ;
6767#endif
6868}
6969
7070
7171inline char thousandSeparator ()
72- // / Returns thousand separator from global locale or
73- // / default ',' for platforms where locale is unavailable.
72+ // / Returns thousand separator from global locale or
73+ // / default ',' for platforms where locale is unavailable.
7474{
7575#if !defined(POCO_NO_LOCALE)
76- return std::use_facet<std::numpunct<char > >(std::locale ()).thousands_sep ();
76+ return std::use_facet<std::numpunct<char > >(std::locale ()).thousands_sep ();
7777#else
78- return ' ,' ;
78+ return ' ,' ;
7979#endif
8080}
8181
8282
8383template <typename I>
84- bool strToInt (const char * pStr, I& result, short base = -1 )
85- // / Converts zero-terminated array to integer number;
86- // / If base is equal to -1, this functin will try to determine
87- // / the numeric base (using '0' prefix for octal, '0x' for
88- // / hexadecimal and no prefix for decimal).
89- // / Thousand separators are recognized for base10 and the locale
90- // / and silently skipped but not verified for correct positioning.
91- // / Returns true if succesful. If parsing was unsuccesful,
92- // / the return value is false with result value undetermined.
84+ bool strToInt (const char * pStr, I& result, short base)
85+ // / Converts zero-terminated character array to integer number;
86+ // / Thousand separators are recognized for base10 and current locale;
87+ // / it is silently skipped but not verified for correct positioning.
88+ // / Function returns true if succesful. If parsing was unsuccesful,
89+ // / the return value is false with the result value undetermined.
9390{
94- if (!std::numeric_limits<I>::is_integer) return false ;
95-
96- if (!pStr || (pStr && *pStr == ' \0 ' )) return false ;
97- while ((*pStr != ' \0 ' ) && (*pStr == ' ' )) ++pStr;
91+ if (!pStr) return false ;
92+ while (*pStr == ' ' ) ++pStr;
9893 if (*pStr == ' \0 ' ) return false ;
99-
100- char sign = 1 ;
101-
102- if (*pStr == ' -' )
94+ I sign = 1 ;
95+ if ((base == 10 ) && (*pStr == ' -' ))
10396 {
104- ++pStr;
10597 sign = -1 ;
106- }
107- else if (*pStr == ' +' ) ++pStr;
108- if (*pStr == ' \0 ' ) return false ;
109-
110- result = 0 ;
111-
112- if (*pStr == ' 0' )
113- {
114- while ((*pStr != ' \0 ' ) && (*pStr == ' 0' )) ++pStr;
115- if (*pStr == ' \0 ' )
116- {
117- result = 0 ;
118- return true ;
119- }
120-
121- if ((*pStr == ' x' ) || (*pStr == ' X' ))
122- {
123- base = 0x10 ;
124- ++pStr;
125- if (*pStr == ' \0 ' ) return false ;
126- }
127- else if (base == -1 ) base = 010 ;
128- }
129- else if (base == -1 ) base = 10 ;
130-
131- while ((*pStr == ' 0' ))
132- {
133- if (*pStr != ' \0 ' )
134- {
135- result = 0 ;
136- return true ;
137- }
13898 ++pStr;
13999 }
140- if (*pStr == ' \0 ' ) return false ;
100+ else if (*pStr == ' + ' ) ++pStr ;
141101
102+ // parser states:
103+ const char STATE_SIGNIFICANT_DIGITS = 1 ;
104+ char state = 0 ;
142105 const char thSep = thousandSeparator ();
143- bool allowDigits = true ;
106+
107+ result = 0 ;
108+ I limitCheck = std::numeric_limits<I>::max () / base;
144109 for (; *pStr != ' \0 ' ; ++pStr)
145110 {
146111 switch (*pStr)
147112 {
148- case ' 0' : case ' 1' : case ' 2' : case ' 3' : case ' 4' :
113+ case ' x' : case ' X' :
114+ if (base != 0x10 ) return false ;
115+
116+ case ' 0' :
117+ if (state < STATE_SIGNIFICANT_DIGITS) break ;
118+
119+ case ' 1' : case ' 2' : case ' 3' : case ' 4' :
149120 case ' 5' : case ' 6' : case ' 7' :
150- if (allowDigits)
151- {
152- if (result > (std::numeric_limits<I>::max () / base)) return false ;
153- result = result * base + (*pStr - ' 0' );
154- }
155- else return false ;
121+ if (state < STATE_SIGNIFICANT_DIGITS) state = STATE_SIGNIFICANT_DIGITS;
122+ if (result > limitCheck) return false ;
123+ result = result * base + (*pStr - ' 0' );
124+
156125 break ;
157126
158127 case ' 8' : case ' 9' :
159- if (allowDigits && (base == 10 || base == 16 ))
128+ if ((base == 10 ) || ( base == 0x10 ))
160129 {
161- if (result > (std::numeric_limits<I>::max () / base)) return false ;
130+ if (state < STATE_SIGNIFICANT_DIGITS) state = STATE_SIGNIFICANT_DIGITS;
131+ if (result > limitCheck) return false ;
162132 result = result * base + (*pStr - ' 0' );
163133 }
164134 else return false ;
135+
165136 break ;
166137
167138 case ' a' : case ' b' : case ' c' : case ' d' : case ' e' : case ' f' :
168- if (allowDigits && base == 16 )
169- {
170- if (result > (std::numeric_limits<I>::max () / base)) return false ;
171- result = result * base + (10 + *pStr - ' a' );
172- }
173- else return false ;
139+ if (base != 0x10 ) return false ;
140+ if (state < STATE_SIGNIFICANT_DIGITS) state = STATE_SIGNIFICANT_DIGITS;
141+ if (result > limitCheck) return false ;
142+ result = result * base + (10 + *pStr - ' a' );
143+
174144 break ;
175145
176146 case ' A' : case ' B' : case ' C' : case ' D' : case ' E' : case ' F' :
177- if (allowDigits && base == 16 )
178- {
179- if (result > (std::numeric_limits<I>::max () / base)) return false ;
180- result = result * base + (10 + *pStr - ' A' );
181- }
182- else
183- return false ;
147+ if (base != 0x10 ) return false ;
148+
149+ if (state < STATE_SIGNIFICANT_DIGITS) state = STATE_SIGNIFICANT_DIGITS;
150+ if (result > limitCheck) return false ;
151+ result = result * base + (10 + *pStr - ' A' );
152+
184153 break ;
185154
186155 case ' U' :
187156 case ' u' :
188157 case ' L' :
189158 case ' l' :
190- allowDigits = false ;
191- break ;
159+ goto done;
192160
193161 case ' .' :
194162 if ((base == 10 ) && (thSep == ' .' )) break ;
@@ -199,23 +167,23 @@ bool strToInt(const char* pStr, I& result, short base = -1)
199167 else return false ;
200168
201169 case ' ' :
202- if (base == 10 ) break ;
203- else return false ;
170+ if (( base == 10 ) && (thSep == ' ' ) ) break ;
171+ goto done ;
204172
205173 default :
206174 return false ;
207175 }
208176 }
209177
210- if ((base == 10 ) && (std::numeric_limits<I>::is_signed))
211- result *= sign;
178+ done:
179+ if ((sign < 0 ) && (base == 10 )) result *= sign;
212180
213181 return true ;
214182}
215183
216184
217185template <typename I>
218- bool strToInt (const std::string& str, I& result, short base = - 1 )
186+ bool strToInt (const std::string& str, I& result, short base)
219187 // / Converts string to integer number;
220188 // / This is a wrapper function, for details see see the
221189 // / bool strToInt(const char*, I&, short&) implementation.
0 commit comments