mirror of
https://github.com/MariaDB/server.git
synced 2026-05-15 19:37:16 +02:00
Incorporating new faster string->number converter functions
into MY_CHARSET_INFO structure.
This commit is contained in:
parent
c0bb6a3882
commit
1325786818
13 changed files with 208 additions and 2 deletions
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue