Incorporating new faster string->number converter functions

into MY_CHARSET_INFO structure.
This commit is contained in:
unknown 2004-09-25 15:29:33 +05:00
commit 1325786818
13 changed files with 208 additions and 2 deletions

View file

@ -18,6 +18,7 @@
/* UCS2 support. Written by Alexander Barkov <bar@mysql.com> */
#include <my_global.h>
#include <my_sys.h>
#include "m_string.h"
#include "m_ctype.h"
#include <errno.h>
@ -852,7 +853,6 @@ bs:
return (negative ? -((longlong) res) : (longlong) res);
}
double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)),
char *nptr, uint length,
char **endptr, int *err)
@ -1000,6 +1000,188 @@ cnv:
}
#undef ULONGLONG_MAX
#define ULONGLONG_MAX (~(ulonglong) 0)
#define MAX_NEGATIVE_NUMBER ((ulonglong) LL(0x8000000000000000))
#define INIT_CNT 9
#define LFACTOR ULL(1000000000)
#define LFACTOR1 ULL(10000000000)
#define LFACTOR2 ULL(100000000000)
static unsigned long lfactor[9]=
{
1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L, 100000000L
};
longlong my_strtoll10_ucs2(CHARSET_INFO *cs __attribute__((unused)),
const char *nptr, char **endptr, int *error)
{
const char *s, *end, *start, *n_end, *true_end;
unsigned char c;
unsigned long i, j, k;
ulonglong li;
int negative;
ulong cutoff, cutoff2, cutoff3;
s= nptr;
/* If fixed length string */
if (endptr)
{
/* Make sure string length is even */
end= s + ((*endptr - s) / 2) * 2;
while (s < end && !s[0] && (s[1] == ' ' || s[1] == '\t'))
s+= 2;
if (s == end)
goto no_conv;
}
else
{
/* We don't support null terminated strings in UCS2 */
goto no_conv;
}
/* Check for a sign. */
negative= 0;
if (!s[0] && s[1] == '-')
{
*error= -1; /* Mark as negative number */
negative= 1;
s+= 2;
if (s == end)
goto no_conv;
cutoff= MAX_NEGATIVE_NUMBER / LFACTOR2;
cutoff2= (MAX_NEGATIVE_NUMBER % LFACTOR2) / 100;
cutoff3= MAX_NEGATIVE_NUMBER % 100;
}
else
{
*error= 0;
if (!s[0] && s[1] == '+')
{
s+= 2;
if (s == end)
goto no_conv;
}
cutoff= ULONGLONG_MAX / LFACTOR2;
cutoff2= ULONGLONG_MAX % LFACTOR2 / 100;
cutoff3= ULONGLONG_MAX % 100;
}
/* Handle case where we have a lot of pre-zero */
if (!s[0] && s[1] == '0')
{
i= 0;
do
{
s+= 2;
if (s == end)
goto end_i; /* Return 0 */
}
while (!s[0] && s[1] == '0');
n_end= s + 2 * INIT_CNT;
}
else
{
/* Read first digit to check that it's a valid number */
if (s[0] || (c= (s[1]-'0')) > 9)
goto no_conv;
i= c;
s+= 2;
n_end= s + 2 * (INIT_CNT-1);
}
/* Handle first 9 digits and store them in i */
if (n_end > end)
n_end= end;
for (; s != n_end ; s+= 2)
{
if (s[0] || (c= (s[1]-'0')) > 9)
goto end_i;
i= i*10+c;
}
if (s == end)
goto end_i;
/* Handle next 9 digits and store them in j */
j= 0;
start= s; /* Used to know how much to shift i */
n_end= true_end= s + 2 * INIT_CNT;
if (n_end > end)
n_end= end;
do
{
if (s[0] || (c= (s[1]-'0')) > 9)
goto end_i_and_j;
j= j*10+c;
s+= 2;
} while (s != n_end);
if (s == end)
{
if (s != true_end)
goto end_i_and_j;
goto end3;
}
if (s[0] || (c= (s[1]-'0')) > 9)
goto end3;
/* Handle the next 1 or 2 digits and store them in k */
k=c;
s+= 2;
if (s == end || s[0] || (c= (s[1]-'0')) > 9)
goto end4;
k= k*10+c;
s+= 2;
*endptr= (char*) s;
/* number string should have ended here */
if (s != end && !s[0] && (c= (s[1]-'0')) <= 9)
goto overflow;
/* Check that we didn't get an overflow with the last digit */
if (i > cutoff || (i == cutoff && ((j > cutoff2 || j == cutoff2) &&
k > cutoff3)))
goto overflow;
li=i*LFACTOR2+ (ulonglong) j*100 + k;
return (longlong) li;
overflow: /* *endptr is set here */
*error= MY_ERRNO_ERANGE;
return negative ? LONGLONG_MIN : (longlong) ULONGLONG_MAX;
end_i:
*endptr= (char*) s;
return (negative ? ((longlong) -(long) i) : (longlong) i);
end_i_and_j:
li= (ulonglong) i * lfactor[(uint) (s-start) / 2] + j;
*endptr= (char*) s;
return (negative ? -((longlong) li) : (longlong) li);
end3:
li=(ulonglong) i*LFACTOR+ (ulonglong) j;
*endptr= (char*) s;
return (negative ? -((longlong) li) : (longlong) li);
end4:
li=(ulonglong) i*LFACTOR1+ (ulonglong) j * 10 + k;
*endptr= (char*) s;
if (negative)
{
if (li > MAX_NEGATIVE_NUMBER)
goto overflow;
return -((longlong) li);
}
return (longlong) li;
no_conv:
/* There was no number to convert. */
*error= MY_ERRNO_EDOM;
*endptr= (char *) nptr;
return 0;
}
static
uint my_numchars_ucs2(CHARSET_INFO *cs __attribute__((unused)),
const char *b, const char *e)
@ -1439,6 +1621,7 @@ MY_CHARSET_HANDLER my_charset_ucs2_handler=
my_strntoll_ucs2,
my_strntoull_ucs2,
my_strntod_ucs2,
my_strtoll10_ucs2,
my_scan_8bit
};