~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mystrings/strto.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-09-13 01:03:01 UTC
  • mto: (1126.9.2 captain-20090915-01)
  • mto: This revision was merged to the branch mainline in revision 1133.
  • Revision ID: osullivan.padraig@gmail.com-20090913010301-tcvvezipx1124acy
Added calls to the dtrace delete begin/end probes.

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
}