00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <config.h>
00019
00020 #include <drizzled/internal/my_sys.h>
00021 #include <drizzled/internal/m_string.h>
00022 #include <drizzled/charset.h>
00023 #include <drizzled/global_charset_info.h>
00024
00025 #include <algorithm>
00026
00027 #include <drizzled/sql_string.h>
00028
00029 using namespace std;
00030
00031 namespace drizzled
00032 {
00033
00034
00035
00036 std::string String_to_std_string(String const& s)
00037 {
00038 return std::string(s.ptr(), s.length());
00039 }
00040
00041 String* set_String_from_std_string(String* s, std::string const& cs)
00042 {
00043 s->set_ascii(cs.c_str(), cs.length());
00044 s->copy();
00045 return s;
00046 }
00047
00048
00049
00050
00051
00052 String::String()
00053 : Ptr(NULL),
00054 str_length(0),
00055 Alloced_length(0),
00056 alloced(false),
00057 str_charset(&my_charset_bin)
00058 { }
00059
00060
00061 String::String(size_t length_arg)
00062 : Ptr(NULL),
00063 str_length(0),
00064 Alloced_length(0),
00065 alloced(false),
00066 str_charset(&my_charset_bin)
00067 {
00068 (void) real_alloc(length_arg);
00069 }
00070
00071 String::String(const char *str, const CHARSET_INFO * const cs)
00072 : Ptr(const_cast<char *>(str)),
00073 str_length(static_cast<size_t>(strlen(str))),
00074 Alloced_length(0),
00075 alloced(false),
00076 str_charset(cs)
00077 { }
00078
00079
00080 String::String(const char *str, size_t len, const CHARSET_INFO * const cs)
00081 : Ptr(const_cast<char *>(str)),
00082 str_length(len),
00083 Alloced_length(0),
00084 alloced(false),
00085 str_charset(cs)
00086 { }
00087
00088
00089 String::String(char *str, size_t len, const CHARSET_INFO * const cs)
00090 : Ptr(str),
00091 str_length(len),
00092 Alloced_length(len),
00093 alloced(false),
00094 str_charset(cs)
00095 { }
00096
00097
00098 String::String(const String &str)
00099 : Ptr(str.Ptr),
00100 str_length(str.str_length),
00101 Alloced_length(str.Alloced_length),
00102 alloced(false),
00103 str_charset(str.str_charset)
00104 { }
00105
00106
00107 void *String::operator new(size_t size, memory::Root *mem_root)
00108 {
00109 return mem_root->alloc_root(static_cast<size_t>(size));
00110 }
00111
00112 String::~String() { free(); }
00113
00114 bool String::real_alloc(size_t arg_length)
00115 {
00116 arg_length=ALIGN_SIZE(arg_length+1);
00117 str_length=0;
00118 if (Alloced_length < arg_length)
00119 {
00120 if (Alloced_length > 0)
00121 free();
00122 if (!(Ptr=(char*) malloc(arg_length)))
00123 return true;
00124 Alloced_length=arg_length;
00125 alloced=1;
00126 }
00127 Ptr[0]=0;
00128 return false;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137 bool String::realloc(size_t alloc_length)
00138 {
00139 size_t len=ALIGN_SIZE(alloc_length+1);
00140 if (Alloced_length < len)
00141 {
00142 char *new_ptr;
00143 if (alloced)
00144 {
00145 if ((new_ptr= (char*) ::realloc(Ptr,len)))
00146 {
00147 Ptr=new_ptr;
00148 Alloced_length=len;
00149 }
00150 else
00151 return true;
00152 }
00153 else if ((new_ptr= (char*) malloc(len)))
00154 {
00155 if (str_length)
00156 memcpy(new_ptr,Ptr,str_length);
00157 new_ptr[str_length]=0;
00158 Ptr=new_ptr;
00159 Alloced_length=len;
00160 alloced=1;
00161 }
00162 else
00163 return true;
00164 }
00165 Ptr[alloc_length]=0;
00166 return false;
00167 }
00168
00169 bool String::set_int(int64_t num, bool unsigned_flag, const CHARSET_INFO * const cs)
00170 {
00171 size_t l=20*cs->mbmaxlen+1;
00172 int base= unsigned_flag ? 10 : -10;
00173
00174 if (alloc(l))
00175 return true;
00176 str_length=(size_t) (cs->cset->int64_t10_to_str)(cs,Ptr,l,base,num);
00177 str_charset=cs;
00178 return false;
00179 }
00180
00181 bool String::set_real(double num,size_t decimals, const CHARSET_INFO * const cs)
00182 {
00183 char buff[FLOATING_POINT_BUFFER];
00184 size_t dummy_errors;
00185 size_t len;
00186
00187 str_charset=cs;
00188 if (decimals >= NOT_FIXED_DEC)
00189 {
00190 len= internal::my_gcvt(num,
00191 internal::MY_GCVT_ARG_DOUBLE,
00192 sizeof(buff) - 1, buff, NULL);
00193 return copy(buff, len, &my_charset_utf8_general_ci, cs, &dummy_errors);
00194 }
00195 len= internal::my_fcvt(num, decimals, buff, NULL);
00196 return copy(buff, (size_t) len, &my_charset_utf8_general_ci, cs,
00197 &dummy_errors);
00198 }
00199
00200
00201 bool String::copy()
00202 {
00203 if (!alloced)
00204 {
00205 Alloced_length=0;
00206 return realloc(str_length);
00207 }
00208 return false;
00209 }
00210
00211 bool String::copy(const String &str)
00212 {
00213 if (alloc(str.str_length))
00214 return true;
00215 str_length=str.str_length;
00216 memmove(Ptr, str.Ptr, str_length);
00217 Ptr[str_length]=0;
00218 str_charset=str.str_charset;
00219 return false;
00220 }
00221
00222 bool String::copy(const std::string& arg, const CHARSET_INFO * const cs)
00223 {
00224 if (alloc(arg.size()))
00225 return true;
00226
00227 if ((str_length= arg.size()))
00228 memcpy(Ptr, arg.c_str(), arg.size());
00229
00230 Ptr[arg.size()]= 0;
00231 str_charset= cs;
00232
00233 return false;
00234 }
00235
00236 bool String::copy(const char *str,size_t arg_length, const CHARSET_INFO * const cs)
00237 {
00238 if (alloc(arg_length))
00239 return true;
00240 if ((str_length=arg_length))
00241 memcpy(Ptr,str,arg_length);
00242 Ptr[arg_length]=0;
00243 str_charset=cs;
00244 return false;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 bool String::needs_conversion(size_t arg_length,
00270 const CHARSET_INFO * const from_cs,
00271 const CHARSET_INFO * const to_cs,
00272 size_t *offset)
00273 {
00274 *offset= 0;
00275 if (!to_cs ||
00276 (to_cs == &my_charset_bin) ||
00277 (to_cs == from_cs) ||
00278 my_charset_same(from_cs, to_cs) ||
00279 ((from_cs == &my_charset_bin) &&
00280 (!(*offset=(arg_length % to_cs->mbminlen)))))
00281 return false;
00282 return true;
00283 }
00284
00285
00286
00287
00288 bool String::set_or_copy_aligned(const char *str,size_t arg_length,
00289 const CHARSET_INFO * const cs)
00290 {
00291
00292 size_t offset= (arg_length % cs->mbminlen);
00293
00294 assert(!offset);
00295
00296 set(str, arg_length, cs);
00297 return false;
00298 }
00299
00300
00301
00302 bool String::copy(const char *str, size_t arg_length,
00303 const CHARSET_INFO * const,
00304 const CHARSET_INFO * const to_cs, size_t *errors)
00305 {
00306 *errors= 0;
00307 return copy(str, arg_length, to_cs);
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 bool String::set_ascii(const char *str, size_t arg_length)
00331 {
00332 if (str_charset->mbminlen == 1)
00333 {
00334 set(str, arg_length, str_charset);
00335 return 0;
00336 }
00337 size_t dummy_errors;
00338 return copy(str, arg_length, &my_charset_utf8_general_ci, str_charset, &dummy_errors);
00339 }
00340
00341 bool String::append(const String &s)
00342 {
00343 if (s.length())
00344 {
00345 if (realloc(str_length+s.length()))
00346 return true;
00347 memcpy(Ptr+str_length,s.ptr(),s.length());
00348 str_length+=s.length();
00349 }
00350 return false;
00351 }
00352
00353
00354
00355
00356
00357
00358 bool String::append(const char *s,size_t arg_length)
00359 {
00360 if (!arg_length)
00361 return false;
00362
00363
00364
00365
00366 if (realloc(str_length+arg_length))
00367 return true;
00368 memcpy(Ptr+str_length,s,arg_length);
00369 str_length+=arg_length;
00370 return false;
00371 }
00372
00373
00374
00375
00376
00377
00378 bool String::append(const char *s)
00379 {
00380 return append(s, strlen(s));
00381 }
00382
00383
00384
00385
00386
00387
00388
00389 bool String::append(const char *s,size_t arg_length, const CHARSET_INFO * const)
00390 {
00391 if (realloc(str_length + arg_length))
00392 return true;
00393 memcpy(Ptr + str_length, s, arg_length);
00394 str_length+= arg_length;
00395
00396 return false;
00397 }
00398
00399
00400 bool String::append_with_prefill(const char *s,size_t arg_length,
00401 size_t full_length, char fill_char)
00402 {
00403 int t_length= arg_length > full_length ? arg_length : full_length;
00404
00405 if (realloc(str_length + t_length))
00406 return true;
00407 t_length= full_length - arg_length;
00408 if (t_length > 0)
00409 {
00410 memset(Ptr+str_length, fill_char, t_length);
00411 str_length=str_length + t_length;
00412 }
00413 append(s, arg_length);
00414 return false;
00415 }
00416
00417 size_t String::numchars()
00418 {
00419 return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
00420 }
00421
00422 int String::charpos(int i,size_t offset)
00423 {
00424 if (i <= 0)
00425 return i;
00426 return str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,i);
00427 }
00428
00429 int String::strstr(const String &s,size_t offset)
00430 {
00431 if (s.length()+offset <= str_length)
00432 {
00433 if (!s.length())
00434 return ((int) offset);
00435
00436 const char *str = Ptr+offset;
00437 const char *search=s.ptr();
00438 const char *end=Ptr+str_length-s.length()+1;
00439 const char *search_end=s.ptr()+s.length();
00440 skip:
00441 while (str != end)
00442 {
00443 if (*str++ == *search)
00444 {
00445 char *i,*j;
00446 i=(char*) str; j=(char*) search+1;
00447 while (j != search_end)
00448 if (*i++ != *j++) goto skip;
00449 return (int) (str-Ptr) -1;
00450 }
00451 }
00452 }
00453 return -1;
00454 }
00455
00456
00457
00458
00459
00460 int String::strrstr(const String &s,size_t offset)
00461 {
00462 if (s.length() <= offset && offset <= str_length)
00463 {
00464 if (!s.length())
00465 return offset;
00466 const char *str = Ptr+offset-1;
00467 const char *search=s.ptr()+s.length()-1;
00468
00469 const char *end=Ptr+s.length()-2;
00470 const char *search_end=s.ptr()-1;
00471 skip:
00472 while (str != end)
00473 {
00474 if (*str-- == *search)
00475 {
00476 char *i,*j;
00477 i=(char*) str; j=(char*) search-1;
00478 while (j != search_end)
00479 if (*i-- != *j--) goto skip;
00480 return (int) (i-Ptr) +1;
00481 }
00482 }
00483 }
00484 return -1;
00485 }
00486
00487
00488
00489
00490
00491
00492 bool String::replace(size_t offset,size_t arg_length,const String &to)
00493 {
00494 return replace(offset,arg_length,to.ptr(),to.length());
00495 }
00496
00497 bool String::replace(size_t offset,size_t arg_length,
00498 const char *to, size_t to_length)
00499 {
00500 long diff = (long) to_length-(long) arg_length;
00501 if (offset+arg_length <= str_length)
00502 {
00503 if (diff < 0)
00504 {
00505 if (to_length)
00506 memcpy(Ptr+offset,to,to_length);
00507 memmove(Ptr+offset+to_length, Ptr+offset+arg_length,
00508 str_length-offset-arg_length);
00509 }
00510 else
00511 {
00512 if (diff)
00513 {
00514 if (realloc(str_length+(size_t) diff))
00515 return true;
00516 internal::bmove_upp((unsigned char*) Ptr+str_length+diff,
00517 (unsigned char*) Ptr+str_length,
00518 str_length-offset-arg_length);
00519 }
00520 if (to_length)
00521 memcpy(Ptr+offset,to,to_length);
00522 }
00523 str_length+=(size_t) diff;
00524 }
00525 return false;
00526 }
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549 int sortcmp(const String *s,const String *t, const CHARSET_INFO * const cs)
00550 {
00551 return cs->coll->strnncollsp(cs,
00552 (unsigned char *) s->ptr(),s->length(),
00553 (unsigned char *) t->ptr(),t->length(), 0);
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 int stringcmp(const String *s,const String *t)
00576 {
00577 size_t s_len= s->length(), t_len= t->length(), len= min(s_len,t_len);
00578 int cmp= memcmp(s->ptr(), t->ptr(), len);
00579 return (cmp) ? cmp : (int) (s_len - t_len);
00580 }
00581
00582
00583 String *copy_if_not_alloced(String *to,String *from,size_t from_length)
00584 {
00585 if (from->Alloced_length >= from_length)
00586 return from;
00587 if (from->alloced || !to || from == to)
00588 {
00589 (void) from->realloc(from_length);
00590 return from;
00591 }
00592 if (to->realloc(from_length))
00593 return from;
00594 if ((to->str_length= min(from->str_length,from_length)))
00595 memcpy(to->Ptr,from->Ptr,to->str_length);
00596 to->str_charset=from->str_charset;
00597 return to;
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 size_t
00633 well_formed_copy_nchars(const CHARSET_INFO * const to_cs,
00634 char *to, size_t to_length,
00635 const CHARSET_INFO * const from_cs,
00636 const char *from, size_t from_length,
00637 size_t nchars,
00638 const char **well_formed_error_pos,
00639 const char **cannot_convert_error_pos,
00640 const char **from_end_pos)
00641 {
00642 size_t res;
00643
00644 assert((to_cs == &my_charset_bin) ||
00645 (from_cs == &my_charset_bin) ||
00646 (to_cs == from_cs) ||
00647 my_charset_same(from_cs, to_cs));
00648
00649 if (to_length < to_cs->mbminlen || !nchars)
00650 {
00651 *from_end_pos= from;
00652 *cannot_convert_error_pos= NULL;
00653 *well_formed_error_pos= NULL;
00654 return 0;
00655 }
00656
00657 if (to_cs == &my_charset_bin)
00658 {
00659 res= min(min(nchars, to_length), from_length);
00660 memmove(to, from, res);
00661 *from_end_pos= from + res;
00662 *well_formed_error_pos= NULL;
00663 *cannot_convert_error_pos= NULL;
00664 }
00665 else
00666 {
00667 int well_formed_error;
00668 size_t from_offset;
00669
00670 if ((from_offset= (from_length % to_cs->mbminlen)) &&
00671 (from_cs == &my_charset_bin))
00672 {
00673
00674
00675
00676
00677
00678 size_t pad_length= to_cs->mbminlen - from_offset;
00679 memset(to, 0, pad_length);
00680 memmove(to + pad_length, from, from_offset);
00681 nchars--;
00682 from+= from_offset;
00683 from_length-= from_offset;
00684 to+= to_cs->mbminlen;
00685 to_length-= to_cs->mbminlen;
00686 }
00687
00688 set_if_smaller(from_length, to_length);
00689 res= to_cs->cset->well_formed_len(to_cs, from, from + from_length,
00690 nchars, &well_formed_error);
00691 memmove(to, from, res);
00692 *from_end_pos= from + res;
00693 *well_formed_error_pos= well_formed_error ? from + res : NULL;
00694 *cannot_convert_error_pos= NULL;
00695 if (from_offset)
00696 res+= to_cs->mbminlen;
00697 }
00698
00699 return res;
00700 }
00701
00702
00703
00704
00705 void String::print(String *str)
00706 {
00707 char *st= (char*)Ptr, *end= st+str_length;
00708 for (; st < end; st++)
00709 {
00710 unsigned char c= *st;
00711 switch (c)
00712 {
00713 case '\\':
00714 str->append("\\\\", sizeof("\\\\")-1);
00715 break;
00716 case '\0':
00717 str->append("\\0", sizeof("\\0")-1);
00718 break;
00719 case '\'':
00720 str->append("\\'", sizeof("\\'")-1);
00721 break;
00722 case '\n':
00723 str->append("\\n", sizeof("\\n")-1);
00724 break;
00725 case '\r':
00726 str->append("\\r", sizeof("\\r")-1);
00727 break;
00728 case '\032':
00729 str->append("\\Z", sizeof("\\Z")-1);
00730 break;
00731 default:
00732 str->append(c);
00733 }
00734 }
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748 extern const CHARSET_INFO *system_charset_info, *files_charset_info;
00749
00750 void String::append_identifier(const char *name, size_t in_length)
00751 {
00752 const char *name_end;
00753 char quote_char;
00754 int q= '`';
00755
00756
00757
00758
00759
00760
00761 reserve(in_length*2 + 2);
00762 quote_char= (char) q;
00763 append("e_char, 1, system_charset_info);
00764
00765 for (name_end= name+in_length ; name < name_end ; name+= in_length)
00766 {
00767 unsigned char chr= (unsigned char) *name;
00768 in_length= my_mbcharlen(system_charset_info, chr);
00769
00770
00771
00772
00773
00774
00775
00776 if (!in_length)
00777 in_length= 1;
00778 if (in_length == 1 && chr == (unsigned char) quote_char)
00779 append("e_char, 1, system_charset_info);
00780 append(name, in_length, system_charset_info);
00781 }
00782 append("e_char, 1, system_charset_info);
00783 }
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 void String::swap(String &s)
00797 {
00798 std::swap(Ptr, s.Ptr);
00799 std::swap(str_length, s.str_length);
00800 std::swap(Alloced_length, s.Alloced_length);
00801 std::swap(alloced, s.alloced);
00802 std::swap(str_charset, s.str_charset);
00803 }
00804
00805 void String::q_append(const size_t n)
00806 {
00807 int8store(Ptr + str_length, n);
00808 str_length += 4;
00809 }
00810 void String::q_append(double d)
00811 {
00812 float8store(Ptr + str_length, d);
00813 str_length += 8;
00814 }
00815 void String::q_append(double *d)
00816 {
00817 float8store(Ptr + str_length, *d);
00818 str_length += 8;
00819 }
00820 void String::q_append(const char *data, size_t data_len)
00821 {
00822 memcpy(Ptr + str_length, data, data_len);
00823 str_length += data_len;
00824 }
00825
00826 void String::write_at_position(int position, size_t value)
00827 {
00828 int8store(Ptr + position,value);
00829 }
00830 bool check_if_only_end_space(const CHARSET_INFO * const cs, char *str,
00831 char *end)
00832 {
00833 return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end;
00834 }
00835
00836 std::ostream& operator<<(std::ostream& output, const String &str)
00837 {
00838 output << "String:(";
00839 output << const_cast<String&>(str).c_str();
00840 output << ", ";
00841 output << str.length();
00842 output << ")";
00843
00844 return output;
00845 }
00846
00847 }
00848
00849 bool operator==(const drizzled::String &s1, const drizzled::String &s2)
00850 {
00851 return stringcmp(&s1,&s2) == 0;
00852 }
00853
00854 bool operator!=(const drizzled::String &s1, const drizzled::String &s2)
00855 {
00856 return !(s1 == s2);
00857 }
00858