~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2003 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
685.1.3 by Monty Taylor
Turned off stdinc - and then fixed the carnage.
16
#include <drizzled/global.h>
17
#include <mystrings/m_string.h>
236.1.27 by Monty Taylor
Some cleanups/decoupling in mystring.
18
#include <errno.h>
1 by brian
clean slate
19
151 by Brian Aker
Ulonglong to uint64_t
20
#define MAX_NEGATIVE_NUMBER	((uint64_t) 0x8000000000000000LL)
1 by brian
clean slate
21
#define INIT_CNT  9
80.1.1 by Brian Aker
LL() cleanup
22
#define LFACTOR   1000000000ULL
23
#define LFACTOR1  10000000000ULL
24
#define LFACTOR2  100000000000ULL
1 by brian
clean slate
25
507 by Brian Aker
Dead code around unsigned (first pass)
26
static uint64_t lfactor[9]=
1 by brian
clean slate
27
{
28
  1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L, 100000000L
29
};
30
31
/*
481.1.2 by Monty Taylor
Replaced all unsigned long long with uint64_t.
32
  Convert a string to an to uint64_t integer value
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
33
1 by brian
clean slate
34
  SYNOPSYS
35
    my_strtoll10()
36
      nptr     in       pointer to the string to be converted
37
      endptr   in/out   pointer to the end of the string/
38
                        pointer to the stop character
39
      error    out      returned error code
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
40
1 by brian
clean slate
41
  DESCRIPTION
42
    This function takes the decimal representation of integer number
43
    from string nptr and converts it to an signed or unsigned
481.1.3 by Monty Taylor
Replaced long long with int64_t.
44
    int64_t value.
1 by brian
clean slate
45
    Space characters and tab are ignored.
46
    A sign character might precede the digit characters. The number
47
    may have any number of pre-zero digits.
48
49
    The function stops reading the string nptr at the first character
50
    that is not a decimal digit. If endptr is not NULL then the function
51
    will not read characters after *endptr.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
52
1 by brian
clean slate
53
  RETURN VALUES
152 by Brian Aker
longlong replacement
54
    Value of string as a signed/unsigned int64_t integer
1 by brian
clean slate
55
56
    if no error and endptr != NULL, it will be set to point at the character
57
    after the number
58
59
    The error parameter contains information how things went:
60
    -1		Number was an ok negative number
61
    0	 	ok
62
    ERANGE	If the the value of the converted number exceeded the
481.1.2 by Monty Taylor
Replaced all unsigned long long with uint64_t.
63
	        maximum negative/uint64_t integer.
365.2.9 by Monty Taylor
Got rid of all instances of ~0
64
		In this case the return value is UINT64_MAX if value was
65
		positive and UINT64_MIN if value was negative.
1 by brian
clean slate
66
    EDOM	If the string didn't contain any digits. In this case
67
    		the return value is 0.
68
69
    If endptr is not NULL the function will store the end pointer to
70
    the stop character here.
71
*/
72
73
152 by Brian Aker
longlong replacement
74
int64_t my_strtoll10(const char *nptr, char **endptr, int *error)
1 by brian
clean slate
75
{
76
  const char *s, *end, *start, *n_end, *true_end;
77
  char *dummy;
236.1.27 by Monty Taylor
Some cleanups/decoupling in mystring.
78
  unsigned char c;
1 by brian
clean slate
79
  unsigned long i, j, k;
151 by Brian Aker
Ulonglong to uint64_t
80
  uint64_t li;
1 by brian
clean slate
81
  int negative;
632.1.10 by Monty Taylor
Got rid of Sun Studio warnings.
82
  uint64_t cutoff, cutoff2, cutoff3;
1 by brian
clean slate
83
84
  s= nptr;
85
  /* If fixed length string */
86
  if (endptr)
87
  {
88
    end= *endptr;
89
    while (s != end && (*s == ' ' || *s == '\t'))
90
      s++;
91
    if (s == end)
92
      goto no_conv;
93
  }
94
  else
95
  {
96
    endptr= &dummy;				/* Easier end test */
97
    while (*s == ' ' || *s == '\t')
98
      s++;
99
    if (!*s)
100
      goto no_conv;
101
    /* This number must be big to guard against a lot of pre-zeros */
102
    end= s+65535;				/* Can't be longer than this */
103
  }
104
105
  /* Check for a sign.	*/
106
  negative= 0;
107
  if (*s == '-')
108
  {
109
    *error= -1;					/* Mark as negative number */
110
    negative= 1;
111
    if (++s == end)
112
      goto no_conv;
113
    cutoff=  MAX_NEGATIVE_NUMBER / LFACTOR2;
114
    cutoff2= (MAX_NEGATIVE_NUMBER % LFACTOR2) / 100;
115
    cutoff3=  MAX_NEGATIVE_NUMBER % 100;
116
  }
117
  else
118
  {
119
    *error= 0;
120
    if (*s == '+')
121
    {
122
      if (++s == end)
123
	goto no_conv;
124
    }
365.2.9 by Monty Taylor
Got rid of all instances of ~0
125
    cutoff=  UINT64_MAX / LFACTOR2;
126
    cutoff2= UINT64_MAX % LFACTOR2 / 100;
127
    cutoff3=  UINT64_MAX % 100;
1 by brian
clean slate
128
  }
129
130
  /* Handle case where we have a lot of pre-zero */
131
  if (*s == '0')
132
  {
133
    i= 0;
134
    do
135
    {
136
      if (++s == end)
137
	goto end_i;				/* Return 0 */
138
    }
139
    while (*s == '0');
140
    n_end= s+ INIT_CNT;
141
  }
142
  else
143
  {
144
    /* Read first digit to check that it's a valid number */
145
    if ((c= (*s-'0')) > 9)
146
      goto no_conv;
147
    i= c;
148
    n_end= ++s+ INIT_CNT-1;
149
  }
150
151
  /* Handle first 9 digits and store them in i */
152
  if (n_end > end)
153
    n_end= end;
154
  for (; s != n_end ; s++)
155
  {
156
    if ((c= (*s-'0')) > 9)
157
      goto end_i;
158
    i= i*10+c;
159
  }
160
  if (s == end)
161
    goto end_i;
162
163
  /* Handle next 9 digits and store them in j */
164
  j= 0;
165
  start= s;				/* Used to know how much to shift i */
166
  n_end= true_end= s + INIT_CNT;
167
  if (n_end > end)
168
    n_end= end;
169
  do
170
  {
171
    if ((c= (*s-'0')) > 9)
172
      goto end_i_and_j;
173
    j= j*10+c;
174
  } while (++s != n_end);
175
  if (s == end)
176
  {
177
    if (s != true_end)
178
      goto end_i_and_j;
179
    goto end3;
180
  }
181
  if ((c= (*s-'0')) > 9)
182
    goto end3;
183
184
  /* Handle the next 1 or 2 digits and store them in k */
185
  k=c;
186
  if (++s == end || (c= (*s-'0')) > 9)
187
    goto end4;
188
  k= k*10+c;
189
  *endptr= (char*) ++s;
190
191
  /* number string should have ended here */
192
  if (s != end && (c= (*s-'0')) <= 9)
193
    goto overflow;
194
195
  /* Check that we didn't get an overflow with the last digit */
196
  if (i > cutoff || (i == cutoff && ((j > cutoff2 || j == cutoff2) &&
197
                                     k > cutoff3)))
198
    goto overflow;
151 by Brian Aker
Ulonglong to uint64_t
199
  li=i*LFACTOR2+ (uint64_t) j*100 + k;
152 by Brian Aker
longlong replacement
200
  return (int64_t) li;
1 by brian
clean slate
201
202
overflow:					/* *endptr is set here */
236.1.27 by Monty Taylor
Some cleanups/decoupling in mystring.
203
  *error= ERANGE;
365.2.9 by Monty Taylor
Got rid of all instances of ~0
204
  return negative ? INT64_MIN: INT64_MAX;
1 by brian
clean slate
205
206
end_i:
207
  *endptr= (char*) s;
152 by Brian Aker
longlong replacement
208
  return (negative ? ((int64_t) -(long) i) : (int64_t) i);
1 by brian
clean slate
209
210
end_i_and_j:
236.1.27 by Monty Taylor
Some cleanups/decoupling in mystring.
211
  li= (uint64_t) i * lfactor[(unsigned int) (s-start)] + j;
1 by brian
clean slate
212
  *endptr= (char*) s;
152 by Brian Aker
longlong replacement
213
  return (negative ? -((int64_t) li) : (int64_t) li);
1 by brian
clean slate
214
215
end3:
151 by Brian Aker
Ulonglong to uint64_t
216
  li=(uint64_t) i*LFACTOR+ (uint64_t) j;
1 by brian
clean slate
217
  *endptr= (char*) s;
152 by Brian Aker
longlong replacement
218
  return (negative ? -((int64_t) li) : (int64_t) li);
1 by brian
clean slate
219
220
end4:
151 by Brian Aker
Ulonglong to uint64_t
221
  li=(uint64_t) i*LFACTOR1+ (uint64_t) j * 10 + k;
1 by brian
clean slate
222
  *endptr= (char*) s;
223
  if (negative)
224
  {
225
   if (li > MAX_NEGATIVE_NUMBER)
226
     goto overflow;
152 by Brian Aker
longlong replacement
227
   return -((int64_t) li);
1 by brian
clean slate
228
  }
152 by Brian Aker
longlong replacement
229
  return (int64_t) li;
1 by brian
clean slate
230
231
no_conv:
232
  /* There was no number to convert.  */
236.1.27 by Monty Taylor
Some cleanups/decoupling in mystring.
233
  *error= EDOM;
1 by brian
clean slate
234
  *endptr= (char *) nptr;
235
  return 0;
236
}