~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 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
16
/*
17
  strtol,strtoul,strtoll,strtoull
481.1.3 by Monty Taylor
Replaced long long with int64_t.
18
  convert string to long, unsigned long, int64_t or uint64_t.
1 by brian
clean slate
19
  strtoxx(char *src,char **ptr,int base)
20
  converts the string pointed to by src to an long of appropriate long and
21
  returnes it. It skips leading spaces and tabs (but not newlines, formfeeds,
22
  backspaces), then it accepts an optional sign and a sequence of digits
23
  in the specified radix.
24
  If the value of ptr is not (char **)NULL, a pointer to the character
25
  terminating the scan is returned in the location pointed to by ptr.
26
  Trailing spaces will NOT be skipped.
27
28
  If an error is detected, the result will be LONG_MIN, 0 or LONG_MAX,
29
  (or LONGLONG..)  and errno will be set to
30
	EDOM	if there are no digits
31
	ERANGE	if the result would overflow.
32
  the ptr will be set to src.
33
  This file is based on the strtol from the the GNU C Library.
34
  it can be compiled with the UNSIGNED and/or LONGLONG flag set
35
*/
36
37
243.1.11 by Jay Pipes
* Added include guards in a couple places, and removed unecessary
38
#if !defined(DRIZZLE_SERVER_GLOBAL_H) || !defined(_m_string_h)
264.1.12 by Monty Taylor
Fixed ref to my_global.h in mystrings/longlong2str_asm.c.
39
#  error  Calling file must include 'drizzled/global.h' and 'mystrings/m_string.h'
1 by brian
clean slate
40
   /* see 'strtoll.c' and 'strtoull.c' for the reasons */
41
#endif
42
994.2.4 by Monty Taylor
Blast. Fixed some make distcheck issues.
43
#include "mysys/mysys_priv.h"
1 by brian
clean slate
44
45
#undef strtoull
46
#undef strtoll
47
#undef strtoul
48
#undef strtol
49
#ifdef USE_LONGLONG
50
#define TYPE_MIN LONGLONG_MIN
51
#define TYPE_MAX LONGLONG_MAX
152 by Brian Aker
longlong replacement
52
#define longtype int64_t
151 by Brian Aker
Ulonglong to uint64_t
53
#define ulongtype uint64_t
1 by brian
clean slate
54
#ifdef USE_UNSIGNED
55
#define function ulongtype strtoull
56
#else
57
#define function longtype strtoll
58
#endif
59
#else
60
#define TYPE_MIN LONG_MIN
61
#define TYPE_MAX LONG_MAX
62
#define longtype long
63
#define ulongtype unsigned long
64
#ifdef USE_UNSIGNED
65
#define function ulongtype strtoul
66
#else
67
#define function longtype strtol
68
#endif
69
#endif
70
71
72
/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
73
   If BASE is 0 the base is determined by the presence of a leading
74
   zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
75
   If BASE is < 2 or > 36, it is reset to 10.
76
   If ENDPTR is not NULL, a pointer to the character after the last
77
   one converted is stored in *ENDPTR.	*/
78
79
80
function (const char *nptr,char **endptr,int base)
81
{
82
  int negative;
83
  register ulongtype cutoff;
84
  register unsigned int cutlim;
85
  register ulongtype i;
86
  register const char *s;
481 by Brian Aker
Remove all of uchar.
87
  register unsigned char c;
1 by brian
clean slate
88
  const char *save;
89
  int overflow;
90
91
  if (base < 0 || base == 1 || base > 36)
92
    base = 10;
93
94
  s = nptr;
95
96
  /* Skip white space.	*/
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
97
  while (my_isspace(&my_charset_utf8_general_ci, *s))
1 by brian
clean slate
98
    ++s;
99
  if (*s == '\0')
100
  {
101
    goto noconv;
102
  }
103
104
  /* Check for a sign.	*/
105
  negative= 0;
106
  if (*s == '-')
107
  {
108
    negative = 1;
109
    ++s;
110
  }
111
  else if (*s == '+')
112
  {
113
    ++s;
114
  }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
115
1 by brian
clean slate
116
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
117
  if (base == 16 && s[0] == '0' && my_toupper (&my_charset_utf8_general_ci, s[1]) == 'X')
1 by brian
clean slate
118
    s += 2;
119
120
  /* If BASE is zero, figure it out ourselves.	*/
121
  if (base == 0)
122
  {
123
    if (*s == '0')
124
    {
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
125
      if (my_toupper (&my_charset_utf8_general_ci, s[1]) == 'X')
1 by brian
clean slate
126
      {
127
	s += 2;
128
	base = 16;
129
      }
130
      else
131
	base = 8;
132
    }
133
    else
134
      base = 10;
135
  }
136
137
  /* Save the pointer so we can check later if anything happened.  */
138
  save = s;
139
365.2.9 by Monty Taylor
Got rid of all instances of ~0
140
  cutoff = UINT64_MAX / (unsigned long int) base;
895 by Brian Aker
Completion (?) of uint conversion.
141
  cutlim = (uint32_t) (UINT64_MAX % (unsigned long int) base);
1 by brian
clean slate
142
143
  overflow = 0;
144
  i = 0;
145
  for (c = *s; c != '\0'; c = *++s)
146
  {
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
147
    if (my_isdigit (&my_charset_utf8_general_ci, c))
1 by brian
clean slate
148
      c -= '0';
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
149
    else if (my_isalpha (&my_charset_utf8_general_ci, c))
150
      c = my_toupper (&my_charset_utf8_general_ci, c) - 'A' + 10;
1 by brian
clean slate
151
    else
152
      break;
153
    if (c >= base)
154
      break;
155
    /* Check for overflow.  */
156
    if (i > cutoff || (i == cutoff && c > cutlim))
157
      overflow = 1;
158
    else
159
    {
160
      i *= (ulongtype) base;
161
      i += c;
162
    }
163
  }
164
165
  /* Check if anything actually happened.  */
166
  if (s == save)
167
    goto noconv;
168
169
  /* Store in ENDPTR the address of one character
170
     past the last character we converted.  */
171
  if (endptr != NULL)
172
    *endptr = (char *) s;
173
174
#ifndef USE_UNSIGNED
175
  /* Check for a value that is within the range of
176
     `unsigned long int', but outside the range of `long int'.	*/
177
  if (negative)
178
  {
179
    if (i  > (ulongtype) TYPE_MIN)
180
      overflow = 1;
181
  }
182
  else if (i > (ulongtype) TYPE_MAX)
183
    overflow = 1;
184
#endif
185
186
  if (overflow)
187
  {
188
    my_errno=ERANGE;
189
#ifdef USE_UNSIGNED
365.2.9 by Monty Taylor
Got rid of all instances of ~0
190
    return UINT64_MAX;
1 by brian
clean slate
191
#else
192
    return negative ? TYPE_MIN : TYPE_MAX;
193
#endif
194
  }
195
196
  /* Return the result of the appropriate sign.  */
197
  return (negative ? -((longtype) i) : (longtype) i);
198
199
noconv:
200
  /* There was no number to convert.  */
201
  my_errno=EDOM;
202
  if (endptr != NULL)
203
    *endptr = (char *) nptr;
204
  return 0L;
205
}