18 #include <my_global.h>
22 #include <mysql_com.h>
24 #include "sql_string.h"
35 bool String::real_alloc(uint32 length)
37 uint32 arg_length= ALIGN_SIZE(length + 1);
38 DBUG_ASSERT(arg_length > length);
39 if (arg_length <= length)
42 if (Alloced_length < arg_length)
45 if (!(
Ptr=(
char*) my_malloc(arg_length,MYF(MY_WME))))
47 Alloced_length=arg_length;
84 uint32 len=ALIGN_SIZE(alloc_length+1);
85 DBUG_ASSERT(len > alloc_length);
86 if (len <= alloc_length)
88 if (Alloced_length < len)
93 if (!(new_ptr= (
char*) my_realloc(
Ptr,len,MYF(MY_WME))))
96 else if ((new_ptr= (
char*) my_malloc(len,MYF(MY_WME))))
98 if (str_length > len - 1)
101 memcpy(new_ptr,
Ptr,str_length);
102 new_ptr[str_length]=0;
114 bool String::set_int(longlong num,
bool unsigned_flag,
const CHARSET_INFO *cs)
116 uint l=20*cs->mbmaxlen+1;
117 int base= unsigned_flag ? 10 : -10;
121 str_length=(uint32) (cs->cset->longlong10_to_str)(cs,
Ptr,l,base,num);
126 bool String::set_real(
double num,uint decimals,
const CHARSET_INFO *cs)
128 char buff[FLOATING_POINT_BUFFER];
133 if (decimals >= NOT_FIXED_DEC)
135 len= my_gcvt(num, MY_GCVT_ARG_DOUBLE,
sizeof(buff) - 1, buff, NULL);
136 return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
138 len= my_fcvt(num, decimals, buff, NULL);
139 return copy(buff, (uint32) len, &my_charset_latin1, cs,
165 bool String::copy(
const String &str)
167 if (alloc(str.str_length))
169 str_length=str.str_length;
170 bmove(
Ptr,str.Ptr,str_length);
172 str_charset=str.str_charset;
176 bool String::copy(
const char *str,uint32 arg_length,
179 if (alloc(arg_length))
181 if ((str_length=arg_length))
182 memcpy(
Ptr,str,arg_length);
211 bool String::needs_conversion(uint32 arg_length,
218 (to_cs == &my_charset_bin) ||
219 (to_cs == from_cs) ||
220 my_charset_same(from_cs, to_cs) ||
221 ((from_cs == &my_charset_bin) &&
222 (!(*offset=(arg_length % to_cs->mbminlen)))))
253 bool String::copy_aligned(
const char *str,uint32 arg_length, uint32 offset,
257 offset= cs->mbminlen -
offset;
258 DBUG_ASSERT(offset && offset != cs->mbminlen);
260 uint32 aligned_length= arg_length +
offset;
261 if (alloc(aligned_length))
269 memset(
Ptr, 0, offset);
270 memcpy(
Ptr + offset, str, arg_length);
271 Ptr[aligned_length]=0;
273 str_length= aligned_length;
279 bool String::set_or_copy_aligned(
const char *str,uint32 arg_length,
283 uint32 offset= (arg_length % cs->mbminlen);
287 set(str, arg_length, cs);
290 return copy_aligned(str, arg_length, offset, cs);
304 bool String::copy(
const char *str, uint32 arg_length,
309 DBUG_ASSERT(!str || str !=
Ptr);
311 if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
314 return copy(str, arg_length, to_cs);
316 if ((from_cs == &my_charset_bin) && offset)
319 return copy_aligned(str, arg_length, offset, to_cs);
321 uint32 new_length= to_cs->mbmaxlen*arg_length;
322 if (alloc(new_length))
324 str_length=copy_and_convert((
char*)
Ptr, new_length, to_cs,
325 str, arg_length, from_cs, errors);
350 bool String::set_ascii(
const char *str, uint32 arg_length)
352 if (str_charset->mbminlen == 1)
354 set(str, arg_length, str_charset);
358 return copy(str, arg_length, &my_charset_latin1, str_charset, &dummy_errors);
364 bool String::fill(uint32 max_length,
char fill_char)
366 if (str_length > max_length)
367 Ptr[str_length=max_length]=0;
372 memset(
Ptr+str_length, fill_char, max_length-str_length);
373 str_length=max_length;
378 void String::strip_sp()
380 while (str_length && my_isspace(str_charset,
Ptr[str_length-1]))
384 bool String::append(
const String &s)
388 if (
realloc(str_length+s.length()))
390 memcpy(
Ptr+str_length,s.ptr(),s.length());
391 str_length+=s.length();
401 bool String::append(
const char *s,uint32 arg_length)
409 if (str_charset->mbminlen > 1)
411 uint32 add_length=arg_length * str_charset->mbmaxlen;
413 if (
realloc(str_length+ add_length))
415 str_length+= copy_and_convert(
Ptr+str_length, add_length, str_charset,
416 s, arg_length, &my_charset_latin1,
424 if (
realloc(str_length+arg_length))
426 memcpy(
Ptr+str_length,s,arg_length);
427 str_length+=arg_length;
436 bool String::append(
const char *s)
438 return append(s, (uint) strlen(s));
443 bool String::append_ulonglong(ulonglong val)
445 if (
realloc(str_length+MAX_BIGINT_WIDTH+2))
447 char *end= (
char*) longlong10_to_str(val, (
char*)
Ptr + str_length, 10);
448 str_length= end -
Ptr;
457 bool String::append(
const char *s,uint32 arg_length,
const CHARSET_INFO *cs)
461 if (needs_conversion(arg_length, cs, str_charset, &offset))
464 if ((cs == &my_charset_bin) && offset)
466 DBUG_ASSERT(str_charset->mbminlen > offset);
467 offset= str_charset->mbminlen -
offset;
468 add_length= arg_length +
offset;
469 if (
realloc(str_length + add_length))
471 memset(
Ptr + str_length, 0, offset);
472 memcpy(
Ptr + str_length + offset, s, arg_length);
473 str_length+= add_length;
477 add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen;
479 if (
realloc(str_length + add_length))
481 str_length+= copy_and_convert(
Ptr+str_length, add_length, str_charset,
482 s, arg_length, cs, &dummy_errors);
486 if (
realloc(str_length + arg_length))
488 memcpy(
Ptr + str_length, s, arg_length);
489 str_length+= arg_length;
496 if (
realloc(str_length+arg_length))
498 if (my_b_read(file, (uchar*)
Ptr + str_length, arg_length))
503 str_length+=arg_length;
519 end= int10_to_str(nr, buff + 1, radix);
521 return append(buff, (uint) (end - buff));
525 bool String::append_with_prefill(
const char *s,uint32 arg_length,
526 uint32 full_length,
char fill_char)
528 int t_length= arg_length > full_length ? arg_length : full_length;
530 if (
realloc(str_length + t_length))
532 t_length= full_length - arg_length;
535 memset(
Ptr+str_length, fill_char, t_length);
536 str_length=str_length + t_length;
538 append(s, arg_length);
542 uint32 String::numchars()
const
544 return str_charset->cset->numchars(str_charset,
Ptr,
Ptr+str_length);
547 int String::charpos(
int i,uint32 offset)
551 return str_charset->cset->charpos(str_charset,
Ptr+offset,
Ptr+str_length,i);
554 int String::strstr(
const String &s,uint32 offset)
556 if (s.length()+offset <= str_length)
562 register const char *search=s.ptr();
563 const char *end=
Ptr+str_length-s.length()+1;
564 const char *search_end=s.ptr()+s.length();
568 if (*str++ == *search)
571 i=(
char*) str; j=(
char*) search+1;
572 while (j != search_end)
573 if (*i++ != *j++)
goto skip;
574 return (
int) (str-
Ptr) -1;
585 int String::strrstr(
const String &s,uint32 offset)
587 if (s.length() <= offset && offset <= str_length)
591 register const char *str =
Ptr+offset-1;
592 register const char *search=s.ptr()+s.length()-1;
594 const char *end=
Ptr+s.length()-2;
595 const char *search_end=s.ptr()-1;
599 if (*str-- == *search)
602 i=(
char*) str; j=(
char*) search-1;
603 while (j != search_end)
604 if (*i-- != *j--)
goto skip;
605 return (
int) (i-
Ptr) +1;
617 bool String::replace(uint32 offset,uint32 arg_length,
const String &
to)
619 return replace(offset,arg_length,to.ptr(),to.length());
622 bool String::replace(uint32 offset,uint32 arg_length,
623 const char *to, uint32 to_length)
625 long diff = (long) to_length-(
long) arg_length;
626 if (offset+arg_length <= str_length)
631 memcpy(
Ptr+offset,to,to_length);
632 bmove(
Ptr+offset+to_length,
Ptr+offset+arg_length,
633 str_length-offset-arg_length);
639 if (
realloc(str_length+(uint32) diff))
641 bmove_upp((uchar*)
Ptr+str_length+diff, (uchar*)
Ptr+str_length,
642 str_length-offset-arg_length);
645 memcpy(
Ptr+offset,to,to_length);
647 str_length+=(uint32) diff;
654 int String::reserve(uint32 space_needed, uint32 grow_by)
656 if (Alloced_length < str_length + space_needed)
658 if (
realloc(Alloced_length + max(space_needed, grow_by) - 1))
664 void String::qs_append(
const char *str, uint32 len)
666 memcpy(
Ptr + str_length, str, len + 1);
670 void String::qs_append(
double d)
672 char *buff =
Ptr + str_length;
673 str_length+= my_gcvt(d, MY_GCVT_ARG_DOUBLE, FLOATING_POINT_BUFFER - 1, buff,
677 void String::qs_append(
double *d)
680 float8get(ld, (
char*) d);
684 void String::qs_append(
int i)
686 char *buff=
Ptr + str_length;
687 char *end= int10_to_str(i, buff, -10);
688 str_length+= (int) (end-buff);
691 void String::qs_append(uint i)
693 char *buff=
Ptr + str_length;
694 char *end= int10_to_str(i, buff, 10);
695 str_length+= (int) (end-buff);
719 return cs->coll->strnncollsp(cs,
720 (uchar *) s->ptr(),s->length(),
721 (uchar *) t->ptr(),t->length(), 0);
745 uint32 s_len=s->length(),t_len=t->length(),len=min(s_len,t_len);
746 int cmp= memcmp(s->ptr(), t->ptr(), len);
747 return (cmp) ? cmp : (int) (s_len - t_len);
753 if (from->Alloced_length >= from_length)
755 if ((from->alloced && (from->Alloced_length != 0)) || !to || from == to)
757 (void) from->
realloc(from_length);
762 if ((to->str_length=min(from->str_length,from_length)))
763 memcpy(to->Ptr,from->Ptr,to->str_length);
764 to->str_charset=from->str_charset;
795 char *dst,
size_t dstlen,
796 const char *src,
size_t srclen)
798 const char *srcend= src + srclen;
801 for ( ; src < srcend ; )
804 if ((chlen= my_ismbchar(cs, src, srcend)))
808 memcpy(dst, src, chlen);
813 else if (*src & 0x80)
819 *dst++= _dig_vec_upper[((
unsigned char) *src) >> 4];
820 *dst++= _dig_vec_upper[((
unsigned char) *src) & 15];
864 char *to, uint to_length,
866 const char *from, uint from_length,
868 const char **well_formed_error_pos,
869 const char **cannot_convert_error_pos,
870 const char **from_end_pos)
874 if ((to_cs == &my_charset_bin) ||
875 (from_cs == &my_charset_bin) ||
876 (to_cs == from_cs) ||
877 my_charset_same(from_cs, to_cs))
879 if (to_length < to_cs->mbminlen || !nchars)
882 *cannot_convert_error_pos= NULL;
883 *well_formed_error_pos= NULL;
887 if (to_cs == &my_charset_bin)
889 res= min(min(nchars, to_length), from_length);
890 memmove(to, from, res);
891 *from_end_pos= from + res;
892 *well_formed_error_pos= NULL;
893 *cannot_convert_error_pos= NULL;
897 int well_formed_error;
900 if ((from_offset= (from_length % to_cs->mbminlen)) &&
901 (from_cs == &my_charset_bin))
908 uint pad_length= to_cs->mbminlen - from_offset;
909 memset(to, 0, pad_length);
910 memmove(to + pad_length, from, from_offset);
920 if (to_cs->cset->well_formed_len(to_cs,
921 to, to + to_cs->mbminlen, 1,
922 &well_formed_error) !=
925 *from_end_pos= *well_formed_error_pos= from;
926 *cannot_convert_error_pos= NULL;
931 from_length-= from_offset;
932 to+= to_cs->mbminlen;
933 to_length-= to_cs->mbminlen;
936 set_if_smaller(from_length, to_length);
937 res= to_cs->cset->well_formed_len(to_cs, from, from + from_length,
938 nchars, &well_formed_error);
939 memmove(to, from, res);
940 *from_end_pos= from + res;
941 *well_formed_error_pos= well_formed_error ? from + res : NULL;
942 *cannot_convert_error_pos= NULL;
944 res+= to_cs->mbminlen;
951 my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
952 my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
953 const uchar *from_end= (
const uchar*) from + from_length;
954 uchar *to_end= (uchar*) to + to_length;
956 *well_formed_error_pos= NULL;
957 *cannot_convert_error_pos= NULL;
959 for ( ; nchars; nchars--)
961 const char *from_prev= from;
962 if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from, from_end)) > 0)
964 else if (cnvres == MY_CS_ILSEQ)
966 if (!*well_formed_error_pos)
967 *well_formed_error_pos= from;
971 else if (cnvres > MY_CS_TOOSMALL)
977 if (!*cannot_convert_error_pos)
978 *cannot_convert_error_pos= from;
986 if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
988 else if (cnvres == MY_CS_ILUNI && wc !=
'?')
990 if (!*cannot_convert_error_pos)
991 *cannot_convert_error_pos= from_prev;
1001 *from_end_pos= from;
1002 res= (uint) (to - to_start);
1004 return (uint32) res;
1010 void String::print(
String *str)
1012 char *st= (
char*)
Ptr, *end= st+str_length;
1013 for (; st < end; st++)
1019 str->append(STRING_WITH_LEN(
"\\\\"));
1022 str->append(STRING_WITH_LEN(
"\\0"));
1025 str->append(STRING_WITH_LEN(
"\\'"));
1028 str->append(STRING_WITH_LEN(
"\\n"));
1031 str->append(STRING_WITH_LEN(
"\\r"));
1034 str->append(STRING_WITH_LEN(
"\\Z"));
1053 void String::swap(
String &s)
1055 swap_variables(
char *,
Ptr, s.Ptr);
1056 swap_variables(uint32, str_length, s.str_length);
1057 swap_variables(uint32, Alloced_length, s.Alloced_length);
1058 swap_variables(
bool, alloced, s.alloced);
1059 swap_variables(
const CHARSET_INFO *, str_charset, s.str_charset);
1083 uint convert_to_printable(
char *to,
size_t to_len,
1084 const char *from,
size_t from_len,
1088 DBUG_ASSERT(to_len >= 8);
1091 char *t_end= to + to_len - 1;
1092 const char *f= from;
1093 const char *f_end= from + (nbytes ? min(from_len, nbytes) : from_len);
1096 if (!f || t == t_end)
1099 for (; t < t_end && f < f_end; f++)
1110 if (((
unsigned char) *f) >= 0x20 &&
1111 ((
unsigned char) *f) <= 0x7F &&
1112 from_cs->mbminlen == 1)
1122 *t++= _dig_vec_upper[((
unsigned char) *f) >> 4];
1123 *t++= _dig_vec_upper[((
unsigned char) *f) & 0x0F];
1128 if (f < from + from_len)
1129 memcpy(dots, STRING_WITH_LEN(
"...\0"));