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