Merge lp:~paul-lucas/zorba/pjl-misc into lp:zorba
- pjl-misc
- Merge into trunk
Proposed by
Paul J. Lucas
Status: | Merged |
---|---|
Approved by: | Matthias Brantner |
Approved revision: | 11029 |
Merged at revision: | 11177 |
Proposed branch: | lp:~paul-lucas/zorba/pjl-misc |
Merge into: | lp:zorba |
Diff against target: |
412 lines (+190/-91) 2 files modified
src/util/string_util.cpp (+63/-56) src/util/string_util.h (+127/-35) |
To merge this branch: | bzr merge lp:~paul-lucas/zorba/pjl-misc |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Matthias Brantner | Approve | ||
Paul J. Lucas | Approve | ||
Review via email: mp+142815@code.launchpad.net |
Commit message
aton() enhancement.
Description of the change
aton() enhancement.
To post a comment you must log in.
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : | # |
Revision history for this message
Paul J. Lucas (paul-lucas) : | # |
review:
Approve
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue job pjl-misc-
All tests succeeded!
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : | # |
Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 1 Approve.
Revision history for this message
Matthias Brantner (matthias-brantner) : | # |
review:
Approve
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue starting for merge proposal.
Log at: http://
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue job pjl-misc-
All tests succeeded!
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/util/string_util.cpp' |
2 | --- src/util/string_util.cpp 2013-01-07 14:49:20 +0000 |
3 | +++ src/util/string_util.cpp 2013-01-10 23:41:23 +0000 |
4 | @@ -21,6 +21,7 @@ |
5 | #include "ascii_util.h" |
6 | #include "cxx_util.h" |
7 | #include "string_util.h" |
8 | +#include "zorbatypes/zstring.h" |
9 | |
10 | #ifdef WIN32 |
11 | namespace std { |
12 | @@ -55,67 +56,73 @@ |
13 | |
14 | /////////////////////////////////////////////////////////////////////////////// |
15 | |
16 | -#define ENABLE_CLIPPING 0 |
17 | - |
18 | -template<typename T> |
19 | -static void check_parse_number( char const *s, char *end, T *result ) { |
20 | +static void check_errno( char const *buf, char const *end ) { |
21 | if ( errno == ERANGE ) { |
22 | - if ( result ) { |
23 | -#if ENABLE_CLIPPING |
24 | - if ( *ascii::trim_start_whitespace( s ) == '-' ) |
25 | - *result = numeric_limits<T>::min(); |
26 | - else |
27 | - *result = numeric_limits<T>::max(); |
28 | -#endif /* ENABLE_CLIPPING */ |
29 | - } else |
30 | - throw std::range_error( |
31 | - BUILD_STRING( '"', s, "\": number too big/small" ) |
32 | - ); |
33 | + zstring const s( buf, end ); |
34 | + throw std::range_error( |
35 | + BUILD_STRING( '"', s, "\": number too big/small" ) |
36 | + ); |
37 | } |
38 | - if ( end == s ) |
39 | - throw std::invalid_argument( BUILD_STRING( '"', s, "\": no digits" ) ); |
40 | - for ( ; *end; ++end ) // remaining characters, if any, ... |
41 | - if ( !ascii::is_space( *end ) ) // ... may only be whitespace |
42 | - throw std::invalid_argument( |
43 | - BUILD_STRING( '"', *end, "\": invalid character" ) |
44 | - ); |
45 | -} |
46 | - |
47 | -double atod( char const *s ) { |
48 | - char *end; |
49 | - errno = 0; |
50 | - double result = std::strtod( s, &end ); |
51 | - check_parse_number( s, end, &result ); |
52 | - return result; |
53 | -} |
54 | - |
55 | -float atof( char const *s ) { |
56 | - char *end; |
57 | - errno = 0; |
58 | - float result = std::strtof( s, &end ); |
59 | - check_parse_number( s, end, &result ); |
60 | - return result; |
61 | -} |
62 | - |
63 | -long long atoll( char const *s ) { |
64 | - char *end; |
65 | - errno = 0; |
66 | - long long const result = std::strtoll( s, &end, 10 ); |
67 | - check_parse_number( s, end, static_cast<long long*>( nullptr ) ); |
68 | - return result; |
69 | -} |
70 | - |
71 | -unsigned long long atoull( char const *s ) { |
72 | +} |
73 | + |
74 | +static void check_parse_number( char const *buf, char const *end, |
75 | + bool check_trailing_chars ) { |
76 | + if ( end == buf ) |
77 | + throw std::invalid_argument( BUILD_STRING( '"', buf, "\": no digits" ) ); |
78 | + if ( check_trailing_chars ) |
79 | + for ( ; *end; ++end ) // remaining characters, if any, ... |
80 | + if ( !ascii::is_space( *end ) ) // ... may only be whitespace |
81 | + throw std::invalid_argument( |
82 | + BUILD_STRING( '"', *end, "\": invalid character" ) |
83 | + ); |
84 | +} |
85 | + |
86 | +#define ATON_PREAMBLE() \ |
87 | + bool check_trailing_chars; \ |
88 | + char const *pc; \ |
89 | + if ( end ) { \ |
90 | + check_trailing_chars = false; \ |
91 | + } else { \ |
92 | + end = &pc; \ |
93 | + check_trailing_chars = true; \ |
94 | + } \ |
95 | + errno = 0 |
96 | + |
97 | +/////////////////////////////////////////////////////////////////////////////// |
98 | + |
99 | +double atod( char const *buf, char const **end ) { |
100 | + ATON_PREAMBLE(); |
101 | + double const result = std::strtod( buf, (char**)end ); |
102 | + check_parse_number( buf, *end, check_trailing_chars ); |
103 | + return result; |
104 | +} |
105 | + |
106 | +float atof( char const *buf, char const **end ) { |
107 | + ATON_PREAMBLE(); |
108 | + float const result = std::strtof( buf, (char**)end ); |
109 | + check_parse_number( buf, *end, check_trailing_chars ); |
110 | + return result; |
111 | +} |
112 | + |
113 | +long long atoll( char const *buf, char const **end ) { |
114 | + ATON_PREAMBLE(); |
115 | + long long const result = std::strtoll( buf, (char**)end, 10 ); |
116 | + check_errno( buf, *end ); |
117 | + check_parse_number( buf, *end, check_trailing_chars ); |
118 | + return result; |
119 | +} |
120 | + |
121 | +unsigned long long atoull( char const *buf, char const **end ) { |
122 | + ATON_PREAMBLE(); |
123 | // |
124 | // We have to check for '-' ourselves since strtoull(3) allows it (oddly). |
125 | // |
126 | - s = ascii::trim_start_whitespace( s ); |
127 | - bool const minus = *s == '-'; |
128 | + buf = ascii::trim_start_whitespace( buf ); |
129 | + bool const minus = *buf == '-'; |
130 | |
131 | - char *end; |
132 | - errno = 0; |
133 | - unsigned long long const result = std::strtoull( s, &end, 10 ); |
134 | - check_parse_number( s, end, static_cast<unsigned long long*>( nullptr ) ); |
135 | + unsigned long long const result = std::strtoull( buf, (char**)end, 10 ); |
136 | + check_errno( buf, *end ); |
137 | + check_parse_number( buf, *end, check_trailing_chars ); |
138 | |
139 | if ( minus && result ) { |
140 | // |
141 | @@ -123,7 +130,7 @@ |
142 | // Hence, this allows "-0" and treats it as "0". |
143 | // |
144 | throw std::invalid_argument( |
145 | - "\"-\": invalid character for unsigned integer" |
146 | + "'-': invalid character for unsigned integer" |
147 | ); |
148 | } |
149 | return result; |
150 | |
151 | === modified file 'src/util/string_util.h' |
152 | --- src/util/string_util.h 2013-01-07 14:49:20 +0000 |
153 | +++ src/util/string_util.h 2013-01-10 23:41:23 +0000 |
154 | @@ -408,61 +408,76 @@ |
155 | /** |
156 | * Parses the given string for a \c double. |
157 | * |
158 | - * @param s The null-terminated C string to parse. Leading and trailing |
159 | + * @param buf The null-terminated C string to parse. Leading and trailing |
160 | * whitespace is ignored. |
161 | + * @param end If not \c null, this is set to point to the character after the |
162 | + * last numeric character parsed; if \c null, characters past the last numeric |
163 | + * character may only be whitespace. |
164 | * @return Returns the \c double value. |
165 | - * @throws invalid_argument if \a s contains characters other than digits or |
166 | + * @throws invalid_argument if \a buf contains characters other than digits or |
167 | * leading/trailing whitespace, or contains no digits at all. |
168 | * @throws range_error if the number overflows/underflows. |
169 | */ |
170 | -double atod( char const *s ); |
171 | +double atod( char const *buf, char const **end = nullptr ); |
172 | |
173 | /** |
174 | * Parses the given string for a \c float. |
175 | * |
176 | - * @param s The null-terminated C string to parse. Leading and trailing |
177 | + * @param buf The null-terminated C string to parse. Leading and trailing |
178 | * whitespace is ignored. |
179 | + * @param end If not \c null, this is set to point to the character after the |
180 | + * last numeric character parsed; if \c null, characters past the last numeric |
181 | + * character may only be whitespace. |
182 | * @return Returns the \c float value. |
183 | - * @throws invalid_argument if \a s contains characters other than digits or |
184 | + * @throws invalid_argument if \a buf contains characters other than digits or |
185 | * leading/trailing whitespace, or contains no digits at all. |
186 | * @throws range_error if the number overflows/underflows. |
187 | */ |
188 | -float atof( char const *s ); |
189 | +float atof( char const *buf, char const **end = nullptr ); |
190 | |
191 | /** |
192 | * Parses the given string for a <code>long lomg</code>. |
193 | * |
194 | - * @param s The null-terminated C string to parse. Leading and trailing |
195 | + * @param buf The null-terminated C string to parse. Leading and trailing |
196 | * whitespace is ignored. |
197 | + * @param end If not \c null, this is set to point to the character after the |
198 | + * last numeric character parsed; if \c null, characters past the last numeric |
199 | + * character may only be whitespace. |
200 | * @return Returns the <code>long long</code> value. |
201 | - * @throws invalid_argument if \a s contains characters other than digits or |
202 | + * @throws invalid_argument if \a buf contains characters other than digits or |
203 | * leading/trailing whitespace, or contains no digits at all. |
204 | * @throws range_error if the number overflows/underflows. |
205 | */ |
206 | -long long atoll( char const *s ); |
207 | +long long atoll( char const *buf, char const **end = nullptr ); |
208 | |
209 | /** |
210 | * Parses the given string for an <code>unsigned long lomg</code>. |
211 | * |
212 | - * @param s The null-terminated C string to parse. Leading and trailing |
213 | + * @param buf The null-terminated C string to parse. Leading and trailing |
214 | * whitespace is ignored. |
215 | + * @param end If not \c null, this is set to point to the character after the |
216 | + * last numeric character parsed; if \c null, characters past the last numeric |
217 | + * character may only be whitespace. |
218 | * @return Returns the <code>unsigned long long</code> value. |
219 | - * @throws invalid_argument if \a s contains characters other than digits or |
220 | + * @throws invalid_argument if \a buf contains characters other than digits or |
221 | * leading/trailing whitespace, or contains no digits at all. |
222 | * @throws range_error if the number overflows/underflows. |
223 | */ |
224 | -unsigned long long atoull( char const *s ); |
225 | +unsigned long long atoull( char const *buf, char const **end = nullptr ); |
226 | |
227 | /** |
228 | * Parses the given string for a C++ signed integral type. |
229 | * |
230 | * @tparam IntegralType The C++ signed integral type to parse for. |
231 | - * @param s The null-terminated C string to parse. Leading and trailing |
232 | + * @param buf The null-terminated C string to parse. Leading and trailing |
233 | * whitespace is ignored. |
234 | + * @param end If not \c null, this is set to point to the character after the |
235 | + * last numeric character parsed; if \c null, characters past the last numeric |
236 | + * character may only be whitespace. |
237 | * @return Returns the \c IntegralType value. |
238 | - * @throws invalid_argument if \a s contains characters other than digits or |
239 | - * leading/trailing whitespace, or contains no digits at all. |
240 | - * @throws range_error if the number overflows/underflows. |
241 | + * @throws invalid_argument if \a buf contains characters other than digits, a |
242 | + * sign, or leading/trailing whitespace, or contains no digits at all. |
243 | + * @throws range_error if the number is either too small or too big. |
244 | */ |
245 | template<typename IntegralType> inline |
246 | // |
247 | @@ -473,8 +488,8 @@ |
248 | typename std::enable_if<ZORBA_TR1_NS::is_integral<IntegralType>::value |
249 | && ZORBA_TR1_NS::is_signed<IntegralType>::value, |
250 | IntegralType>::type |
251 | -aton( char const *s ) { |
252 | - long long const result = atoll( s ); |
253 | +aton( char const *buf, char const **end = nullptr ) { |
254 | + long long const result = atoll( buf, end ); |
255 | if ( result < std::numeric_limits<IntegralType>::min() || |
256 | result > std::numeric_limits<IntegralType>::max() ) |
257 | throw std::range_error( |
258 | @@ -484,60 +499,137 @@ |
259 | } |
260 | |
261 | /** |
262 | + * Parses the given string for a C++ signed integral type. |
263 | + * |
264 | + * @tparam IntegralType The C++ signed integral type to parse for. |
265 | + * @param buf The null-terminated C string to parse. Leading and trailing |
266 | + * whitespace is ignored. |
267 | + * @param low The lower acceptable bound. |
268 | + * @param high the higher acceptable bound. |
269 | + * @param end If not \c null, this is set to point to the character after the |
270 | + * last numeric character parsed; if \c null, characters past the last numeric |
271 | + * character may only be whitespace. |
272 | + * @return Returns the \c IntegralType value. |
273 | + * @throws invalid_argument if \a buf contains characters other than digits, a |
274 | + * sign, or leading/trailing whitespace, or contains no digits at all. |
275 | + * @throws range_error if the number is either too small or too big. |
276 | + */ |
277 | +template<typename IntegralType> inline |
278 | +// |
279 | +// Note that the is_integral shouldn't be needed since is_signed means "is a |
280 | +// signed integral type", but Microsoft's implementation is broken and returns |
281 | +// true for floating point types as well. |
282 | +// |
283 | +typename std::enable_if<ZORBA_TR1_NS::is_integral<IntegralType>::value |
284 | + && ZORBA_TR1_NS::is_signed<IntegralType>::value, |
285 | + IntegralType>::type |
286 | +aton( char const *buf, IntegralType low, IntegralType high, |
287 | + char const **end = nullptr ) { |
288 | + long long const result = atoll( buf, end ); |
289 | + if ( result < low || result > high ) |
290 | + throw std::range_error( |
291 | + BUILD_STRING( |
292 | + '"', result, "\": number not in range ", low, '-', high |
293 | + ) |
294 | + ); |
295 | + return static_cast<IntegralType>( result ); |
296 | +} |
297 | + |
298 | +/** |
299 | * Parses the given string for a C++ unsigned integral types. |
300 | * |
301 | * @tparam IntegralType The C++ unsigned integral type to parse for. |
302 | - * @param s The null-terminated C string to parse. Leading and trailing |
303 | + * @param buf The null-terminated C string to parse. Leading and trailing |
304 | * whitespace is ignored. |
305 | + * @param end If not \c null, this is set to point to the character after the |
306 | + * last numeric character parsed; if \c null, characters past the last numeric |
307 | + * character may only be whitespace. |
308 | * @return Returns the \c IntegralType value. |
309 | - * @throws invalid_argument if \a s contains characters other than digits or |
310 | - * leading/trailing whitespace, or contains no digits at all. |
311 | - * @throws range_error if the number overflows/underflows. |
312 | + * @throws invalid_argument if \a buf contains characters other than digits, a |
313 | + * sign, or leading/trailing whitespace, or contains no digits at all. |
314 | + * @throws range_error if the number is either too small or too big. |
315 | */ |
316 | template<typename IntegralType> inline |
317 | typename std::enable_if<ZORBA_TR1_NS::is_unsigned<IntegralType>::value, |
318 | IntegralType>::type |
319 | -aton( char const *s ) { |
320 | - unsigned long long const result = atoull( s ); |
321 | +aton( char const *buf, char const **end = nullptr ) { |
322 | + unsigned long long const result = atoull( buf, end ); |
323 | if ( result > std::numeric_limits<IntegralType>::max() ) |
324 | throw std::range_error( BUILD_STRING( '"', result, "\": number too big" ) ); |
325 | return static_cast<IntegralType>( result ); |
326 | } |
327 | |
328 | /** |
329 | + * Parses the given string for a C++ unsigned integral types. |
330 | + * |
331 | + * @tparam IntegralType The C++ unsigned integral type to parse for. |
332 | + * @param buf The null-terminated C string to parse. Leading and trailing |
333 | + * whitespace is ignored. |
334 | + * @param low The lower acceptable bound. |
335 | + * @param high the higher acceptable bound. |
336 | + * @param end If not \c null, this is set to point to the character after the |
337 | + * last numeric character parsed; if \c null, characters past the last numeric |
338 | + * character may only be whitespace. |
339 | + * @return Returns the \c IntegralType value. |
340 | + * @throws invalid_argument if \a buf contains characters other than digits or |
341 | + * leading/trailing whitespace, or contains no digits at all. |
342 | + * @throws range_error if the number is either too small or too big. |
343 | + */ |
344 | +template<typename IntegralType> inline |
345 | +typename std::enable_if<ZORBA_TR1_NS::is_unsigned<IntegralType>::value, |
346 | + IntegralType>::type |
347 | +aton( char const *buf, IntegralType low, IntegralType high, |
348 | + char const **end = nullptr ) { |
349 | + unsigned long long const result = atoull( buf, end ); |
350 | + if ( result < low || result > high ) |
351 | + throw std::range_error( |
352 | + BUILD_STRING( |
353 | + '"', result, "\": number not in range ", low, '-', high |
354 | + ) |
355 | + ); |
356 | + return static_cast<IntegralType>( result ); |
357 | +} |
358 | + |
359 | +/** |
360 | * Parses the given string for a C++ \c double type. |
361 | * |
362 | - * @param s The null-terminated C string to parse. Leading and trailing |
363 | + * @param buf The null-terminated C string to parse. Leading and trailing |
364 | * whitespace is ignored. |
365 | + * @param end If not \c null, this is set to point to the character after the |
366 | + * last numeric character parsed; if \c null, characters past the last numeric |
367 | + * character may only be whitespace. |
368 | * @return Returns the \c double value. |
369 | - * @throws invalid_argument if \a s contains characters other than those for a |
370 | - * valid \c double value or leading/trailing whitespace, or contains no digits |
371 | - * at all. |
372 | + * @throws invalid_argument if \a buf contains characters other than those for |
373 | + * a valid \c double value or leading/trailing whitespace, or contains no |
374 | + * digits at all. |
375 | * @throws range_error if the number overflows/underflows. |
376 | */ |
377 | template<typename NumericType> inline |
378 | typename std::enable_if<ZORBA_TR1_NS::is_same<NumericType,double>::value, |
379 | NumericType>::type |
380 | -aton( char const *s ) { |
381 | - return atod( s ); |
382 | +aton( char const *buf, char const **end = nullptr ) { |
383 | + return atod( buf, end ); |
384 | } |
385 | |
386 | /** |
387 | * Parses the given string for a C++ \c float type. |
388 | * |
389 | - * @param s The null-terminated C string to parse. Leading and trailing |
390 | + * @param buf The null-terminated C string to parse. Leading and trailing |
391 | * whitespace is ignored. |
392 | + * @param end If not \c null, this is set to point to the character after the |
393 | + * last numeric character parsed; if \c null, characters past the last numeric |
394 | + * character may only be whitespace. |
395 | * @return Returns the \c float value. |
396 | - * @throws invalid_argument if \a s contains characters other than those for a |
397 | - * valid \c float value or leading/trailing whitespace, or contains no digits |
398 | + * @throws invalid_argument if \a buf contains characters other than those for |
399 | + * a valid \c float value or leading/trailing whitespace, or contains no digits |
400 | * at all. |
401 | * @throws range_error if the number overflows/underflows. |
402 | */ |
403 | template<typename NumericType> inline |
404 | typename std::enable_if<ZORBA_TR1_NS::is_same<NumericType,float>::value, |
405 | NumericType>::type |
406 | -aton( char const *s ) { |
407 | - return atof( s ); |
408 | +aton( char const *buf, char const **end = nullptr ) { |
409 | + return atof( buf, end ); |
410 | } |
411 | |
412 | ////////// To-string conversion //////////////////////////////////////////////// |
Validation queue starting for merge proposal. zorbatest. lambda. nu:8080/ remotequeue/ pjl-misc- 2013-01- 10T23-45- 42.555Z/ log.html
Log at: http://