00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <config.h>
00017 #include <drizzled/internal/m_string.h>
00018 #include <errno.h>
00019
00020 namespace drizzled
00021 {
00022 namespace internal
00023 {
00024
00025 #define MAX_NEGATIVE_NUMBER ((uint64_t) 0x8000000000000000LL)
00026 #define INIT_CNT 9
00027 #define LFACTOR 1000000000ULL
00028 #define LFACTOR1 10000000000ULL
00029 #define LFACTOR2 100000000000ULL
00030
00031 static uint64_t lfactor[9]=
00032 {
00033 1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L, 100000000L
00034 };
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 int64_t my_strtoll10(const char *nptr, char **endptr, int *error)
00080 {
00081 const char *s, *end, *start, *n_end, *true_end;
00082 char *dummy;
00083 unsigned char c;
00084 unsigned long i, j, k;
00085 uint64_t li;
00086 int negative;
00087 uint64_t cutoff, cutoff2, cutoff3;
00088
00089 s= nptr;
00090
00091 if (endptr)
00092 {
00093 end= *endptr;
00094 while (s != end && (*s == ' ' || *s == '\t'))
00095 s++;
00096 if (s == end)
00097 goto no_conv;
00098 }
00099 else
00100 {
00101 endptr= &dummy;
00102 while (*s == ' ' || *s == '\t')
00103 s++;
00104 if (!*s)
00105 goto no_conv;
00106
00107 end= s+65535;
00108 }
00109
00110
00111 negative= 0;
00112 if (*s == '-')
00113 {
00114 *error= -1;
00115 negative= 1;
00116 if (++s == end)
00117 goto no_conv;
00118 cutoff= MAX_NEGATIVE_NUMBER / LFACTOR2;
00119 cutoff2= (MAX_NEGATIVE_NUMBER % LFACTOR2) / 100;
00120 cutoff3= MAX_NEGATIVE_NUMBER % 100;
00121 }
00122 else
00123 {
00124 *error= 0;
00125 if (*s == '+')
00126 {
00127 if (++s == end)
00128 goto no_conv;
00129 }
00130 cutoff= UINT64_MAX / LFACTOR2;
00131 cutoff2= UINT64_MAX % LFACTOR2 / 100;
00132 cutoff3= UINT64_MAX % 100;
00133 }
00134
00135
00136 if (*s == '0')
00137 {
00138 i= 0;
00139 do
00140 {
00141 if (++s == end)
00142 goto end_i;
00143 }
00144 while (*s == '0');
00145 n_end= s+ INIT_CNT;
00146 }
00147 else
00148 {
00149
00150 if ((c= (*s-'0')) > 9)
00151 goto no_conv;
00152 i= c;
00153 n_end= ++s+ INIT_CNT-1;
00154 }
00155
00156
00157 if (n_end > end)
00158 n_end= end;
00159 for (; s != n_end ; s++)
00160 {
00161 if ((c= (*s-'0')) > 9)
00162 goto end_i;
00163 i= i*10+c;
00164 }
00165 if (s == end)
00166 goto end_i;
00167
00168
00169 j= 0;
00170 start= s;
00171 n_end= true_end= s + INIT_CNT;
00172 if (n_end > end)
00173 n_end= end;
00174 do
00175 {
00176 if ((c= (*s-'0')) > 9)
00177 goto end_i_and_j;
00178 j= j*10+c;
00179 } while (++s != n_end);
00180 if (s == end)
00181 {
00182 if (s != true_end)
00183 goto end_i_and_j;
00184 goto end3;
00185 }
00186 if ((c= (*s-'0')) > 9)
00187 goto end3;
00188
00189
00190 k=c;
00191 if (++s == end || (c= (*s-'0')) > 9)
00192 goto end4;
00193 k= k*10+c;
00194 *endptr= (char*) ++s;
00195
00196
00197 if (s != end && (c= (*s-'0')) <= 9)
00198 goto overflow;
00199
00200
00201 if (i > cutoff || (i == cutoff && ((j > cutoff2 || j == cutoff2) &&
00202 k > cutoff3)))
00203 goto overflow;
00204 li=i*LFACTOR2+ (uint64_t) j*100 + k;
00205 return (int64_t) li;
00206
00207 overflow:
00208 *error= ERANGE;
00209 return negative ? INT64_MIN: INT64_MAX;
00210
00211 end_i:
00212 *endptr= (char*) s;
00213 return (negative ? ((int64_t) -(long) i) : (int64_t) i);
00214
00215 end_i_and_j:
00216 li= (uint64_t) i * lfactor[(unsigned int) (s-start)] + j;
00217 *endptr= (char*) s;
00218 return (negative ? -((int64_t) li) : (int64_t) li);
00219
00220 end3:
00221 li=(uint64_t) i*LFACTOR+ (uint64_t) j;
00222 *endptr= (char*) s;
00223 return (negative ? -((int64_t) li) : (int64_t) li);
00224
00225 end4:
00226 li=(uint64_t) i*LFACTOR1+ (uint64_t) j * 10 + k;
00227 *endptr= (char*) s;
00228 if (negative)
00229 {
00230 if (li > MAX_NEGATIVE_NUMBER)
00231 goto overflow;
00232 return -((int64_t) li);
00233 }
00234 return (int64_t) li;
00235
00236 no_conv:
00237
00238 *error= EDOM;
00239 *endptr= (char *) nptr;
00240 return 0;
00241 }
00242
00243 }
00244 }