~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mystrings/strto.cc

Remove PLUGIN and MODULES.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
18
 
  convert string to long, unsigned long, int64_t or uint64_t.
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
 
 
38
 
#if !defined(DRIZZLE_SERVER_GLOBAL_H) || !defined(_m_string_h)
39
 
#  error  Calling file must include 'drizzled/global.h' and 'mystrings/m_string.h'
40
 
   /* see 'strtoll.c' and 'strtoull.c' for the reasons */
41
 
#endif
42
 
 
43
 
#include "mysys/mysys_priv.h"
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
52
 
#define longtype int64_t
53
 
#define ulongtype uint64_t
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;
87
 
  register unsigned char c;
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.  */
97
 
  while (my_isspace(&my_charset_utf8_general_ci, *s))
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
 
  }
115
 
 
116
 
 
117
 
  if (base == 16 && s[0] == '0' && my_toupper (&my_charset_utf8_general_ci, s[1]) == 'X')
118
 
    s += 2;
119
 
 
120
 
  /* If BASE is zero, figure it out ourselves.  */
121
 
  if (base == 0)
122
 
  {
123
 
    if (*s == '0')
124
 
    {
125
 
      if (my_toupper (&my_charset_utf8_general_ci, s[1]) == 'X')
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
 
 
140
 
  cutoff = UINT64_MAX / (unsigned long int) base;
141
 
  cutlim = (uint32_t) (UINT64_MAX % (unsigned long int) base);
142
 
 
143
 
  overflow = 0;
144
 
  i = 0;
145
 
  for (c = *s; c != '\0'; c = *++s)
146
 
  {
147
 
    if (my_isdigit (&my_charset_utf8_general_ci, c))
148
 
      c -= '0';
149
 
    else if (my_isalpha (&my_charset_utf8_general_ci, c))
150
 
      c = my_toupper (&my_charset_utf8_general_ci, c) - 'A' + 10;
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
190
 
    return UINT64_MAX;
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
 
}