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