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