ctype-simple.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:27k
- /* Copyright (C) 2002 MySQL AB
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
- #include <my_global.h>
- #include "m_string.h"
- #include "m_ctype.h"
- #include <errno.h>
- #include "stdarg.h"
- /*
- Converts a string into its sort key.
-
- SYNOPSIS
- my_strnxfrm_xxx()
-
- IMPLEMENTATION
-
- The my_strxfrm_xxx() function transforms a string pointed to by
- 'src' with length 'srclen' according to the charset+collation
- pair 'cs' and copies the result key into 'dest'.
-
- Comparing two strings using memcmp() after my_strnxfrm_xxx()
- is equal to comparing two original strings with my_strnncollsp_xxx().
-
- Not more than 'dstlen' bytes are written into 'dst'.
- To garantee that the whole string is transformed, 'dstlen' must be
- at least srclen*cs->strnxfrm_multiply bytes long. Otherwise,
- consequent memcmp() may return a non-accurate result.
-
- If the source string is too short to fill whole 'dstlen' bytes,
- then the 'dest' string is padded up to 'dstlen', ensuring that:
-
- "a" == "a "
- "a " < "a"
- "a " < "a "
-
- my_strnxfrm_simple() is implemented for 8bit charsets and
- simple collations with one-to-one string->key transformation.
-
- See also implementations for various charsets/collations in
- other ctype-xxx.c files.
-
- RETURN
-
- Target len 'dstlen'.
-
- */
- int my_strnxfrm_simple(CHARSET_INFO * cs,
- uchar *dest, uint len,
- const uchar *src, uint srclen)
- {
- uchar *map= cs->sort_order;
- uint dstlen= len;
- set_if_smaller(len, srclen);
- if (dest != src)
- {
- const uchar *end;
- for ( end=src+len; src < end ; )
- *dest++= map[*src++];
- }
- else
- {
- const uchar *end;
- for ( end=dest+len; dest < end ; dest++)
- *dest= (char) map[(uchar) *dest];
- }
- if (dstlen > len)
- bfill(dest, dstlen - len, ' ');
- return dstlen;
- }
- int my_strnncoll_simple(CHARSET_INFO * cs, const uchar *s, uint slen,
- const uchar *t, uint tlen,
- my_bool t_is_prefix)
- {
- int len = ( slen > tlen ) ? tlen : slen;
- uchar *map= cs->sort_order;
- if (t_is_prefix && slen > tlen)
- slen=tlen;
- while (len--)
- {
- if (map[*s++] != map[*t++])
- return ((int) map[s[-1]] - (int) map[t[-1]]);
- }
- return (int) (slen - tlen);
- }
- /*
- Compare strings, discarding end space
- SYNOPSIS
- my_strnncollsp_simple()
- cs character set handler
- a First string to compare
- a_length Length of 'a'
- b Second string to compare
- b_length Length of 'b'
- IMPLEMENTATION
- If one string is shorter as the other, then we space extend the other
- so that the strings have equal length.
- This will ensure that the following things hold:
- "a" == "a "
- "a " < "a"
- "a " < "a "
- RETURN
- < 0 a < b
- = 0 a == b
- > 0 a > b
- */
- int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
- const uchar *b, uint b_length)
- {
- const uchar *map= cs->sort_order, *end;
- uint length;
- end= a + (length= min(a_length, b_length));
- while (a < end)
- {
- if (map[*a++] != map[*b++])
- return ((int) map[a[-1]] - (int) map[b[-1]]);
- }
- if (a_length != b_length)
- {
- int swap= 1;
- /*
- Check the next not space character of the longer key. If it's < ' ',
- then it's smaller than the other key.
- */
- if (a_length < b_length)
- {
- /* put shorter key in s */
- a_length= b_length;
- a= b;
- swap= -1; /* swap sign of result */
- }
- for (end= a + a_length-length; a < end ; a++)
- {
- if (*a != ' ')
- return (*a < ' ') ? -swap : swap;
- }
- }
- return 0;
- }
- void my_caseup_str_8bit(CHARSET_INFO * cs,char *str)
- {
- register uchar *map=cs->to_upper;
- while ((*str = (char) map[(uchar) *str]) != 0)
- str++;
- }
- void my_casedn_str_8bit(CHARSET_INFO * cs,char *str)
- {
- register uchar *map=cs->to_lower;
- while ((*str = (char) map[(uchar)*str]) != 0)
- str++;
- }
- void my_caseup_8bit(CHARSET_INFO * cs, char *str, uint length)
- {
- register uchar *map=cs->to_upper;
- for ( ; length>0 ; length--, str++)
- *str= (char) map[(uchar)*str];
- }
- void my_casedn_8bit(CHARSET_INFO * cs, char *str, uint length)
- {
- register uchar *map=cs->to_lower;
- for ( ; length>0 ; length--, str++)
- *str= (char) map[(uchar) *str];
- }
- int my_strcasecmp_8bit(CHARSET_INFO * cs,const char *s, const char *t)
- {
- register uchar *map=cs->to_upper;
- while (map[(uchar) *s] == map[(uchar) *t++])
- if (!*s++) return 0;
- return ((int) map[(uchar) s[0]] - (int) map[(uchar) t[-1]]);
- }
- int my_mb_wc_8bit(CHARSET_INFO *cs,my_wc_t *wc,
- const unsigned char *str,
- const unsigned char *end __attribute__((unused)))
- {
- if (str >= end)
- return MY_CS_TOOFEW(0);
-
- *wc=cs->tab_to_uni[*str];
- return (!wc[0] && str[0]) ? MY_CS_ILSEQ : 1;
- }
- int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc,
- unsigned char *str,
- unsigned char *end __attribute__((unused)))
- {
- MY_UNI_IDX *idx;
- if (str >= end)
- return MY_CS_TOOSMALL;
-
- for (idx=cs->tab_from_uni; idx->tab ; idx++)
- {
- if (idx->from <= wc && idx->to >= wc)
- {
- str[0]= idx->tab[wc - idx->from];
- return (!str[0] && wc) ? MY_CS_ILUNI : 1;
- }
- }
- return MY_CS_ILUNI;
- }
- /*
- We can't use vsprintf here as it's not guaranteed to return
- the length on all operating systems.
- This function is also not called in a safe environment, so the
- end buffer must be checked.
- */
- int my_snprintf_8bit(CHARSET_INFO *cs __attribute__((unused)),
- char* to, uint n __attribute__((unused)),
- const char* fmt, ...)
- {
- va_list args;
- int result;
- va_start(args,fmt);
- result= my_vsnprintf(to, n, fmt, args);
- va_end(args);
- return result;
- }
- void my_hash_sort_simple(CHARSET_INFO *cs,
- const uchar *key, uint len,
- ulong *nr1, ulong *nr2)
- {
- register uchar *sort_order=cs->sort_order;
- const uchar *pos = key;
-
- key+= len;
-
- for (; pos < (uchar*) key ; pos++)
- {
- nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
- ((uint) sort_order[(uint) *pos])) + (nr1[0] << 8);
- nr2[0]+=3;
- }
- }
- long my_strntol_8bit(CHARSET_INFO *cs,
- const char *nptr, uint l, int base,
- char **endptr, int *err)
- {
- int negative;
- register uint32 cutoff;
- register unsigned int cutlim;
- register uint32 i;
- register const char *s;
- register unsigned char c;
- const char *save, *e;
- int overflow;
- *err= 0; /* Initialize error indicator */
- #ifdef NOT_USED
- if (base < 0 || base == 1 || base > 36)
- base = 10;
- #endif
- s = nptr;
- e = nptr+l;
-
- for ( ; s<e && my_isspace(cs, *s) ; s++);
-
- if (s == e)
- {
- goto noconv;
- }
-
- /* Check for a sign. */
- if (*s == '-')
- {
- negative = 1;
- ++s;
- }
- else if (*s == '+')
- {
- negative = 0;
- ++s;
- }
- else
- negative = 0;
- #ifdef NOT_USED
- if (base == 16 && s[0] == '0' && (s[1]=='X' || s[1]=='x'))
- s += 2;
- #endif
- #ifdef NOT_USED
- if (base == 0)
- {
- if (*s == '0')
- {
- if (s[1]=='X' || s[1]=='x')
- {
- s += 2;
- base = 16;
- }
- else
- base = 8;
- }
- else
- base = 10;
- }
- #endif
- save = s;
- cutoff = ((uint32)~0L) / (uint32) base;
- cutlim = (uint) (((uint32)~0L) % (uint32) base);
- overflow = 0;
- i = 0;
- for (c = *s; s != e; c = *++s)
- {
- if (c>='0' && c<='9')
- c -= '0';
- else if (c>='A' && c<='Z')
- c = c - 'A' + 10;
- else if (c>='a' && c<='z')
- c = c - 'a' + 10;
- else
- break;
- if (c >= base)
- break;
- if (i > cutoff || (i == cutoff && c > cutlim))
- overflow = 1;
- else
- {
- i *= (uint32) base;
- i += c;
- }
- }
-
- if (s == save)
- goto noconv;
-
- if (endptr != NULL)
- *endptr = (char *) s;
-
- if (negative)
- {
- if (i > (uint32) INT_MIN32)
- overflow = 1;
- }
- else if (i > INT_MAX32)
- overflow = 1;
-
- if (overflow)
- {
- err[0]= ERANGE;
- return negative ? INT_MIN32 : INT_MAX32;
- }
-
- return (negative ? -((long) i) : (long) i);
- noconv:
- err[0]= EDOM;
- if (endptr != NULL)
- *endptr = (char *) nptr;
- return 0L;
- }
- ulong my_strntoul_8bit(CHARSET_INFO *cs,
- const char *nptr, uint l, int base,
- char **endptr, int *err)
- {
- int negative;
- register uint32 cutoff;
- register unsigned int cutlim;
- register uint32 i;
- register const char *s;
- register unsigned char c;
- const char *save, *e;
- int overflow;
- *err= 0; /* Initialize error indicator */
- #ifdef NOT_USED
- if (base < 0 || base == 1 || base > 36)
- base = 10;
- #endif
- s = nptr;
- e = nptr+l;
-
- for( ; s<e && my_isspace(cs, *s); s++);
-
- if (s==e)
- {
- goto noconv;
- }
- if (*s == '-')
- {
- negative = 1;
- ++s;
- }
- else if (*s == '+')
- {
- negative = 0;
- ++s;
- }
- else
- negative = 0;
- #ifdef NOT_USED
- if (base == 16 && s[0] == '0' && (s[1]=='X' || s[1]=='x'))
- s += 2;
- #endif
- #ifdef NOT_USED
- if (base == 0)
- {
- if (*s == '0')
- {
- if (s[1]=='X' || s[1]=='x')
- {
- s += 2;
- base = 16;
- }
- else
- base = 8;
- }
- else
- base = 10;
- }
- #endif
- save = s;
- cutoff = ((uint32)~0L) / (uint32) base;
- cutlim = (uint) (((uint32)~0L) % (uint32) base);
- overflow = 0;
- i = 0;
-
- for (c = *s; s != e; c = *++s)
- {
- if (c>='0' && c<='9')
- c -= '0';
- else if (c>='A' && c<='Z')
- c = c - 'A' + 10;
- else if (c>='a' && c<='z')
- c = c - 'a' + 10;
- else
- break;
- if (c >= base)
- break;
- if (i > cutoff || (i == cutoff && c > cutlim))
- overflow = 1;
- else
- {
- i *= (uint32) base;
- i += c;
- }
- }
- if (s == save)
- goto noconv;
- if (endptr != NULL)
- *endptr = (char *) s;
- if (overflow)
- {
- err[0]= ERANGE;
- return (~(uint32) 0);
- }
-
- return (negative ? -((long) i) : (long) i);
-
- noconv:
- err[0]= EDOM;
- if (endptr != NULL)
- *endptr = (char *) nptr;
- return 0L;
- }
- longlong my_strntoll_8bit(CHARSET_INFO *cs __attribute__((unused)),
- const char *nptr, uint l, int base,
- char **endptr,int *err)
- {
- int negative;
- register ulonglong cutoff;
- register unsigned int cutlim;
- register ulonglong i;
- register const char *s, *e;
- const char *save;
- int overflow;
- *err= 0; /* Initialize error indicator */
- #ifdef NOT_USED
- if (base < 0 || base == 1 || base > 36)
- base = 10;
- #endif
- s = nptr;
- e = nptr+l;
- for(; s<e && my_isspace(cs,*s); s++);
- if (s == e)
- {
- goto noconv;
- }
- if (*s == '-')
- {
- negative = 1;
- ++s;
- }
- else if (*s == '+')
- {
- negative = 0;
- ++s;
- }
- else
- negative = 0;
- #ifdef NOT_USED
- if (base == 16 && s[0] == '0' && (s[1]=='X'|| s[1]=='x'))
- s += 2;
- #endif
- #ifdef NOT_USED
- if (base == 0)
- {
- if (*s == '0')
- {
- if (s[1]=='X' || s[1]=='x')
- {
- s += 2;
- base = 16;
- }
- else
- base = 8;
- }
- else
- base = 10;
- }
- #endif
- save = s;
- cutoff = (~(ulonglong) 0) / (unsigned long int) base;
- cutlim = (uint) ((~(ulonglong) 0) % (unsigned long int) base);
- overflow = 0;
- i = 0;
- for ( ; s != e; s++)
- {
- register unsigned char c= *s;
- if (c>='0' && c<='9')
- c -= '0';
- else if (c>='A' && c<='Z')
- c = c - 'A' + 10;
- else if (c>='a' && c<='z')
- c = c - 'a' + 10;
- else
- break;
- if (c >= base)
- break;
- if (i > cutoff || (i == cutoff && c > cutlim))
- overflow = 1;
- else
- {
- i *= (ulonglong) base;
- i += c;
- }
- }
- if (s == save)
- goto noconv;
- if (endptr != NULL)
- *endptr = (char *) s;
- if (negative)
- {
- if (i > (ulonglong) LONGLONG_MIN)
- overflow = 1;
- }
- else if (i > (ulonglong) LONGLONG_MAX)
- overflow = 1;
- if (overflow)
- {
- err[0]= ERANGE;
- return negative ? LONGLONG_MIN : LONGLONG_MAX;
- }
- return (negative ? -((longlong) i) : (longlong) i);
- noconv:
- err[0]= EDOM;
- if (endptr != NULL)
- *endptr = (char *) nptr;
- return 0L;
- }
- ulonglong my_strntoull_8bit(CHARSET_INFO *cs,
- const char *nptr, uint l, int base,
- char **endptr, int *err)
- {
- int negative;
- register ulonglong cutoff;
- register unsigned int cutlim;
- register ulonglong i;
- register const char *s, *e;
- const char *save;
- int overflow;
- *err= 0; /* Initialize error indicator */
- #ifdef NOT_USED
- if (base < 0 || base == 1 || base > 36)
- base = 10;
- #endif
- s = nptr;
- e = nptr+l;
- for(; s<e && my_isspace(cs,*s); s++);
- if (s == e)
- {
- goto noconv;
- }
- if (*s == '-')
- {
- negative = 1;
- ++s;
- }
- else if (*s == '+')
- {
- negative = 0;
- ++s;
- }
- else
- negative = 0;
- #ifdef NOT_USED
- if (base == 16 && s[0] == '0' && (s[1]=='X' || s[1]=='x'))
- s += 2;
- #endif
- #ifdef NOT_USED
- if (base == 0)
- {
- if (*s == '0')
- {
- if (s[1]=='X' || s[1]=='x')
- {
- s += 2;
- base = 16;
- }
- else
- base = 8;
- }
- else
- base = 10;
- }
- #endif
- save = s;
- cutoff = (~(ulonglong) 0) / (unsigned long int) base;
- cutlim = (uint) ((~(ulonglong) 0) % (unsigned long int) base);
- overflow = 0;
- i = 0;
- for ( ; s != e; s++)
- {
- register unsigned char c= *s;
- if (c>='0' && c<='9')
- c -= '0';
- else if (c>='A' && c<='Z')
- c = c - 'A' + 10;
- else if (c>='a' && c<='z')
- c = c - 'a' + 10;
- else
- break;
- if (c >= base)
- break;
- if (i > cutoff || (i == cutoff && c > cutlim))
- overflow = 1;
- else
- {
- i *= (ulonglong) base;
- i += c;
- }
- }
- if (s == save)
- goto noconv;
- if (endptr != NULL)
- *endptr = (char *) s;
- if (overflow)
- {
- err[0]= ERANGE;
- return (~(ulonglong) 0);
- }
- return (negative ? -((longlong) i) : (longlong) i);
- noconv:
- err[0]= EDOM;
- if (endptr != NULL)
- *endptr = (char *) nptr;
- return 0L;
- }
- /*
- Read double from string
- SYNOPSIS:
- my_strntod_8bit()
- cs Character set information
- str String to convert to double
- length Optional length for string.
- end result pointer to end of converted string
- err Error number if failed conversion
-
- NOTES:
- If length is not INT_MAX32 or str[length] != 0 then the given str must
- be writeable
- If length == INT_MAX32 the str must be