strfunc.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:6k
- /* Copyright (C) 2003 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 */
- /* Some useful string utility functions used by the MySQL server */
- #include "mysql_priv.h"
- /*
- Return bitmap for strings used in a set
- SYNOPSIS
- find_set()
- lib Strings in set
- str Strings of set-strings separated by ','
- err_pos If error, set to point to start of wrong set string
- err_len If error, set to the length of wrong set string
- set_warning Set to 1 if some string in set couldn't be used
- NOTE
- We delete all end space from str before comparison
- RETURN
- bitmap of all sets found in x.
- set_warning is set to 1 if there was any sets that couldn't be set
- */
- static const char field_separator=',';
- ulonglong find_set(TYPELIB *lib, const char *str, uint length, CHARSET_INFO *cs,
- char **err_pos, uint *err_len, bool *set_warning)
- {
- CHARSET_INFO *strip= cs ? cs : &my_charset_latin1;
- const char *end= str + strip->cset->lengthsp(strip, str, length);
- ulonglong found= 0;
- *err_pos= 0; // No error yet
- if (str != end)
- {
- const char *start= str;
- for (;;)
- {
- const char *pos= start;
- uint var_len;
- int mblen= 1;
- if (cs && cs->mbminlen > 1)
- {
- for ( ; pos < end; pos+= mblen)
- {
- my_wc_t wc;
- if ((mblen= cs->cset->mb_wc(cs, &wc, (const uchar *) pos,
- (const uchar *) end)) < 1)
- mblen= 1; // Not to hang on a wrong multibyte sequence
- if (wc == (my_wc_t) field_separator)
- break;
- }
- }
- else
- for (; pos != end && *pos != field_separator; pos++) ;
- var_len= (uint) (pos - start);
- uint find= cs ? find_type2(lib, start, var_len, cs) :
- find_type(lib, start, var_len, (bool) 0);
- if (!find)
- {
- *err_pos= (char*) start;
- *err_len= var_len;
- *set_warning= 1;
- }
- else
- found|= ((longlong) 1 << (find - 1));
- if (pos >= end)
- break;
- start= pos + mblen;
- }
- }
- return found;
- }
- /*
- Function to find a string in a TYPELIB
- (Same format as mysys/typelib.c)
- SYNOPSIS
- find_type()
- lib TYPELIB (struct of pointer to values + count)
- find String to find
- length Length of string to find
- part_match Allow part matching of value
- RETURN
- 0 error
- > 0 position in TYPELIB->type_names +1
- */
- uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match)
- {
- uint found_count=0, found_pos=0;
- const char *end= find+length;
- const char *i;
- const char *j;
- for (uint pos=0 ; (j=lib->type_names[pos++]) ; )
- {
- for (i=find ; i != end &&
- my_toupper(system_charset_info,*i) ==
- my_toupper(system_charset_info,*j) ; i++, j++) ;
- if (i == end)
- {
- if (! *j)
- return(pos);
- found_count++;
- found_pos= pos;
- }
- }
- return(found_count == 1 && part_match ? found_pos : 0);
- }
- /*
- Find a string in a list of strings according to collation
- SYNOPSIS
- find_type2()
- lib TYPELIB (struct of pointer to values + count)
- x String to find
- length String length
- cs Character set + collation to use for comparison
- NOTES
- RETURN
- 0 No matching value
- >0 Offset+1 in typelib for matched string
- */
- uint find_type2(TYPELIB *typelib, const char *x, uint length, CHARSET_INFO *cs)
- {
- int find,pos;
- const char *j;
- DBUG_ENTER("find_type2");
- DBUG_PRINT("enter",("x: '%s' lib: 0x%lx",x,typelib));
- if (!typelib->count)
- {
- DBUG_PRINT("exit",("no count"));
- DBUG_RETURN(0);
- }
- for (find=0, pos=0 ; (j=typelib->type_names[pos]) ; pos++)
- {
- if (!my_strnncoll(cs, (const uchar*) x, length,
- (const uchar*) j, typelib->type_lengths[pos]))
- DBUG_RETURN(pos+1);
- }
- DBUG_PRINT("exit",("Couldn't find type"));
- DBUG_RETURN(0);
- } /* find_type */
- /*
- Un-hex all elements in a typelib
- SYNOPSIS
- unhex_type2()
- interval TYPELIB (struct of pointer to values + lengths + count)
- NOTES
- RETURN
- N/A
- */
- void unhex_type2(TYPELIB *interval)
- {
- for (uint pos= 0; pos < interval->count; pos++)
- {
- char *from, *to;
- for (from= to= (char*) interval->type_names[pos]; *from; )
- {
- /*
- Note, hexchar_to_int(*from++) doesn't work
- one some compilers, e.g. IRIX. Looks like a compiler
- bug in inline functions in combination with arguments
- that have a side effect. So, let's use from[0] and from[1]
- and increment 'from' by two later.
- */
- *to++= (char) (hexchar_to_int(from[0]) << 4) +
- hexchar_to_int(from[1]);
- from+= 2;
- }
- interval->type_lengths[pos] /= 2;
- }
- }
- /*
- Check if the first word in a string is one of the ones in TYPELIB
- SYNOPSIS
- check_word()
- lib TYPELIB
- val String to check
- end End of input
- end_of_word Store value of last used byte here if we found word
- RETURN
- 0 No matching value
- > 1 lib->type_names[#-1] matched
- end_of_word will point to separator character/end in 'val'
- */
- uint check_word(TYPELIB *lib, const char *val, const char *end,
- const char **end_of_word)
- {
- int res;
- const char *ptr;
- /* Fiend end of word */
- for (ptr= val ; ptr < end && my_isalpha(&my_charset_latin1, *ptr) ; ptr++)
- ;
- if ((res=find_type(lib, val, (uint) (ptr - val), 1)) > 0)
- *end_of_word= ptr;
- return res;
- }