Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
strtol.cpp
Go to the documentation of this file.
1
29#define _RWSTD_LIB_SRC
30#include <rw/_defs.h>
31
32#include "strtol.h"
33#include <errno.h> // for ERANGE, errno
34
35
36// in case EINVAL is not #defined in errno.h
37#ifdef EINVAL
38# define _RWSTD_EINVAL EINVAL
39#else // if !defined (EINVAL)
40// actual value of EINVAL on both Linux and SunOS is 22
41# define _RWSTD_EINVAL 22
42#endif // EINVAL
43
44
46
47
48typedef unsigned char UChar;
49
50
51// array of values of each base 2 through 36 digits, i.e., 0-9, A-Z,
52// and a-z; elements with value greater than 35 do not correspond to
53// any valid digit
54_RWSTD_EXPORT extern const UChar
55__rw_digit_map[] = {
56
57#if 'A' == 0x41
58
59 // basic ASCII:
60 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
61 // NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI
62 /* 0 */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
63 // DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
64 /* 1 */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
65 // SPC ! " # $ % ' ' ( ) * + , - . /
66 /* 2 */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 43, 99, 43, 99, 99,
67 // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
68 /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 99, 99, 99, 99, 99, 99,
69 // @ A B C D E F G H I J K L M N O
70 /* 4 */ 99, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
71 // P Q R S T U V W X Y Z [ \ ] ^ _
72 /* 5 */ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 99, 99, 99, 99, 99,
73 // ` a b c d e f g h i j k l m n o
74 /* 6 */ 99, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
75 // p q r s t u v w x y z { | } ~ DEL
76 /* 7 */ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 99, 99, 99, 99, 99,
77
78 // extended ASCII:
79 // IND NEL SSA ESA HTS HTJ VTS PLD PLU RI SS2 SS3
80 /* 8 */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
81 // DCS PU1 PU2 STS CCH MW SPA EPA CSI ST OSC PM APC
82 /* 9 */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
83 /* a */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
84 /* b */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
85 /* c */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
86 /* d */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
87 /* e */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
88 /* f */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99
89
90#elif 'A' == 0xc1
91
92 // EBCDIC:
93 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
94 // NUL SOH STX ETX PF HT LC DEL SMM VT FF CR SO SI
95 /* 0 */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
96 // DLE DC1 DC2 TM RES NL BS IL CAN EM CC CU1 IFS IGS IRS IUS
97 /* 1 */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
98 // DS SOS FS BYP LF ETB ESC SM CU2 ENQ ACK BEL
99 /* 2 */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
100 // SYN PN RS UC EOT CU3 DC4 NAK SUB
101 /* 3 */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
102 // SP ct. . < ( + |
103 /* 4 */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 43, 99,
104 // & ! $ * ) ; ~
105 /* 5 */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
106 // - / , % _ > ?
107 /* 6 */ 43, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
108 // : # @ ' = "
109 /* 7 */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
110 // a b c d e f g h i
111 /* 8 */ 99, 10, 11, 12, 13, 14, 15, 16, 17, 18, 99, 99, 99, 99, 99, 99,
112 // j k l m n o p q r
113 /* 9 */ 99, 19, 20, 21, 22, 23, 24, 25, 26, 27, 99, 99, 99, 99, 99, 99,
114 // s t u v w x y z
115 /* a */ 99, 99, 28, 29, 30, 31, 32, 33, 34, 35, 99, 99, 99, 99, 99, 99,
116 // `
117 /* b */ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
118 // A B C D E F G H I
119 /* c */ 99, 10, 11, 12, 13, 14, 15, 16, 17, 18, 99, 99, 99, 99, 99, 99,
120 // J K L M N O P Q R
121 /* d */ 99, 19, 20, 21, 22, 23, 24, 25, 26, 27, 99, 99, 99, 99, 99, 99,
122 // S T U V W X Y Z
123 /* e */ 99, 99, 28, 29, 30, 31, 32, 33, 34, 35, 99, 99, 99, 99, 99, 99,
124 // 0 1 2 3 4 5 6 7 8 9
125 /* f */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 99, 99, 99, 99, 99, 99
126
127#else // 'A' != 0x41 && 'A' != 0xc1
128# error unknown character set (neither ASCII nor EBCDIC)
129#endif // ASCII or EBCDIC
130
131};
132
133
134// the number of bits necessary to exactly represent
135// a single digit in base 0 - 36 (base is index)
136static const char
137__rw_base_bits [] = {
138 /* 0 - 15 */ 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
139 /* 16 - 31 */ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
140 /* 32 - 36 */ 0, 0, 0, 0, 0
141
142 // Note: __rw_base_bits [32] is 0 above to eliminate overflow
143 // checking for strings of up to 8 hexadecimal digits
144 // in __rw_strtoul() below
145};
146
147
148#undef max
149#undef min
150
151
152// SHift Left and OR: helper macro used by __rw_strtol
153// to multiply a number by a power of 2 (SHL) and add
154// another number less than the power (OR)
155//
156// IMPORTANT: each argument must be evaluated exactly once
157#undef SHLOR
158#define SHLOR(x, dig) (((x) << shift) | __rw_digit_map [UChar (dig)])
159
160// helper macro to keep lines under 80 characters
161#define SHLOR_4_DIGITS_BEGIN(res, nptr) \
162 if (*++nptr) { \
163 res = SHLOR (res, *nptr); \
164 if (*++nptr) { \
165 res = SHLOR (res, *nptr); \
166 if (*++nptr) { \
167 res = SHLOR (res, *nptr); \
168 if (*++nptr) { \
169 res = SHLOR (res, *nptr)
170
171#define SHLOR_4_DIGITS_END() } } } } (void)0
172
173
174// MULtiply and ADD: helper macro used by __rw_strtol
175//
176// IMPORTANT: each argument must be evaluated exactly once
177#undef MULADD
178#define MULADD(x, dig) (((x) * base) + __rw_digit_map [UChar (dig)])
179
180// helper macro to keep lines under 80 characters
181#define MULADD_4_DIGITS_BEGIN(res, nptr) \
182 if (nptr [1]) { \
183 res = MULADD (res, *++nptr); \
184 if (nptr [1]) { \
185 res = MULADD (res, *++nptr); \
186 if (nptr [1]) { \
187 res = MULADD (res, *++nptr); \
188 if (nptr [1]) { \
189 res = MULADD (res, *++nptr)
190
191#define MULADD_4_DIGITS_END() } } } } (void)0
192
193
194unsigned long
195__rw_strtoul (const char *nptr, int *errptr, int base) _THROWS (())
196{
197 _RWSTD_ASSERT (0 != nptr);
198 _RWSTD_ASSERT (0 != errptr);
199 _RWSTD_ASSERT ('+' == *nptr || '-' == *nptr);
200 _RWSTD_ASSERT (1 < base && base < 37);
201
202 const bool neg = '-' == *nptr++;
203
204 if (!*nptr) {
205 *errptr = _RWSTD_EINVAL;
206 return 0;
207 }
208
209 const int shift = __rw_base_bits [base];
210
211 unsigned long res = __rw_digit_map [UChar (*nptr)];
212
213 _RWSTD_ASSERT (res < unsigned (base));
214
215 if (shift) {
216
217 // process subject sequence by shifting
218
219 if (*++nptr) {
220
221 // unroll loop w/o overflow checking for as many as
222 // 8 (on ILP32) or 16 (on LP64) digits (max base is 16)
223
224 // shift left and add second digit
225 res = SHLOR (res, *nptr);
226
227 if (*++nptr) {
228 // third digit
229 res = SHLOR (res, *nptr);
230
231 if (*++nptr) {
232 // fourth digit
233 res = SHLOR (res, *nptr);
234
235#if 2 < _RWSTD_LONG_SIZE
236
237 // parse up to 4 more digits w/o overflow checking
238 // (i.e., digits 5 through 8, inclusive)
240
241# if 4 < _RWSTD_LONG_SIZE
242
243 // .2....:....1....:....0
244 // ULONG_MAX >= 1777777777777777777777 (oct)
245 // ULONG_MAX >= ffffffffffffffff (hex)
246
247 // parse up to 8 more digits w/o overflow checking
248 // (i.e., digits 9 through 16, inclusive)
251
252# endif // 4 < _RWSTD_LONG_SIZE
253#endif // 2 < _RWSTD_LONG_SIZE
254
255 // parse any remaining digits with overflow checking
256 // (i.e., digits 9 on ILP32 or 17 on LP64 and beyond)
257 while (*++nptr) {
258 const unsigned digit =
259 __rw_digit_map [UChar (*nptr)];
260
261 _RWSTD_ASSERT (digit < unsigned (base));
262
263 // check for overflow
264 const unsigned long save = res;
265
266 res <<= shift;
267
268 if (res < save)
269 goto overflow;
270
271 // can't overflow
272 res += digit;
273 }
274
275#if 2 < _RWSTD_LONG_SIZE
276# if 4 < _RWSTD_LONG_SIZE
277
278 // close brackets
281
282# endif // 4 < _RWSTD_LONG_SIZE
283
284 // close brackets
286
287#endif // 2 < _RWSTD_LONG_SIZE
288
289 }
290 }
291 }
292 }
293 else {
294 // process subject sequence by multiplication
295
296 // unroll loop w/o overflow checking
297 if (*++nptr) {
298 // multiply by base and add second digit
299 res = MULADD (res, *nptr);
300
301#if 2 < _RWSTD_LONG_SIZE
302
303 // ....:....0 (10 decimal digits)
304 // ULONG_MAX >= 4294967295 (dec)
305 // ULONG_MAX >= 1z141z3 (base-36)
306
307 // digits 3 through 6, inclusive
309
310# if 4 < _RWSTD_LONG_SIZE
311
312 // ....:....1....:....0 (20 decimal digits)
313 // ULONG_MAX >= 18446744073709551615 (dec)
314 // ULONG_MAX >= 5g24a25twkwff (base-36)
315
316 // digits 7 through 10, inclusive
318
319 if (nptr [1]) {
320 // digit 11
321 res = MULADD (res, *++nptr);
322
323 if (base < 12) {
324
325 // unroll w/o overflow checking for bases up to 11
326
327 // digits 12 - 19
330
331 // close brackets
334 }
335 }
336
337 // close brackets
339
340# else // if 4 >= _RWSTD_LONG_SIZE
341
342 if (base < 12) {
343
344 // unroll w/o overflow checking for bases up to 11
345
346 if (nptr [1]) {
347 // seventh digit
348 res = MULADD (res, *++nptr);
349 if (nptr [1]) {
350 // eighth digit
351 res = MULADD (res, *++nptr);
352 if (nptr [1]) {
353 // ninth digit
354 res = MULADD (res, *++nptr);
355 }
356 }
357 }
358 }
359
360# endif // 4 < _RWSTD_LONG_SIZE
361
362 // close brackets
364
365#endif // 2 < _RWSTD_LONG_SIZE
366
367 for (unsigned long maxres = _RWSTD_ULONG_MAX / base; *++nptr; ) {
368
369 const unsigned digit = __rw_digit_map [UChar (*nptr)];
370
371 _RWSTD_ASSERT (digit < unsigned (base));
372
373 // check for overflow
374 if (maxres < res)
375 goto overflow;
376
377 res *= base;
378
379 if (_RWSTD_ULONG_MAX - res < digit)
380 goto overflow;
381
382 res += digit;
383 }
384 }
385 }
386
387 return neg ? 0UL - res : res;
388
389overflow:
390
391 // set errptr to ERANGE on overflow and return ULONG_MAX
392 *errptr = ERANGE;
393 return _RWSTD_ULONG_MAX;
394}
395
396
397long
398__rw_strtol (const char *nptr, int *errptr, int base) _THROWS (())
399{
400 _RWSTD_ASSERT (0 != nptr);
401 _RWSTD_ASSERT (0 != errptr);
402 _RWSTD_ASSERT ('+' == *nptr || '-' == *nptr);
403
404 const bool neg = '-' == *nptr++;
405
406 if (!*nptr) {
407 *errptr = _RWSTD_EINVAL;
408 return 0;
409 }
410
411 const int shift = __rw_base_bits [base];
412
413 unsigned long res = __rw_digit_map [UChar (*nptr)];
414
415 _RWSTD_ASSERT (res < unsigned (base));
416
417 if (shift) {
418
419 // process subject sequence by shifting
420
421 if (*++nptr) {
422
423 // unroll loop w/o overflow checking for as many as
424 // 8 (on ILP32) or 16 (on LP64) digits (max base is 16)
425
426 // shift left and add second digit
427 res = SHLOR (res, *nptr);
428
429 if (*++nptr) {
430 // third digit
431 res = SHLOR (res, *nptr);
432
433 if (*++nptr) {
434 // fourth digit
435 res = SHLOR (res, *nptr);
436
437#if 2 < _RWSTD_LONG_SIZE
438
439 // parse up to 4 more digits w/o overflow checking
440 // (i.e., digits 5 through 8, inclusive)
442
443# if 4 < _RWSTD_LONG_SIZE
444
445 // .2....:....1....:....0
446 // ULONG_MAX >= 1777777777777777777777 (oct)
447 // ULONG_MAX >= ffffffffffffffff (hex)
448
449 // parse up to 8 more digits w/o overflow checking
450 // (i.e., digits 9 through 16, inclusive)
453
454# endif // 4 < _RWSTD_LONG_SIZE
455#endif // 2 < _RWSTD_LONG_SIZE
456
457 // parse any remaining digits with overflow checking
458 // (i.e., digits 9 on ILP32 or 17 on LP64 and beyond)
459 while (*++nptr) {
460 const unsigned digit =
461 __rw_digit_map [UChar (*nptr)];
462
463 _RWSTD_ASSERT (digit < unsigned (base));
464
465 // check for overflow
466 const unsigned long save = res;
467
468 res <<= shift;
469
470 if (res < save)
471 goto overflow;
472
473 // can't overflow
474 res += digit;
475 }
476
477#if 2 < _RWSTD_LONG_SIZE
478# if 4 < _RWSTD_LONG_SIZE
479
480 // close brackets
483
484# endif // 4 < _RWSTD_LONG_SIZE
485
486 // close brackets
488
489#endif // 2 < _RWSTD_LONG_SIZE
490
491 }
492 }
493 }
494 }
495 else {
496 // process subject sequence by multiplication
497
498 // unroll loop w/o overflow checking
499 if (*++nptr) {
500 // multiply by base and add second digit
501 res = MULADD (res, *nptr);
502
503#if 2 < _RWSTD_LONG_SIZE
504
505 // ....:....0 (10 decimal digits)
506 // ULONG_MAX >= 4294967295 (dec)
507 // ULONG_MAX >= 1z141z3 (base-36)
508
509 // digits 3 through 6, inclusive
511
512# if 4 < _RWSTD_LONG_SIZE
513
514 // ....:....1....:....0 (20 decimal digits)
515 // ULONG_MAX >= 18446744073709551615 (dec)
516 // ULONG_MAX >= 5g24a25twkwff (base-36)
517
518 // digits 7 through 10, inclusive
520
521 if (nptr [1]) {
522 // digit 11
523 res = MULADD (res, *++nptr);
524
525 if (base < 12) {
526
527 // unroll w/o overflow checking for bases up to 11
528
529 // digits 12 - 19
532
533 // close brackets
536 }
537 }
538
539 // close brackets
541
542# else // if 4 >= _RWSTD_LONG_SIZE
543
544 if (base < 12) {
545
546 // unroll w/o overflow checking for bases up to 11
547
548 if (nptr [1]) {
549 // seventh digit
550 res = MULADD (res, *++nptr);
551 if (nptr [1]) {
552 // eighth digit
553 res = MULADD (res, *++nptr);
554 if (nptr [1]) {
555 // ninth digit
556 res = MULADD (res, *++nptr);
557 }
558 }
559 }
560 }
561
562# endif // 4 < _RWSTD_LONG_SIZE
563
564 // close brackets
566
567#endif // 2 < _RWSTD_LONG_SIZE
568
569
570 for (unsigned long maxres = _RWSTD_ULONG_MAX / base; *++nptr; ) {
571
572 const unsigned digit = __rw_digit_map [UChar (*nptr)];
573
574 _RWSTD_ASSERT (digit < unsigned (base));
575
576 // check for overflow
577 if (maxres < res)
578 goto overflow;
579
580 res *= base;
581
582 if (_RWSTD_ULONG_MAX - res < digit)
583 goto overflow;
584
585 res += digit;
586 }
587 }
588 }
589
590 typedef unsigned long ULong;
591
592 if (neg) {
593 if (res > ULong (_RWSTD_LONG_MIN)) {
594 *errptr = ERANGE;
595 return _RWSTD_LONG_MIN;
596 }
597
598 return -long (res);
599 }
600
601 if (res > ULong (_RWSTD_LONG_MAX)) {
602 *errptr = ERANGE;
603 return _RWSTD_LONG_MAX;
604 }
605
606 return res;
607
608overflow:
609
610 // set errptr to ERANGE on overflow and return LONG_MIN or _MAX
611 *errptr = ERANGE;
612 return ULong (neg ? _RWSTD_LONG_MIN : _RWSTD_LONG_MAX);
613}
614
615
616#ifdef _RWSTD_LONG_LONG
617
618
619// for convenience
620typedef _RWSTD_LONG_LONG LLong;
621typedef unsigned _RWSTD_LONG_LONG ULLong;
622
623
624 // using LLONG_SIZE instead of ULLONG_MAX in the preprocessor
625 // conditional below to work around a gcc 3.2 bug (PR #28595)
626# if (_RWSTD_LONG_SIZE < _RWSTD_LLONG_SIZE)
627
628ULLong
629__rw_strtoull (const char *nptr, int *errptr, int base) _THROWS (())
630{
631 _RWSTD_ASSERT (0 != nptr);
632 _RWSTD_ASSERT (0 != errptr);
633 _RWSTD_ASSERT ('+' == *nptr || '-' == *nptr);
634
635 const bool neg = '-' == *nptr++;
636
637 if (!*nptr) {
638 *errptr = _RWSTD_EINVAL;
639 return 0;
640 }
641
642 const int shift = __rw_base_bits [base];
643
644 ULLong res = __rw_digit_map [UChar (*nptr)];
645
646 _RWSTD_ASSERT (res < unsigned (base));
647
648 if (shift) {
649
650 // process subject sequence by shifting
651
652 if (*++nptr) {
653
654 // unroll loop w/o overflow checking for as many as
655 // 8 (on ILP32) or 16 (on LP64) digits (max base is 16)
656
657 // shift left and add second digit
658 res = SHLOR (res, *nptr);
659
660 if (*++nptr) {
661 // third digit
662 res = SHLOR (res, *nptr);
663
664 if (*++nptr) {
665 // fourth digit
666 res = SHLOR (res, *nptr);
667
668 // parse up to 4 more digits w/o overflow checking
669 // (i.e., digits 5 through 8, inclusive)
671
672# if 4 < _RWSTD_LLONG_SIZE
673
674 // .2....:....1....:....0
675 // ULLONG_MAX >= 1777777777777777777777 (oct)
676 // ULLONG_MAX >= ffffffffffffffff (hex)
677
678 // parse up to 8 more digits w/o overflow checking
679 // (i.e., digits 9 through 16, inclusive)
682
683# endif // 4 < _RWSTD_LLONG_SIZE
684
685 // parse any remaining digits with overflow checking
686 // (i.e., digits 9 on ILP32 or 17 on LP64 and beyond)
687 while (*++nptr) {
688 const unsigned digit =
689 __rw_digit_map [UChar (*nptr)];
690
691 _RWSTD_ASSERT (digit < unsigned (base));
692
693 // check for overflow
694 const ULLong save = res;
695
696 res <<= shift;
697
698 if (res < save)
699 goto overflow;
700
701 // can't overflow
702 res += digit;
703 }
704
705# if 4 < _RWSTD_LLONG_SIZE
706
707 // close brackets
710
711# endif // 4 < _RWSTD_LLONG_SIZE
712
713 // close brackets
715 }
716 }
717 }
718 }
719 else {
720 // process subject sequence by multiplication
721
722 // unroll loop w/o overflow checking
723 if (nptr [1]) {
724 // multiply by base and add second digit
725 res = MULADD (res, *++nptr);
726
727 // digits 3 through 6, inclusive
729
730# if 4 < _RWSTD_LLONG_SIZE
731
732 // ....:....1....:....0 (20 decimal digits)
733 // ULLONG_MAX >= 18446744073709551615 (dec)
734 // ULLONG_MAX >= 5g24a25twkwff (base-36)
735
736 // digits 7 through 10, inclusive
738
739 if (nptr [1]) {
740 // digit 11
741 res = MULADD (res, *++nptr);
742
743 if (base < 12) {
744
745 // unroll w/o overflow checking for bases up to 11
746
747 // digits 12 - 19
750
751 // close brackets
754 }
755 }
756
757 // close brackets
759
760# else // if 4 >= _RWSTD_LLONG_SIZE
761
762 if (base < 12) {
763
764 // unroll w/o overflow checking for bases up to 11
765
766 if (nptr [1]) {
767 // seventh digit
768 res = MULADD (res, *++nptr);
769 if (nptr [1]) {
770 // eighth digit
771 res = MULADD (res, *++nptr);
772 if (nptr [1]) {
773 // ninth digit
774 res = MULADD (res, *++nptr);
775 }
776 }
777 }
778 }
779
780# endif // 4 < _RWSTD_LLONG_SIZE
781
782 // close brackets
784
785 for (ULLong maxres = _RWSTD_ULLONG_MAX / base; *++nptr; ) {
786
787 const unsigned digit = __rw_digit_map [UChar (*nptr)];
788
789 _RWSTD_ASSERT (digit < unsigned (base));
790
791 // check for overflow
792 if (maxres < res)
793 goto overflow;
794
795 res *= base;
796
797 if (_RWSTD_ULLONG_MAX - res < digit)
798 goto overflow;
799
800 res += digit;
801 }
802 }
803 }
804
805 return neg ? 0UL - res : res;
806
807overflow:
808
809 // set errptr to ERANGE on overflow and return ULLONG_MAX
810 *errptr = ERANGE;
811 return _RWSTD_ULLONG_MAX;
812}
813
814
815LLong
816__rw_strtoll (const char *nptr, int *errptr, int base) _THROWS (())
817{
818 _RWSTD_ASSERT (0 != nptr);
819 _RWSTD_ASSERT (0 != errptr);
820 _RWSTD_ASSERT ('+' == *nptr || '-' == *nptr);
821
822 const bool neg = '-' == *nptr++;
823
824 if (!*nptr) {
825 *errptr = _RWSTD_EINVAL;
826 return 0;
827 }
828
829 const int shift = __rw_base_bits [base];
830
831 ULLong res = __rw_digit_map [UChar (*nptr)];
832
833 _RWSTD_ASSERT (res < unsigned (base));
834
835 if (shift) {
836
837 // process subject sequence by shifting
838
839 if (*++nptr) {
840
841 // unroll loop w/o overflow checking for as many as
842 // 8 (on ILP32) or 16 (on LP64) digits (max base is 16)
843
844 // shift left and add second digit
845 res = SHLOR (res, *nptr);
846
847 if (*++nptr) {
848 // third digit
849 res = SHLOR (res, *nptr);
850
851 if (*++nptr) {
852 // fourth digit
853 res = SHLOR (res, *nptr);
854
855 // parse up to 4 more digits w/o overflow checking
856 // (i.e., digits 5 through 8, inclusive)
858
859# if 4 < _RWSTD_LLONG_SIZE
860
861 // .2....:....1....:....0
862 // ULLONG_MAX >= 1777777777777777777777 (oct)
863 // ULLONG_MAX >= ffffffffffffffff (hex)
864
865 // parse up to 8 more digits w/o overflow checking
866 // (i.e., digits 9 through 16, inclusive)
869
870# endif // 4 < _RWSTD_LLONG_SIZE
871
872 // parse any remaining digits with overflow checking
873 // (i.e., digits 9 on ILP32 or 17 on LP64 and beyond)
874 while (*++nptr) {
875 const unsigned digit =
876 __rw_digit_map [UChar (*nptr)];
877
878 _RWSTD_ASSERT (digit < unsigned (base));
879
880 // check for overflow
881 const ULLong save = res;
882
883 res <<= shift;
884
885 if (res < save)
886 goto overflow;
887
888 // can't overflow
889 res += digit;
890 }
891
892# if 4 < _RWSTD_LLONG_SIZE
893
894 // close brackets
897
898# endif // 4 < _RWSTD_LLONG_SIZE
899
900 // close brackets
902 }
903 }
904 }
905 }
906 else {
907
908 // process subject sequence by multiplication
909
910 // unroll loop w/o overflow checking
911 if (*++nptr) {
912 // multiply by base and add second digit
913 res = MULADD (res, *nptr);
914
915 // digits 3 through 6, inclusive
917
918# if 4 < _RWSTD_LLONG_SIZE
919
920 // ....:....1....:....0 (20 decimal digits)
921 // ULLONG_MAX >= 18446744073709551615 (dec)
922 // ULLONG_MAX >= 5g24a25twkwff (base-36)
923
924 // digits 7 through 10, inclusive
926
927 if (nptr [1]) {
928 // digit 11
929 res = MULADD (res, *++nptr);
930
931 if (base < 12) {
932
933 // unroll w/o overflow checking for bases up to 11
934
935 // digits 12 - 19
938
939 // close brackets
942 }
943 }
944
945 // close brackets
947
948# else // if 4 >= _RWSTD_LLONG_SIZE
949
950 if (base < 12) {
951
952 // unroll w/o overflow checking for bases up to 11
953
954 if (nptr [1]) {
955 // seventh digit
956 res = MULADD (res, *++nptr);
957 if (nptr [1]) {
958 // eighth digit
959 res = MULADD (res, *++nptr);
960 if (nptr [1]) {
961 // ninth digit
962 res = MULADD (res, *++nptr);
963 }
964 }
965 }
966 }
967
968# endif // 4 < _RWSTD_LLONG_SIZE
969
970 // close brackets
972
973 for (ULLong maxres = _RWSTD_ULLONG_MAX / base; *++nptr; ) {
974
975 const unsigned digit = __rw_digit_map [UChar (*nptr)];
976
977 _RWSTD_ASSERT (digit < unsigned (base));
978
979 // check for overflow
980 if (maxres < res)
981 goto overflow;
982
983 res *= base;
984
985 if (_RWSTD_ULLONG_MAX - res < digit)
986 goto overflow;
987
988 res += digit;
989 }
990 }
991 }
992
993 if (neg) {
994 if (res > ULLong (_RWSTD_LLONG_MIN)) {
995 *errptr = ERANGE;
996 return _RWSTD_LLONG_MIN;
997 }
998
999 return -LLong (res);
1000 }
1001
1002 if (res > ULLong (_RWSTD_LLONG_MAX)) {
1003 *errptr = ERANGE;
1004 return _RWSTD_LLONG_MAX;
1005 }
1006
1007 return res;
1008
1009overflow:
1010
1011 // set errptr to ERANGE on overflow and return LLONG_MIN or _MAX
1012 *errptr = ERANGE;
1013 return ULLong (neg ? _RWSTD_LLONG_MIN : _RWSTD_LLONG_MAX);
1014}
1015
1016
1017# endif // _RWSTD_LLONG_SIZE < _RWSTD_LLONG_SIZE
1018#endif // _RWSTD_LONG_LONG
1019
1020
1021} // namespace __rw
#define res
Definition 17.names.cpp:531
#define neg
Definition 17.names.cpp:503
#define save
Definition 17.names.cpp:538
int shift(int i, int n)
@ ULLong
#define ERANGE
#define LLong
#define _THROWS()
#define _RWSTD_LONG_LONG
#define _RWSTD_EXPORT
Definition _defs.h:485
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
unsigned long ULong
Definition fmt_defs.h:43
unsigned char UChar
Definition collate.cpp:122
#define MULADD(x, dig)
#define MULADD_4_DIGITS_BEGIN(res, nptr)
#define SHLOR_4_DIGITS_END()
#define _RWSTD_EINVAL
Definition strtol.cpp:41
#define SHLOR_4_DIGITS_BEGIN(res, nptr)
#define MULADD_4_DIGITS_END()
#define SHLOR(x, dig)