root/win32/strtoi64.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _strtoi64

   1 #if _MSC_VERS <= 1300
   2 #include "php_strtoi64.h"
   3 /*
   4         From APR, apr_strings.c
   5         See http://www.apache.org/licenses/LICENSE-2.0
   6 */
   7 
   8 PHPAPI int64_t _strtoi64(const char *nptr, char **endptr, int base)
   9 {
  10         const char *s;
  11         int64_t acc;
  12         int64_t val;
  13         int neg, any;
  14         char c;
  15 
  16         /*
  17          * Skip white space and pick up leading +/- sign if any.
  18          * If base is 0, allow 0x for hex and 0 for octal, else
  19          * assume decimal; if base is already 16, allow 0x.
  20          */
  21         s = nptr;
  22         do {
  23                 c = *s++;
  24         } while (isspace((unsigned char)c));
  25         if (c == '-') {
  26                 neg = 1;
  27                 c = *s++;
  28         } else {
  29                 neg = 0;
  30                 if (c == '+') {
  31                         c = *s++;
  32                 }
  33         }
  34 
  35         if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
  36                 c = s[1];
  37                 s += 2;
  38                 base = 16;
  39         }
  40         if (base == 0) {
  41                 base = c == '0' ? 8 : 10;
  42         }
  43         acc = any = 0;
  44         if (base < 2 || base > 36) {
  45                 errno = EINVAL;
  46                 if (endptr != NULL) {
  47                         *endptr = (char *)(any ? s - 1 : nptr);
  48                 }
  49                 return acc;
  50         }
  51 
  52         /* The classic bsd implementation requires div/mod operators
  53          * to compute a cutoff.  Benchmarking proves that iss very, very
  54          * evil to some 32 bit processors.  Instead, look for underflow
  55          * in both the mult and add/sub operation.  Unlike the bsd impl,
  56          * we also work strictly in a signed int64 word as we haven't
  57          * implemented the unsigned type in win32.
  58          *
  59          * Set 'any' if any `digits' consumed; make it negative to indicate
  60          * overflow.
  61          */
  62     val = 0;
  63         for ( ; ; c = *s++) {
  64                 if (c >= '0' && c <= '9')
  65                         c -= '0';
  66 
  67 #if (('Z' - 'A') == 25)
  68                 else if (c >= 'A' && c <= 'Z')
  69                         c -= 'A' - 10;
  70                 else if (c >= 'a' && c <= 'z')
  71                         c -= 'a' - 10;
  72 #elif APR_CHARSET_EBCDIC
  73                 else if (c >= 'A' && c <= 'I')
  74                         c -= 'A' - 10;
  75                 else if (c >= 'J' && c <= 'R')
  76                         c -= 'J' - 19;
  77                 else if (c >= 'S' && c <= 'Z')
  78                         c -= 'S' - 28;
  79                 else if (c >= 'a' && c <= 'i')
  80                         c -= 'a' - 10;
  81                 else if (c >= 'j' && c <= 'r')
  82                         c -= 'j' - 19;
  83                 else if (c >= 's' && c <= 'z')
  84                         c -= 'z' - 28;
  85 #else
  86 # error "CANNOT COMPILE apr_strtoi64(), only ASCII and EBCDIC supported"
  87 #endif
  88                 else {
  89                         break;
  90                 }
  91 
  92                 if (c >= base) {
  93                         break;
  94                 }
  95 
  96                 val *= base;
  97                 if ( (any < 0)  /* already noted an over/under flow - short circuit */
  98                                 || (neg && (val > acc || (val -= c) > acc)) /* underflow */
  99                                 || (val < acc || (val += c) < acc)) {       /* overflow */
 100                         any = -1;       /* once noted, over/underflows never go away */
 101 #ifdef APR_STRTOI64_OVERFLOW_IS_BAD_CHAR
 102                         break;
 103 #endif
 104                 } else {
 105                         acc = val;
 106                         any = 1;
 107                 }
 108         }
 109 
 110         if (any < 0) {
 111                 acc = neg ? INT64_MIN : INT64_MAX;
 112                 errno = ERANGE;
 113         } else if (!any) {
 114                 errno = EINVAL;
 115         }
 116 
 117         if (endptr != NULL) {
 118                 *endptr = (char *)(any ? s - 1 : nptr);
 119         }
 120         return (acc);
 121 }
 122 #endif

/* [<][>][^][v][top][bottom][index][help] */