diff options
author | unknown <bar@bar.mysql.r18.ru> | 2002-11-29 13:29:48 +0400 |
---|---|---|
committer | unknown <bar@bar.mysql.r18.ru> | 2002-11-29 13:29:48 +0400 |
commit | 4b0a6e6bcdda3d4b97c389cc5063a6afd520b0a0 (patch) | |
tree | b528e1e854cc3b19043313a8756eaef4cc36c035 | |
parent | 781a5bc81ad3fdd6111986a895e6025d6910773e (diff) | |
download | mariadb-git-4b0a6e6bcdda3d4b97c389cc5063a6afd520b0a0.tar.gz |
my_strntod_ucs2 and my_strntol_ucs2 fixes
-rw-r--r-- | strings/ctype-utf8.c | 210 |
1 files changed, 112 insertions, 98 deletions
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 8adeed7144a..c77dc871009 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -22,7 +22,7 @@ #include "m_string.h" #include "m_ctype.h" #include "my_sys.h" /* defines errno */ - +#include <errno.h> #ifdef HAVE_CHARSET_utf8 #define HAVE_UNIDATA @@ -2118,7 +2118,7 @@ static int my_ucs2_uni (CHARSET_INFO *cs __attribute__((unused)) , my_wc_t * pwc, const uchar *s, const uchar *e) { if (s+2 > e) /* Need 2 characters */ - return MY_CS_ILSEQ; + return MY_CS_TOOFEW(0); *pwc= ((unsigned char)s[0]) * 256 + ((unsigned char)s[1]); return 2; @@ -2441,118 +2441,114 @@ static int my_snprintf_ucs2(CHARSET_INFO *cs __attribute__((unused)) return my_vsnprintf_ucs2(to, n, fmt, args); } -#define MY_ERRNO(x) long my_strntol_ucs2(CHARSET_INFO *cs, const char *nptr, uint l, char **endptr, int base) { - int negative; - register ulong cutoff; + int negative=0; + int overflow; + int cnv; + my_wc_t wc; register unsigned int cutlim; - register ulong i; - register const char *s; - register unsigned char c; - const char *save, *e; - int overflow; + register ulong cutoff; + register ulong res; + register const char *s=nptr; + register const char *e=nptr+l; + const char *save; - if (base < 0 || base == 1 || base > 36) - base = 10; + do { + if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + { + switch (wc) + { + case ' ' : break; + case '\t': break; + case '-' : negative= !negative; break; + case '+' : break; + default : goto bs; + } + } + else /* No more characters or bad multibyte sequence */ + { + if (endptr !=NULL ) + *endptr = (char*)s; + my_errno = (cnv==MY_CS_ILSEQ) ? EILSEQ : EDOM; + return 0; + } + s+=cnv; + } while (1); - s = nptr; - e = nptr+l; +bs: - for ( ; s<e && my_isspace(cs, *s) ; s++); + if (base <= 0 || base == 1 || base > 36) + base = 10; - if (s == e) - { - goto noconv; - } + overflow = 0; + res = 0; + save = s; + cutoff = ((ulong)~0L) / (unsigned long int) base; + cutlim = (uint) (((ulong)~0L) % (unsigned long int) base); - /* Check for a sign. */ - if (*s == '-') - { - negative = 1; - ++s; - } - else if (*s == '+') - { - negative = 0; - ++s; - } - else - negative = 0; - - if (base == 16 && s[0] == '0' && my_toupper(cs,s[1]) == 'X') - s += 2; - - if (base == 0) - { - if (*s == '0') + do { + if ((cnv=cs->mb_wc(cs,&wc,s,e))>0) { - if (my_toupper(cs,s[1]) == 'X') + s+=cnv; + if ( wc>='0' && wc<='9') + wc -= '0'; + else if ( wc>='A' && wc<='Z') + wc = wc - 'A' + 10; + else if ( wc>='a' && wc<='z') + wc = wc - 'a' + 10; + else + break; + if ((int)wc >= base) + break; + if (res > cutoff || (res == cutoff && wc > cutlim)) + overflow = 1; + else { - s += 2; - base = 16; + res *= (ulong) base; + res += wc; } - else - base = 8; } - else - base = 10; - } - - save = s; - cutoff = ((ulong)~0L) / (unsigned long int) base; - cutlim = (uint) (((ulong)~0L) % (unsigned long int) base); - - overflow = 0; - i = 0; - for (c = *s; s != e; c = *++s) - { - if (my_isdigit(cs,c)) - c -= '0'; - else if (my_isalpha(cs,c)) - c = my_toupper(cs,c) - 'A' + 10; - else - break; - if (c >= base) - break; - if (i > cutoff || (i == cutoff && c > cutlim)) - overflow = 1; + else if (cnv==MY_CS_ILSEQ) + { + if (endptr !=NULL ) + *endptr = (char*)s; + my_errno=EILSEQ; + return 0; + } else { - i *= (ulong) base; - i += c; + /* No more characters */ + break; } - } - - if (s == save) - goto noconv; + } while(1); if (endptr != NULL) *endptr = (char *) s; + if (s == save) + { + my_errno=EDOM; + return 0L; + } + if (negative) { - if (i > (ulong) LONG_MIN) + if (res > (ulong) LONG_MIN) overflow = 1; } - else if (i > (ulong) LONG_MAX) + else if (res > (ulong) LONG_MAX) overflow = 1; if (overflow) { - MY_ERRNO(ERANGE); + my_errno=(ERANGE); return negative ? LONG_MIN : LONG_MAX; } - return (negative ? -((long) i) : (long) i); - -noconv: - MY_ERRNO(EDOM); - if (endptr != NULL) - *endptr = (char *) nptr; - return 0L; + return (negative ? -((long) res) : (long) res); } @@ -2646,14 +2642,14 @@ ulong my_strntoul_ucs2(CHARSET_INFO *cs, if (overflow) { - MY_ERRNO(ERANGE); + my_errno=(ERANGE); return ((ulong)~0L); } return (negative ? -((long) i) : (long) i); noconv: - MY_ERRNO(EDOM); + my_errno=(EDOM); if (endptr != NULL) *endptr = (char *) nptr; return 0L; @@ -2759,14 +2755,14 @@ longlong my_strntoll_ucs2(CHARSET_INFO *cs __attribute__((unused)), if (overflow) { - MY_ERRNO(ERANGE); + my_errno=(ERANGE); return negative ? LONGLONG_MIN : LONGLONG_MAX; } return (negative ? -((longlong) i) : (longlong) i); noconv: - MY_ERRNO(EDOM); + my_errno=(EDOM); if (endptr != NULL) *endptr = (char *) nptr; return 0L; @@ -2864,35 +2860,53 @@ ulonglong my_strntoull_ucs2(CHARSET_INFO *cs, if (overflow) { - MY_ERRNO(ERANGE); + my_errno=(ERANGE); return (~(ulonglong) 0); } return (negative ? -((longlong) i) : (longlong) i); noconv: - MY_ERRNO(EDOM); + my_errno=(EDOM); if (endptr != NULL) *endptr = (char *) nptr; return 0L; } double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *s, uint l, char **e) + const char *nptr, uint l, char **endptr) { - char buf[256]; - double res; + char buf[256]; + double res; + register char *b=buf; + register const char *s=nptr; + register const char *e=nptr+l; + my_wc_t wc; + int cnv; + if((l+1)>sizeof(buf)) { - if (e) - memcpy(*e,s,sizeof(s)); + if (endptr) + *endptr=(char*)nptr; + my_errno=ERANGE; return 0; } - strncpy(buf,s,l); - buf[l]='\0'; - res=strtod(buf,e); - if (e) - memcpy(*e,*e-buf+s,sizeof(s)); + + while ((cnv=cs->mb_wc(cs,&wc,s,e))>0) + { + s+=cnv; + if (wc < 128) + { + *b++=wc; + } + else + break; + } + *b='\0'; + + res=strtod(buf,endptr); + if (endptr) + *endptr=(char*) (*endptr-buf+nptr); return res; } |