16
16
/* This file is originally from the mysql distribution. Coded by monty */
19
#include <mysys/my_sys.h>
20
#include <mystrings/m_string.h>
18
#ifdef USE_PRAGMA_IMPLEMENTATION
19
#pragma implementation // gcc: Class implementation
22
#include <my_global.h>
25
28
The following extern declarations are ok as these are interface functions
26
29
required by the string function
29
extern unsigned char* sql_alloc(unsigned size);
32
extern uchar* sql_alloc(unsigned size);
30
33
extern void sql_element_free(void *ptr);
32
35
#include "sql_string.h"
35
38
** String functions
36
39
*****************************************************************************/
38
bool String::real_alloc(uint32_t arg_length)
41
bool String::real_alloc(uint32 arg_length)
40
43
arg_length=ALIGN_SIZE(arg_length+1);
57
60
** (for C functions)
60
bool String::realloc(uint32_t alloc_length)
63
bool String::realloc(uint32 alloc_length)
62
uint32_t len=ALIGN_SIZE(alloc_length+1);
65
uint32 len=ALIGN_SIZE(alloc_length+1);
63
66
if (Alloced_length < len)
92
bool String::set_int(int64_t num, bool unsigned_flag, const CHARSET_INFO * const cs)
95
bool String::set_int(int64_t num, bool unsigned_flag, CHARSET_INFO *cs)
94
uint32_t l=20*cs->mbmaxlen+1;
97
uint l=20*cs->mbmaxlen+1;
95
98
int base= unsigned_flag ? 10 : -10;
99
str_length=(uint32_t) (cs->cset->int64_t10_to_str)(cs,Ptr,l,base,num);
102
str_length=(uint32) (cs->cset->int64_t10_to_str)(cs,Ptr,l,base,num);
104
bool String::set_real(double num,uint32_t decimals, const CHARSET_INFO * const cs)
107
bool String::set_real(double num,uint decimals, CHARSET_INFO *cs)
106
109
char buff[FLOATING_POINT_BUFFER];
107
uint32_t dummy_errors;
111
114
if (decimals >= NOT_FIXED_DEC)
113
116
len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
114
return copy(buff, len, &my_charset_utf8_general_ci, cs, &dummy_errors);
117
return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
116
119
len= my_fcvt(num, decimals, buff, NULL);
117
return copy(buff, (uint32_t) len, &my_charset_utf8_general_ci, cs,
120
return copy(buff, (uint32) len, &my_charset_latin1, cs,
134
137
if (alloc(str.str_length))
136
139
str_length=str.str_length;
137
memmove(Ptr, str.Ptr, str_length); // May be overlapping
140
bmove(Ptr,str.Ptr,str_length); // May be overlapping
138
141
Ptr[str_length]=0;
139
142
str_charset=str.str_charset;
143
bool String::copy(const char *str,uint32_t arg_length, const CHARSET_INFO * const cs)
146
bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
145
148
if (alloc(arg_length))
162
165
arg_length Length of string to copy.
163
166
from_cs Character set to copy from
164
167
to_cs Character set to copy to
165
uint32_t *offset Returns number of unaligned characters.
168
uint32 *offset Returns number of unaligned characters.
168
171
0 No conversion needed
174
177
character_set_results is NULL.
177
bool String::needs_conversion(uint32_t arg_length,
178
const CHARSET_INFO * const from_cs,
179
const CHARSET_INFO * const to_cs,
180
bool String::needs_conversion(uint32 arg_length,
181
CHARSET_INFO *from_cs,
219
bool String::copy_aligned(const char *str,uint32_t arg_length, uint32_t offset,
220
const CHARSET_INFO * const cs)
222
bool String::copy_aligned(const char *str,uint32 arg_length, uint32 offset,
222
225
/* How many bytes are in incomplete character */
223
226
offset= cs->mbmaxlen - offset; /* How many zeros we should prepend */
224
227
assert(offset && offset != cs->mbmaxlen);
226
uint32_t aligned_length= arg_length + offset;
229
uint32 aligned_length= arg_length + offset;
227
230
if (alloc(aligned_length))
232
235
If we add little-endian UCS-2 sometimes, this code
233
236
will be more complicated. But it's OK for now.
235
memset(Ptr, 0, offset);
238
bzero((char*) Ptr, offset);
236
239
memcpy(Ptr + offset, str, arg_length);
237
240
Ptr[aligned_length]=0;
238
241
/* str_length is always >= 0 as arg_length is != 0 */
245
bool String::set_or_copy_aligned(const char *str,uint32_t arg_length,
246
const CHARSET_INFO * const cs)
248
bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
248
251
/* How many bytes are in incomplete character */
249
uint32_t offset= (arg_length % cs->mbminlen);
252
uint32 offset= (arg_length % cs->mbminlen);
251
254
if (!offset) /* All characters are complete, just copy */
259
262
/* Copy with charset conversion */
261
bool String::copy(const char *str, uint32_t arg_length,
262
const CHARSET_INFO * const from_cs,
263
const CHARSET_INFO * const to_cs, uint32_t *errors)
264
bool String::copy(const char *str, uint32 arg_length,
265
CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors)
266
268
if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
274
276
return copy_aligned(str, arg_length, offset, to_cs);
276
uint32_t new_length= to_cs->mbmaxlen*arg_length;
278
uint32 new_length= to_cs->mbmaxlen*arg_length;
277
279
if (alloc(new_length))
279
281
str_length=copy_and_convert((char*) Ptr, new_length, to_cs,
305
bool String::set_ascii(const char *str, uint32_t arg_length)
307
bool String::set_ascii(const char *str, uint32 arg_length)
307
309
if (str_charset->mbminlen == 1)
309
311
set(str, arg_length, str_charset);
312
uint32_t dummy_errors;
313
return copy(str, arg_length, &my_charset_utf8_general_ci, str_charset, &dummy_errors);
315
return copy(str, arg_length, &my_charset_latin1, str_charset, &dummy_errors);
317
319
/* This is used by mysql.cc */
319
bool String::fill(uint32_t max_length,char fill_char)
321
bool String::fill(uint32 max_length,char fill_char)
321
323
if (str_length > max_length)
322
324
Ptr[str_length=max_length]=0;
325
327
if (realloc(max_length))
327
memset(Ptr+str_length, fill_char, max_length-str_length);
329
bfill(Ptr+str_length,max_length-str_length,fill_char);
328
330
str_length=max_length;
335
void String::strip_sp()
337
while (str_length && my_isspace(str_charset,Ptr[str_length-1]))
333
341
bool String::append(const String &s)
358
366
if (str_charset->mbminlen > 1)
360
uint32_t add_length=arg_length * str_charset->mbmaxlen;
361
uint32_t dummy_errors;
368
uint32 add_length=arg_length * str_charset->mbmaxlen;
362
370
if (realloc(str_length+ add_length))
364
372
str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
365
s, arg_length, &my_charset_utf8_general_ci,
373
s, arg_length, &my_charset_latin1,
393
401
with character set recoding
396
bool String::append(const char *s,uint32_t arg_length, const CHARSET_INFO * const cs)
404
bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs)
398
uint32_t dummy_offset;
400
408
if (needs_conversion(arg_length, cs, str_charset, &dummy_offset))
402
uint32_t add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen;
403
uint32_t dummy_errors;
410
uint32 add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen;
404
412
if (realloc(str_length + add_length))
406
414
str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
420
bool String::append(IO_CACHE* file, uint32_t arg_length)
428
bool String::append(IO_CACHE* file, uint32 arg_length)
422
430
if (realloc(str_length+arg_length))
424
if (my_b_read(file, (unsigned char*) Ptr + str_length, arg_length))
432
if (my_b_read(file, (uchar*) Ptr + str_length, arg_length))
426
434
shrink(str_length);
433
bool String::append_with_prefill(const char *s,uint32_t arg_length,
434
uint32_t full_length, char fill_char)
441
bool String::append_with_prefill(const char *s,uint32 arg_length,
442
uint32 full_length, char fill_char)
436
444
int t_length= arg_length > full_length ? arg_length : full_length;
440
448
t_length= full_length - arg_length;
441
449
if (t_length > 0)
443
memset(Ptr+str_length, fill_char, t_length);
451
bfill(Ptr+str_length, t_length, fill_char);
444
452
str_length=str_length + t_length;
446
454
append(s, arg_length);
450
uint32_t String::numchars()
458
uint32 String::numchars()
452
460
return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
455
int String::charpos(int i,uint32_t offset)
463
int String::charpos(int i,uint32 offset)
459
467
return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
462
int String::strstr(const String &s,uint32_t offset)
470
int String::strstr(const String &s,uint32 offset)
464
472
if (s.length()+offset <= str_length)
490
498
** Search string from end. Offset is offset to the end of string
493
int String::strrstr(const String &s,uint32_t offset)
501
int String::strrstr(const String &s,uint32 offset)
495
503
if (s.length() <= offset && offset <= str_length)
522
530
If wrong parameter or not enough memory, do nothing
525
bool String::replace(uint32_t offset,uint32_t arg_length,const String &to)
533
bool String::replace(uint32 offset,uint32 arg_length,const String &to)
527
535
return replace(offset,arg_length,to.ptr(),to.length());
530
bool String::replace(uint32_t offset,uint32_t arg_length,
531
const char *to, uint32_t to_length)
538
bool String::replace(uint32 offset,uint32 arg_length,
539
const char *to, uint32 to_length)
533
541
long diff = (long) to_length-(long) arg_length;
534
542
if (offset+arg_length <= str_length)
539
547
memcpy(Ptr+offset,to,to_length);
540
memcpy(Ptr+offset+to_length, Ptr+offset+arg_length,
541
str_length-offset-arg_length);
548
bmove(Ptr+offset+to_length,Ptr+offset+arg_length,
549
str_length-offset-arg_length);
547
if (realloc(str_length+(uint32_t) diff))
555
if (realloc(str_length+(uint32) diff))
549
bmove_upp((unsigned char*) Ptr+str_length+diff, (unsigned char*) Ptr+str_length,
557
bmove_upp((uchar*) Ptr+str_length+diff, (uchar*) Ptr+str_length,
550
558
str_length-offset-arg_length);
553
561
memcpy(Ptr+offset,to,to_length);
555
str_length+=(uint32_t) diff;
563
str_length+=(uint32) diff;
561
569
// added by Holyfoot for "geometry" needs
562
int String::reserve(uint32_t space_needed, uint32_t grow_by)
570
int String::reserve(uint32 space_needed, uint32 grow_by)
564
572
if (Alloced_length < str_length + space_needed)
566
if (realloc(Alloced_length + cmax(space_needed, grow_by) - 1))
574
if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
572
void String::qs_append(const char *str, uint32_t len)
580
void String::qs_append(const char *str, uint32 len)
574
582
memcpy(Ptr + str_length, str, len + 1);
575
583
str_length += len;
595
603
str_length+= (int) (end-buff);
598
void String::qs_append(uint32_t i)
606
void String::qs_append(uint i)
600
608
char *buff= Ptr + str_length;
601
609
char *end= int10_to_str(i, buff, 10);
624
int sortcmp(const String *s,const String *t, const CHARSET_INFO * const cs)
632
int sortcmp(const String *s,const String *t, CHARSET_INFO *cs)
626
634
return cs->coll->strnncollsp(cs,
627
(unsigned char *) s->ptr(),s->length(),
628
(unsigned char *) t->ptr(),t->length(), 0);
635
(uchar *) s->ptr(),s->length(),
636
(uchar *) t->ptr(),t->length(), 0);
650
658
int stringcmp(const String *s,const String *t)
652
uint32_t s_len=s->length(),t_len=t->length(),len=cmin(s_len,t_len);
660
uint32 s_len=s->length(),t_len=t->length(),len=min(s_len,t_len);
653
661
int cmp= memcmp(s->ptr(), t->ptr(), len);
654
662
return (cmp) ? cmp : (int) (s_len - t_len);
658
String *copy_if_not_alloced(String *to,String *from,uint32_t from_length)
666
String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
660
668
if (from->Alloced_length >= from_length)
667
675
if (to->realloc(from_length))
668
676
return from; // Actually an error
669
if ((to->str_length=cmin(from->str_length,from_length)))
677
if ((to->str_length=min(from->str_length,from_length)))
670
678
memcpy(to->Ptr,from->Ptr,to->str_length);
671
679
to->str_charset=from->str_charset;
700
copy_and_convert_extended(char *to, uint32_t to_length,
701
const CHARSET_INFO * const to_cs,
702
const char *from, uint32_t from_length,
703
const CHARSET_INFO * const from_cs,
708
copy_and_convert_extended(char *to, uint32 to_length, CHARSET_INFO *to_cs,
709
const char *from, uint32 from_length,
710
CHARSET_INFO *from_cs,
708
const unsigned char *from_end= (const unsigned char*) from+from_length;
715
const uchar *from_end= (const uchar*) from+from_length;
709
716
char *to_start= to;
710
unsigned char *to_end= (unsigned char*) to+to_length;
717
uchar *to_end= (uchar*) to+to_length;
711
718
my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
712
719
my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
713
uint32_t error_count= 0;
717
if ((cnvres= (*mb_wc)(from_cs, &wc, (unsigned char*) from,
724
if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from,
720
727
else if (cnvres == MY_CS_ILSEQ)
737
744
break; // Not enough characters
740
if ((cnvres= (*wc_mb)(to_cs, wc, (unsigned char*) to, to_end)) > 0)
747
if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
742
749
else if (cnvres == MY_CS_ILUNI && wc != '?')
751
758
*errors= error_count;
752
return (uint32_t) (to - to_start);
759
return (uint32) (to - to_start);
757
764
Optimized for quick copying of ASCII characters in the range 0x00..0x7F.
760
copy_and_convert(char *to, uint32_t to_length, const CHARSET_INFO * const to_cs,
761
const char *from, uint32_t from_length,
762
const CHARSET_INFO * const from_cs, uint32_t *errors)
767
copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
768
const char *from, uint32 from_length, CHARSET_INFO *from_cs,
765
772
If any of the character sets is not ASCII compatible,
769
776
return copy_and_convert_extended(to, to_length, to_cs,
770
777
from, from_length, from_cs, errors);
772
uint32_t length= cmin(to_length, from_length), length2= length;
779
uint32 length= min(to_length, from_length), length2= length;
774
781
#if defined(__i386__)
782
789
for ( ; length >= 4; length-= 4, from+= 4, to+= 4)
784
if ((*(uint32_t*)from) & 0x80808080)
791
if ((*(uint32*)from) & 0x80808080)
786
*((uint32_t*) to)= *((const uint32_t*) from);
793
*((uint32*) to)= *((const uint32*) from);
797
804
if (*((unsigned char*) from) > 0x7F) /* A non-ASCII character */
799
uint32_t copied_length= length2 - length;
806
uint32 copied_length= length2 - length;
800
807
to_length-= copied_length;
801
808
from_length-= copied_length;
802
809
return copied_length + copy_and_convert_extended(to, to_length,
836
my_copy_with_hex_escaping(const CHARSET_INFO * const cs,
843
my_copy_with_hex_escaping(CHARSET_INFO *cs,
837
844
char *dst, size_t dstlen,
838
845
const char *src, size_t srclen)
905
well_formed_copy_nchars(const CHARSET_INFO * const to_cs,
906
char *to, uint32_t to_length,
907
const CHARSET_INFO * const from_cs,
908
const char *from, uint32_t from_length,
912
well_formed_copy_nchars(CHARSET_INFO *to_cs,
913
char *to, uint to_length,
914
CHARSET_INFO *from_cs,
915
const char *from, uint from_length,
910
917
const char **well_formed_error_pos,
911
918
const char **cannot_convert_error_pos,
912
919
const char **from_end_pos)
916
923
if ((to_cs == &my_charset_bin) ||
917
924
(from_cs == &my_charset_bin) ||
929
936
if (to_cs == &my_charset_bin)
931
res= cmin(cmin(nchars, to_length), from_length);
938
res= min(min(nchars, to_length), from_length);
932
939
memmove(to, from, res);
933
940
*from_end_pos= from + res;
934
941
*well_formed_error_pos= NULL;
947
954
INSERT INTO t1 (ucs2_column) VALUES (0x01);
950
uint32_t pad_length= to_cs->mbminlen - from_offset;
951
memset(to, 0, pad_length);
957
uint pad_length= to_cs->mbminlen - from_offset;
958
bzero(to, pad_length);
952
959
memmove(to + pad_length, from, from_offset);
954
961
from+= from_offset;
975
982
my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
976
983
my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
977
const unsigned char *from_end= (const unsigned char*) from + from_length;
978
unsigned char *to_end= (unsigned char*) to + to_length;
984
const uchar *from_end= (const uchar*) from + from_length;
985
uchar *to_end= (uchar*) to + to_length;
979
986
char *to_start= to;
980
987
*well_formed_error_pos= NULL;
981
988
*cannot_convert_error_pos= NULL;
983
990
for ( ; nchars; nchars--)
985
992
const char *from_prev= from;
986
if ((cnvres= (*mb_wc)(from_cs, &wc, (unsigned char*) from, from_end)) > 0)
993
if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from, from_end)) > 0)
988
995
else if (cnvres == MY_CS_ILSEQ)
1007
1014
break; // Not enough characters
1010
if ((cnvres= (*wc_mb)(to_cs, wc, (unsigned char*) to, to_end)) > 0)
1017
if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
1012
1019
else if (cnvres == MY_CS_ILUNI && wc != '?')
1077
1084
void String::swap(String &s)
1079
std::swap(Ptr, s.Ptr);
1080
std::swap(str_length, s.str_length);
1081
std::swap(Alloced_length, s.Alloced_length);
1082
std::swap(alloced, s.alloced);
1083
std::swap(str_charset, s.str_charset);
1086
swap_variables(char *, Ptr, s.Ptr);
1087
swap_variables(uint32, str_length, s.str_length);
1088
swap_variables(uint32, Alloced_length, s.Alloced_length);
1089
swap_variables(bool, alloced, s.alloced);
1090
swap_variables(CHARSET_INFO*, str_charset, s.str_charset);