Apple里的strtol实现!

  1 static inline int
  2 isupper(char c)
  3 {
  4     return (c >= 'A' && c <= 'Z');
  5 }
  6 
  7 static inline int
  8 isalpha(char c)
  9 {
 10     return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
 11 }
 12 
 13 
 14 static inline int
 15 isspace(char c)
 16 {
 17     return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
 18 }
 19 
 20 static inline int
 21 isdigit(char c)
 22 {
 23     return (c >= '0' && c <= '9');
 24 }
 25 
 26 /*
 27  * Convert a string to a long integer.
 28  *
 29  * Ignores `locale' stuff.  Assumes that the upper and lower case
 30  * alphabets and digits are each contiguous.
 31  */
 32 long
 33 strtol(nptr, endptr, base)
 34     const char *nptr;
 35     char **endptr;
 36     register int base;
 37 {
 38     register const char *s = nptr;
 39     register unsigned long acc;
 40     register int c;
 41     register unsigned long cutoff;
 42     register int neg = 0, any, cutlim;
 43 
 44     /*
 45      * Skip white space and pick up leading +/- sign if any.
 46      * If base is 0, allow 0x for hex and 0 for octal, else
 47      * assume decimal; if base is already 16, allow 0x.
 48      */
 49     do {
 50         c = *s++;
 51     } while (isspace(c));
 52     if (c == '-') {
 53         neg = 1;
 54         c = *s++;
 55     } else if (c == '+')
 56         c = *s++;
 57     if ((base == 0 || base == 16) &&
 58         c == '0' && (*s == 'x' || *s == 'X')) {
 59         c = s[1];
 60         s += 2;
 61         base = 16;
 62     } else if ((base == 0 || base == 2) &&
 63         c == '0' && (*s == 'b' || *s == 'B')) {
 64         c = s[1];
 65         s += 2;
 66         base = 2;
 67     }
 68     if (base == 0)
 69         base = c == '0' ? 8 : 10;
 70 
 71     /*
 72      * Compute the cutoff value between legal numbers and illegal
 73      * numbers.  That is the largest legal value, divided by the
 74      * base.  An input number that is greater than this value, if
 75      * followed by a legal input character, is too big.  One that
 76      * is equal to this value may be valid or not; the limit
 77      * between valid and invalid numbers is then based on the last
 78      * digit.  For instance, if the range for longs is
 79      * [-2147483648..2147483647] and the input base is 10,
 80      * cutoff will be set to 214748364 and cutlim to either
 81      * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
 82      * a value > 214748364, or equal but the next digit is > 7 (or 8),
 83      * the number is too big, and we will return a range error.
 84      *
 85      * Set any if any `digits' consumed; make it negative to indicate
 86      * overflow.
 87      */
 88     cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
 89     cutlim = cutoff % (unsigned long)base;
 90     cutoff /= (unsigned long)base;
 91     for (acc = 0, any = 0;; c = *s++) {
 92         if (isdigit(c))
 93             c -= '0';
 94         else if (isalpha(c))
 95             c -= isupper(c) ? 'A' - 10 : 'a' - 10;
 96         else
 97             break;
 98         if (c >= base)
 99             break;
100         if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
101             any = -1;
102         else {
103             any = 1;
104             acc *= base;
105             acc += c;
106         }
107     }
108     if (any < 0) {
109         acc = neg ? LONG_MIN : LONG_MAX;
110 //        errno = ERANGE;
111     } else if (neg)
112         acc = -acc;
113     if (endptr != 0)
114         *endptr = (char *)(any ? s - 1 : nptr);
115     return (acc);
116 }
117 
118 /*
119  * Convert a string to an unsigned long integer.
120  *
121  * Ignores `locale' stuff.  Assumes that the upper and lower case
122  * alphabets and digits are each contiguous.
123  */
124 unsigned long
125 strtoul(nptr, endptr, base)
126     const char *nptr;
127     char **endptr;
128     register int base;
129 {
130     register const char *s = nptr;
131     register unsigned long acc;
132     register int c;
133     register unsigned long cutoff;
134     register int neg = 0, any, cutlim;
135 
136     /*
137      * See strtol for comments as to the logic used.
138      */
139     do {
140         c = *s++;
141     } while (isspace(c));
142     if (c == '-') {
143         neg = 1;
144         c = *s++;
145     } else if (c == '+')
146         c = *s++;
147     if ((base == 0 || base == 16) &&
148         c == '0' && (*s == 'x' || *s == 'X')) {
149         c = s[1];
150         s += 2;
151         base = 16;
152     } else if ((base == 0 || base == 2) &&
153         c == '0' && (*s == 'b' || *s == 'B')) {
154         c = s[1];
155         s += 2;
156         base = 2;
157     }
158     if (base == 0)
159         base = c == '0' ? 8 : 10;
160     cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
161     cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
162     for (acc = 0, any = 0;; c = *s++) {
163         if (isdigit(c))
164             c -= '0';
165         else if (isalpha(c))
166             c -= isupper(c) ? 'A' - 10 : 'a' - 10;
167         else
168             break;
169         if (c >= base)
170             break;
171         if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
172             any = -1;
173         else {
174             any = 1;
175             acc *= base;
176             acc += c;
177         }
178     }
179     if (any < 0) {
180         acc = ULONG_MAX;
181 //        errno = ERANGE;
182     } else if (neg)
183         acc = -acc;
184     if (endptr != 0)
185         *endptr = (char *)(any ? s - 1 : nptr);
186     return (acc);
187 }
posted @ 2012-10-22 00:38  lorddeseis  阅读(417)  评论(0编辑  收藏  举报