]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/curl/lib/strtoofft.c
hello world
[icculus/iodoom3.git] / neo / curl / lib / strtoofft.c
1 /***************************************************************************
2  *                                  _   _ ____  _     
3  *  Project                     ___| | | |  _ \| |    
4  *                             / __| | | | |_) | |    
5  *                            | (__| |_| |  _ <| |___ 
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at http://curl.haxx.se/docs/copyright.html.
13  * 
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * $Id: strtoofft.c,v 1.5 2004/02/19 08:12:13 bagder Exp $
22  ***************************************************************************/
23
24 #include "setup.h"
25 #include "strtoofft.h"
26
27 #ifdef NEED_CURL_STRTOLL
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <errno.h>
31
32 static int get_char(char c, int base);
33
34 /**
35  * Emulated version of the strtoll function.  This extracts a long long
36  * value from the given input string and returns it.
37  */
38 curl_off_t
39 curlx_strtoll(const char *nptr, char **endptr, int base)
40 {
41   char *end;
42   int is_negative = 0;
43   int overflow;
44   int i;
45   curl_off_t value = 0;
46   curl_off_t newval;
47
48   /* Skip leading whitespace. */
49   end = (char *)nptr;
50   while (isspace((int)end[0])) {
51     end++;
52   }
53
54   /* Handle the sign, if any. */
55   if (end[0] == '-') {
56     is_negative = 1;
57     end++;
58   }
59   else if (end[0] == '+') {
60     end++;
61   }
62   else if (end[0] == '\0') {
63     /* We had nothing but perhaps some whitespace -- there was no number. */
64     if (endptr) {
65       *endptr = end;
66     }
67     return 0;
68   }
69
70   /* Handle special beginnings, if present and allowed. */
71   if (end[0] == '0' && end[1] == 'x') {
72     if (base == 16 || base == 0) {
73       end += 2;
74       base = 16;
75     }
76   }
77   else if (end[0] == '0') {
78     if (base == 8 || base == 0) {
79       end++;
80       base = 8;
81     }
82   }
83
84   /* Matching strtol, if the base is 0 and it doesn't look like
85    * the number is octal or hex, we assume it's base 10.
86    */
87   if (base == 0) {
88     base = 10;
89   }
90
91   /* Loop handling digits. */
92   value = 0;
93   overflow = 0;
94   for (i = get_char(end[0], base);
95        i != -1;
96        end++, i = get_char(end[0], base)) {
97     newval = base * value + i;
98     if (newval < value) {
99       /* We've overflowed. */
100       overflow = 1;
101       break;
102     }
103     else
104       value = newval;
105   }
106
107   if (!overflow) {
108     if (is_negative) {
109       /* Fix the sign. */
110       value *= -1;
111     }
112   }
113   else {
114     if (is_negative)
115       value = 0x8000000000000000L;
116     else
117       value = 0x7FFFFFFFFFFFFFFFL;
118
119     errno = ERANGE;
120   }
121
122   if (endptr)
123     *endptr = end;
124
125   return value;
126 }
127
128 /**
129  * Returns the value of c in the given base, or -1 if c cannot
130  * be interpreted properly in that base (i.e., is out of range,
131  * is a null, etc.).
132  *
133  * @param c     the character to interpret according to base
134  * @param base  the base in which to interpret c
135  *
136  * @return  the value of c in base, or -1 if c isn't in range
137  */
138 static int get_char(char c, int base)
139 {
140   int value = -1;
141   if (c <= '9' && c >= '0') {
142     value = c - '0';
143   }
144   else if (c <= 'Z' && c >= 'A') {
145     value = c - 'A' + 10;
146   }
147   else if (c <= 'z' && c >= 'a') {
148     value = c - 'a' + 10;
149   }
150
151   if (value >= base) {
152     value = -1;
153   }
154
155   return value;
156 }
157 #endif  /* Only present if we need strtoll, but don't have it. */