diff options
Diffstat (limited to 'sql/sql_string.cc')
-rw-r--r-- | sql/sql_string.cc | 108 |
1 files changed, 78 insertions, 30 deletions
diff --git a/sql/sql_string.cc b/sql/sql_string.cc index e7051883d36..9024f98bd92 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -32,7 +32,7 @@ required by the string function */ -extern gptr sql_alloc(unsigned size); +extern uchar* sql_alloc(unsigned size); extern void sql_element_free(void *ptr); #include "sql_string.h" @@ -95,29 +95,19 @@ bool String::realloc(uint32 alloc_length) return FALSE; } -bool String::set(longlong num, CHARSET_INFO *cs) +bool String::set_int(longlong num, bool unsigned_flag, CHARSET_INFO *cs) { uint l=20*cs->mbmaxlen+1; + int base= unsigned_flag ? 10 : -10; if (alloc(l)) return TRUE; - str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,-10,num); + str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,base,num); str_charset=cs; return FALSE; } -bool String::set(ulonglong num, CHARSET_INFO *cs) -{ - uint l=20*cs->mbmaxlen+1; - - if (alloc(l)) - return TRUE; - str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,10,num); - str_charset=cs; - return FALSE; -} - -bool String::set(double num,uint decimals, CHARSET_INFO *cs) +bool String::set_real(double num,uint decimals, CHARSET_INFO *cs) { char buff[331]; uint dummy_errors; @@ -335,7 +325,7 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length, return copy_aligned(str, arg_length, offset, cs); } - /* Copy with charset convertion */ + /* Copy with charset conversion */ bool String::copy(const char *str, uint32 arg_length, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors) @@ -506,7 +496,7 @@ bool String::append(FILE* file, uint32 arg_length, myf my_flags) { if (realloc(str_length+arg_length)) return TRUE; - if (my_fread(file, (byte*) Ptr + str_length, arg_length, my_flags)) + if (my_fread(file, (uchar*) Ptr + str_length, arg_length, my_flags)) { shrink(str_length); return TRUE; @@ -520,7 +510,7 @@ bool String::append(IO_CACHE* file, uint32 arg_length) { if (realloc(str_length+arg_length)) return TRUE; - if (my_b_read(file, (byte*) Ptr + str_length, arg_length)) + if (my_b_read(file, (uchar*) Ptr + str_length, arg_length)) { shrink(str_length); return TRUE; @@ -645,7 +635,7 @@ bool String::replace(uint32 offset,uint32 arg_length, { if (realloc(str_length+(uint32) diff)) return TRUE; - bmove_upp(Ptr+str_length+diff,Ptr+str_length, + bmove_upp((uchar*) Ptr+str_length+diff, (uchar*) Ptr+str_length, str_length-offset-arg_length); } if (to_length) @@ -723,8 +713,8 @@ void String::qs_append(uint i) int sortcmp(const String *s,const String *t, CHARSET_INFO *cs) { return cs->coll->strnncollsp(cs, - (unsigned char *) s->ptr(),s->length(), - (unsigned char *) t->ptr(),t->length(), 0); + (uchar *) s->ptr(),s->length(), + (uchar *) t->ptr(),t->length(), 0); } @@ -737,7 +727,7 @@ int sortcmp(const String *s,const String *t, CHARSET_INFO *cs) t Second string NOTE: - Strings are compared as a stream of unsigned chars + Strings are compared as a stream of uchars RETURN < 0 s < t @@ -805,10 +795,8 @@ copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, const uchar *from_end= (const uchar*) from+from_length; char *to_start= to; uchar *to_end= (uchar*) to+to_length; - int (*mb_wc)(struct charset_info_st *, my_wc_t *, const uchar *, - const uchar *) = from_cs->cset->mb_wc; - int (*wc_mb)(struct charset_info_st *, my_wc_t, uchar *s, uchar *e)= - to_cs->cset->wc_mb; + my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc; + my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb; uint error_count= 0; while (1) @@ -852,6 +840,68 @@ outp: } +/** + Copy string with HEX-encoding of "bad" characters. + + @details This functions copies the string pointed by "src" + to the string pointed by "dst". Not more than "srclen" bytes + are read from "src". Any sequences of bytes representing + a not-well-formed substring (according to cs) are hex-encoded, + and all well-formed substrings (according to cs) are copied as is. + Not more than "dstlen" bytes are written to "dst". The number + of bytes written to "dst" is returned. + + @param cs character set pointer of the destination string + @param[out] dst destination string + @param dstlen size of dst + @param src source string + @param srclen length of src + + @retval result length +*/ + +size_t +my_copy_with_hex_escaping(CHARSET_INFO *cs, + char *dst, size_t dstlen, + const char *src, size_t srclen) +{ + const char *srcend= src + srclen; + char *dst0= dst; + + for ( ; src < srcend ; ) + { + size_t chlen; + if ((chlen= my_ismbchar(cs, src, srcend))) + { + if (dstlen < chlen) + break; /* purecov: inspected */ + memcpy(dst, src, chlen); + src+= chlen; + dst+= chlen; + dstlen-= chlen; + } + else if (*src & 0x80) + { + if (dstlen < 4) + break; /* purecov: inspected */ + *dst++= '\\'; + *dst++= 'x'; + *dst++= _dig_vec_upper[((unsigned char) *src) >> 4]; + *dst++= _dig_vec_upper[((unsigned char) *src) & 15]; + src++; + dstlen-= 4; + } + else + { + if (dstlen < 1) + break; /* purecov: inspected */ + *dst++= *src++; + dstlen--; + } + } + return dst - dst0; +} + /* copy a string, with optional character set conversion, @@ -950,10 +1000,8 @@ well_formed_copy_nchars(CHARSET_INFO *to_cs, { int cnvres; my_wc_t wc; - int (*mb_wc)(struct charset_info_st *, my_wc_t *, - const uchar *, const uchar *)= from_cs->cset->mb_wc; - int (*wc_mb)(struct charset_info_st *, my_wc_t, - uchar *s, uchar *e)= to_cs->cset->wc_mb; + my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc; + my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb; const uchar *from_end= (const uchar*) from + from_length; uchar *to_end= (uchar*) to + to_length; char *to_start= to; |