~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to strings/my_strtoll10.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
   along with this program; if not, write to the Free Software
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
 
#include "config.h"
17
 
#include "drizzled/internal/m_string.h"
18
 
#include <errno.h>
 
16
#include <my_global.h>
 
17
#include <my_sys.h>            /* Needed for MY_ERRNO_ERANGE */
 
18
#include <m_string.h>
19
19
 
20
 
#define MAX_NEGATIVE_NUMBER     ((uint64_t) 0x8000000000000000LL)
 
20
#undef  ULONGLONG_MAX
 
21
/*
 
22
  Needed under MetroWerks Compiler, since MetroWerks compiler does not
 
23
  properly handle a constant expression containing a mod operator
 
24
*/
 
25
#if defined(__NETWARE__) && defined(__MWERKS__) 
 
26
static ulonglong ulonglong_max= ~(ulonglong) 0;
 
27
#define ULONGLONG_MAX ulonglong_max
 
28
#else
 
29
#define ULONGLONG_MAX           (~(ulonglong) 0)
 
30
#endif /* __NETWARE__ && __MWERKS__ */
 
31
#define MAX_NEGATIVE_NUMBER     ((ulonglong) LL(0x8000000000000000))
21
32
#define INIT_CNT  9
22
 
#define LFACTOR   1000000000ULL
23
 
#define LFACTOR1  10000000000ULL
24
 
#define LFACTOR2  100000000000ULL
 
33
#define LFACTOR   ULL(1000000000)
 
34
#define LFACTOR1  ULL(10000000000)
 
35
#define LFACTOR2  ULL(100000000000)
25
36
 
26
 
static uint64_t lfactor[9]=
 
37
static unsigned long lfactor[9]=
27
38
{
28
39
  1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L, 100000000L
29
40
};
30
41
 
31
42
/*
32
 
  Convert a string to an to uint64_t integer value
33
 
 
 
43
  Convert a string to an to unsigned long long integer value
 
44
  
34
45
  SYNOPSYS
35
46
    my_strtoll10()
36
47
      nptr     in       pointer to the string to be converted
37
48
      endptr   in/out   pointer to the end of the string/
38
49
                        pointer to the stop character
39
50
      error    out      returned error code
40
 
 
 
51
 
41
52
  DESCRIPTION
42
53
    This function takes the decimal representation of integer number
43
54
    from string nptr and converts it to an signed or unsigned
44
 
    int64_t value.
 
55
    long long integer value.
45
56
    Space characters and tab are ignored.
46
57
    A sign character might precede the digit characters. The number
47
58
    may have any number of pre-zero digits.
49
60
    The function stops reading the string nptr at the first character
50
61
    that is not a decimal digit. If endptr is not NULL then the function
51
62
    will not read characters after *endptr.
52
 
 
 
63
 
53
64
  RETURN VALUES
54
 
    Value of string as a signed/unsigned int64_t integer
 
65
    Value of string as a signed/unsigned longlong integer
55
66
 
56
67
    if no error and endptr != NULL, it will be set to point at the character
57
68
    after the number
60
71
    -1          Number was an ok negative number
61
72
    0           ok
62
73
    ERANGE      If the the value of the converted number exceeded the
63
 
                maximum negative/uint64_t integer.
64
 
                In this case the return value is UINT64_MAX if value was
65
 
                positive and UINT64_MIN if value was negative.
 
74
                maximum negative/unsigned long long integer.
 
75
                In this case the return value is ~0 if value was
 
76
                positive and LONGLONG_MIN if value was negative.
66
77
    EDOM        If the string didn't contain any digits. In this case
67
78
                the return value is 0.
68
79
 
71
82
*/
72
83
 
73
84
 
74
 
int64_t my_strtoll10(const char *nptr, char **endptr, int *error)
 
85
longlong my_strtoll10(const char *nptr, char **endptr, int *error)
75
86
{
76
87
  const char *s, *end, *start, *n_end, *true_end;
77
88
  char *dummy;
78
 
  unsigned char c;
 
89
  uchar c;
79
90
  unsigned long i, j, k;
80
 
  uint64_t li;
 
91
  ulonglong li;
81
92
  int negative;
82
 
  uint64_t cutoff, cutoff2, cutoff3;
 
93
  ulong cutoff, cutoff2, cutoff3;
83
94
 
84
95
  s= nptr;
85
96
  /* If fixed length string */
122
133
      if (++s == end)
123
134
        goto no_conv;
124
135
    }
125
 
    cutoff=  UINT64_MAX / LFACTOR2;
126
 
    cutoff2= UINT64_MAX % LFACTOR2 / 100;
127
 
    cutoff3=  UINT64_MAX % 100;
 
136
    cutoff=  ULONGLONG_MAX / LFACTOR2;
 
137
    cutoff2= ULONGLONG_MAX % LFACTOR2 / 100;
 
138
    cutoff3=  ULONGLONG_MAX % 100;
128
139
  }
129
140
 
130
141
  /* Handle case where we have a lot of pre-zero */
196
207
  if (i > cutoff || (i == cutoff && ((j > cutoff2 || j == cutoff2) &&
197
208
                                     k > cutoff3)))
198
209
    goto overflow;
199
 
  li=i*LFACTOR2+ (uint64_t) j*100 + k;
200
 
  return (int64_t) li;
 
210
  li=i*LFACTOR2+ (ulonglong) j*100 + k;
 
211
  return (longlong) li;
201
212
 
202
213
overflow:                                       /* *endptr is set here */
203
 
  *error= ERANGE;
204
 
  return negative ? INT64_MIN: INT64_MAX;
 
214
  *error= MY_ERRNO_ERANGE;
 
215
  return negative ? LONGLONG_MIN : (longlong) ULONGLONG_MAX;
205
216
 
206
217
end_i:
207
218
  *endptr= (char*) s;
208
 
  return (negative ? ((int64_t) -(long) i) : (int64_t) i);
 
219
  return (negative ? ((longlong) -(long) i) : (longlong) i);
209
220
 
210
221
end_i_and_j:
211
 
  li= (uint64_t) i * lfactor[(unsigned int) (s-start)] + j;
 
222
  li= (ulonglong) i * lfactor[(uint) (s-start)] + j;
212
223
  *endptr= (char*) s;
213
 
  return (negative ? -((int64_t) li) : (int64_t) li);
 
224
  return (negative ? -((longlong) li) : (longlong) li);
214
225
 
215
226
end3:
216
 
  li=(uint64_t) i*LFACTOR+ (uint64_t) j;
 
227
  li=(ulonglong) i*LFACTOR+ (ulonglong) j;
217
228
  *endptr= (char*) s;
218
 
  return (negative ? -((int64_t) li) : (int64_t) li);
 
229
  return (negative ? -((longlong) li) : (longlong) li);
219
230
 
220
231
end4:
221
 
  li=(uint64_t) i*LFACTOR1+ (uint64_t) j * 10 + k;
 
232
  li=(ulonglong) i*LFACTOR1+ (ulonglong) j * 10 + k;
222
233
  *endptr= (char*) s;
223
234
  if (negative)
224
235
  {
225
236
   if (li > MAX_NEGATIVE_NUMBER)
226
237
     goto overflow;
227
 
   return -((int64_t) li);
 
238
   return -((longlong) li);
228
239
  }
229
 
  return (int64_t) li;
 
240
  return (longlong) li;
230
241
 
231
242
no_conv:
232
243
  /* There was no number to convert.  */
233
 
  *error= EDOM;
 
244
  *error= MY_ERRNO_EDOM;
234
245
  *endptr= (char *) nptr;
235
246
  return 0;
236
247
}