43
39
static const char field_separator=',';
45
uint64_t find_set(TYPELIB *lib, const char *str, uint32_t length,
46
const CHARSET_INFO * const cs,
47
char **err_pos, uint32_t *err_len, bool *set_warning)
41
ulonglong find_set(TYPELIB *lib, const char *str, uint length, CHARSET_INFO *cs,
42
char **err_pos, uint *err_len, bool *set_warning)
49
const CHARSET_INFO * const strip= cs ? cs : &my_charset_utf8_general_ci;
44
CHARSET_INFO *strip= cs ? cs : &my_charset_latin1;
50
45
const char *end= str + strip->cset->lengthsp(strip, str, length);
52
47
*err_pos= 0; // No error yet
55
const char *start= str;
50
const char *start= str;
58
53
const char *pos= start;
62
for (; pos != end && *pos != field_separator; pos++)
64
var_len= (uint32_t) (pos - start);
65
uint32_t find= cs ? find_type2(lib, start, var_len, cs) :
57
if (cs && cs->mbminlen > 1)
59
for ( ; pos < end; pos+= mblen)
62
if ((mblen= cs->cset->mb_wc(cs, &wc, (const uchar *) pos,
63
(const uchar *) end)) < 1)
64
mblen= 1; // Not to hang on a wrong multibyte sequence
65
if (wc == (my_wc_t) field_separator)
70
for (; pos != end && *pos != field_separator; pos++) ;
71
var_len= (uint) (pos - start);
72
uint find= cs ? find_type2(lib, start, var_len, cs) :
66
73
find_type(lib, start, var_len, (bool) 0);
97
104
> 0 position in TYPELIB->type_names +1
100
uint32_t find_type(const TYPELIB *lib, const char *find, uint32_t length,
107
uint find_type(const TYPELIB *lib, const char *find, uint length,
103
uint32_t found_count=0, found_pos=0;
110
uint found_count=0, found_pos=0;
104
111
const char *end= find+length;
107
for (uint32_t pos=0 ; (j=lib->type_names[pos++]) ; )
114
for (uint pos=0 ; (j=lib->type_names[pos++]) ; )
109
for (i=find ; i != end &&
110
my_toupper(system_charset_info,*i) ==
116
for (i=find ; i != end &&
117
my_toupper(system_charset_info,*i) ==
111
118
my_toupper(system_charset_info,*j) ; i++, j++) ;
138
145
>0 Offset+1 in typelib for matched string
141
uint32_t find_type2(const TYPELIB *typelib, const char *x, uint32_t length,
142
const CHARSET_INFO * const cs)
148
uint find_type2(const TYPELIB *typelib, const char *x, uint length,
153
DBUG_ENTER("find_type2");
154
DBUG_PRINT("enter",("x: '%.*s' lib: 0x%lx", length, x, (long) typelib));
147
156
if (!typelib->count)
158
DBUG_PRINT("exit",("no count"));
152
162
for (pos=0 ; (j=typelib->type_names[pos]) ; pos++)
154
if (!my_strnncoll(cs, (const unsigned char*) x, length,
155
(const unsigned char*) j, typelib->type_lengths[pos]))
164
if (!my_strnncoll(cs, (const uchar*) x, length,
165
(const uchar*) j, typelib->type_lengths[pos]))
168
DBUG_PRINT("exit",("Couldn't find type"));
159
170
} /* find_type */
174
Un-hex all elements in a typelib
178
interval TYPELIB (struct of pointer to values + lengths + count)
186
void unhex_type2(TYPELIB *interval)
188
for (uint pos= 0; pos < interval->count; pos++)
191
for (from= to= (char*) interval->type_names[pos]; *from; )
194
Note, hexchar_to_int(*from++) doesn't work
195
one some compilers, e.g. IRIX. Looks like a compiler
196
bug in inline functions in combination with arguments
197
that have a side effect. So, let's use from[0] and from[1]
198
and increment 'from' by two later.
201
*to++= (char) (hexchar_to_int(from[0]) << 4) +
202
hexchar_to_int(from[1]);
205
interval->type_lengths[pos] /= 2;
211
Check if the first word in a string is one of the ones in TYPELIB
218
end_of_word Store value of last used byte here if we found word
222
> 1 lib->type_names[#-1] matched
223
end_of_word will point to separator character/end in 'val'
226
uint check_word(TYPELIB *lib, const char *val, const char *end,
227
const char **end_of_word)
232
/* Fiend end of word */
233
for (ptr= val ; ptr < end && my_isalpha(&my_charset_latin1, *ptr) ; ptr++)
235
if ((res=find_type(lib, val, (uint) (ptr - val), 1)) > 0)
242
Converts a string between character sets
246
from_cs source character set
247
from source, a null terminated string
248
to destination buffer
249
to_length destination buffer length
252
'to' is always terminated with a '\0' character.
253
If there is no enough space to convert whole string,
254
only prefix is converted, and terminated with '\0'.
261
uint strconvert(CHARSET_INFO *from_cs, const char *from,
262
CHARSET_INFO *to_cs, char *to, uint to_length, uint *errors)
267
uchar *to_end= (uchar*) to + to_length - 1;
268
my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
269
my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
275
Using 'from + 10' is safe:
276
- it is enough to scan a single character in any character set.
277
- if remaining string is shorter than 10, then mb_wc will return
278
with error because of unexpected '\0' character.
280
if ((cnvres= (*mb_wc)(from_cs, &wc,
281
(uchar*) from, (uchar*) from + 10)) > 0)
287
else if (cnvres == MY_CS_ILSEQ)
294
break; // Impossible char.
298
if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
300
else if (cnvres == MY_CS_ILUNI && wc != '?')
310
*errors= error_count;
311
return (uint32) (to - to_start);
317
Searches for a LEX_STRING in an LEX_STRING array.
320
find_string_in_array()
322
needle The string to search for
325
The last LEX_STRING in the array should have str member set to NULL
332
int find_string_in_array(LEX_STRING * const haystack, LEX_STRING * const needle,
333
CHARSET_INFO * const cs)
335
const LEX_STRING *pos;
336
for (pos= haystack; pos->str; pos++)
337
if (!cs->coll->strnncollsp(cs, (uchar *) pos->str, pos->length,
338
(uchar *) needle->str, needle->length, 0))
340
return (pos - haystack);