My Project
|
00001 #ifndef SQL_STRING_INCLUDED 00002 #define SQL_STRING_INCLUDED 00003 00004 /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; version 2 of the License. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00018 00019 /* This file is originally from the mysql distribution. Coded by monty */ 00020 00021 #include "m_ctype.h" /* my_charset_bin */ 00022 #include "my_sys.h" /* alloc_root, my_free, my_realloc */ 00023 #include "m_string.h" /* TRASH */ 00024 00025 00037 class Simple_cstring 00038 { 00039 private: 00040 const char *m_str; 00041 size_t m_length; 00042 protected: 00046 void set(const char *str_arg, size_t length_arg) 00047 { 00048 // NULL is allowed only with length==0 00049 DBUG_ASSERT(str_arg || length_arg == 0); 00050 // For non-NULL, make sure length_arg is in sync with '\0' terminator. 00051 DBUG_ASSERT(!str_arg || str_arg[length_arg] == '\0'); 00052 m_str= str_arg; 00053 m_length= length_arg; 00054 } 00055 public: 00056 Simple_cstring() 00057 { 00058 set(NULL, 0); 00059 } 00060 Simple_cstring(const char *str_arg, size_t length_arg) 00061 { 00062 set(str_arg, length_arg); 00063 } 00064 Simple_cstring(const LEX_STRING arg) 00065 { 00066 set(arg.str, arg.length); 00067 } 00068 void reset() 00069 { 00070 set(NULL, 0); 00071 } 00075 void set(const char *str) 00076 { 00077 set(str, str ? strlen(str) : 0); 00078 } 00082 const char *ptr() const { return m_str; } 00086 bool is_set() const { return m_str != NULL; } 00090 size_t length() const { return m_length; } 00094 bool eq_bin(const Simple_cstring other) const 00095 { 00096 return m_length == other.m_length && 00097 memcmp(m_str, other.m_str, m_length) == 0; 00098 } 00102 void strcpy(char *buff) const 00103 { 00104 memcpy(buff, m_str, m_length); 00105 buff[m_length]= '\0'; 00106 } 00107 }; 00108 00109 00110 class String; 00111 typedef struct charset_info_st CHARSET_INFO; 00112 typedef struct st_io_cache IO_CACHE; 00113 typedef struct st_mem_root MEM_ROOT; 00114 00115 int sortcmp(const String *a,const String *b, const CHARSET_INFO *cs); 00116 String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); 00117 inline uint32 copy_and_convert(char *to, uint32 to_length, 00118 const CHARSET_INFO *to_cs, 00119 const char *from, uint32 from_length, 00120 const CHARSET_INFO *from_cs, uint *errors) 00121 { 00122 return my_convert(to, to_length, to_cs, from, from_length, from_cs, errors); 00123 } 00124 uint32 well_formed_copy_nchars(const CHARSET_INFO *to_cs, 00125 char *to, uint to_length, 00126 const CHARSET_INFO *from_cs, 00127 const char *from, uint from_length, 00128 uint nchars, 00129 const char **well_formed_error_pos, 00130 const char **cannot_convert_error_pos, 00131 const char **from_end_pos); 00132 size_t my_copy_with_hex_escaping(const CHARSET_INFO *cs, 00133 char *dst, size_t dstlen, 00134 const char *src, size_t srclen); 00135 uint convert_to_printable(char *to, size_t to_len, 00136 const char *from, size_t from_len, 00137 const CHARSET_INFO *from_cs, size_t nbytes= 0); 00138 00139 class String 00140 { 00141 char *Ptr; 00142 uint32 str_length,Alloced_length; 00143 bool alloced; 00144 const CHARSET_INFO *str_charset; 00145 public: 00146 String() 00147 { 00148 Ptr=0; str_length=Alloced_length=0; alloced=0; 00149 str_charset= &my_charset_bin; 00150 } 00151 String(uint32 length_arg) 00152 { 00153 alloced=0; Alloced_length=0; (void) real_alloc(length_arg); 00154 str_charset= &my_charset_bin; 00155 } 00156 String(const char *str, const CHARSET_INFO *cs) 00157 { 00158 Ptr=(char*) str; str_length=(uint) strlen(str); Alloced_length=0; alloced=0; 00159 str_charset=cs; 00160 } 00161 String(const char *str,uint32 len, const CHARSET_INFO *cs) 00162 { 00163 Ptr=(char*) str; str_length=len; Alloced_length=0; alloced=0; 00164 str_charset=cs; 00165 } 00166 String(char *str,uint32 len, const CHARSET_INFO *cs) 00167 { 00168 Ptr=(char*) str; Alloced_length=str_length=len; alloced=0; 00169 str_charset=cs; 00170 } 00171 String(const String &str) 00172 { 00173 Ptr=str.Ptr ; str_length=str.str_length ; 00174 Alloced_length=str.Alloced_length; alloced=0; 00175 str_charset=str.str_charset; 00176 } 00177 static void *operator new(size_t size, MEM_ROOT *mem_root) throw () 00178 { return (void*) alloc_root(mem_root, (uint) size); } 00179 static void operator delete(void *ptr_arg, size_t size) 00180 { 00181 (void) ptr_arg; 00182 (void) size; 00183 TRASH(ptr_arg, size); 00184 } 00185 static void operator delete(void *, MEM_ROOT *) 00186 { /* never called */ } 00187 ~String() { free(); } 00188 00189 inline void set_charset(const CHARSET_INFO *charset_arg) 00190 { str_charset= charset_arg; } 00191 inline const CHARSET_INFO *charset() const { return str_charset; } 00192 inline uint32 length() const { return str_length;} 00193 inline uint32 alloced_length() const { return Alloced_length;} 00194 inline char& operator [] (uint32 i) const { return Ptr[i]; } 00195 inline void length(uint32 len) { str_length=len ; } 00196 inline bool is_empty() const { return (str_length == 0); } 00197 inline void mark_as_const() { Alloced_length= 0;} 00198 inline const char *ptr() const { return Ptr; } 00199 inline char *c_ptr() 00200 { 00201 DBUG_ASSERT(!alloced || !Ptr || !Alloced_length || 00202 (Alloced_length >= (str_length + 1))); 00203 00204 if (!Ptr || Ptr[str_length]) /* Should be safe */ 00205 (void) realloc(str_length); 00206 return Ptr; 00207 } 00208 inline char *c_ptr_quick() 00209 { 00210 if (Ptr && str_length < Alloced_length) 00211 Ptr[str_length]=0; 00212 return Ptr; 00213 } 00214 inline char *c_ptr_safe() 00215 { 00216 if (Ptr && str_length < Alloced_length) 00217 Ptr[str_length]=0; 00218 else 00219 (void) realloc(str_length); 00220 return Ptr; 00221 } 00222 LEX_STRING lex_string() const 00223 { 00224 LEX_STRING lex_string = { (char*) ptr(), length() }; 00225 return lex_string; 00226 } 00227 00228 void set(String &str,uint32 offset,uint32 arg_length) 00229 { 00230 DBUG_ASSERT(&str != this); 00231 free(); 00232 Ptr=(char*) str.ptr()+offset; str_length=arg_length; alloced=0; 00233 if (str.Alloced_length) 00234 Alloced_length=str.Alloced_length-offset; 00235 else 00236 Alloced_length=0; 00237 str_charset=str.str_charset; 00238 } 00239 00240 00249 inline void set(char *str,uint32 arg_length, const CHARSET_INFO *cs) 00250 { 00251 free(); 00252 Ptr=(char*) str; str_length=Alloced_length=arg_length ; alloced=0; 00253 str_charset=cs; 00254 } 00255 inline void set(const char *str,uint32 arg_length, const CHARSET_INFO *cs) 00256 { 00257 free(); 00258 Ptr=(char*) str; str_length=arg_length; Alloced_length=0 ; alloced=0; 00259 str_charset=cs; 00260 } 00261 bool set_ascii(const char *str, uint32 arg_length); 00262 inline void set_quick(char *str,uint32 arg_length, const CHARSET_INFO *cs) 00263 { 00264 if (!alloced) 00265 { 00266 Ptr=(char*) str; str_length=Alloced_length=arg_length; 00267 } 00268 str_charset=cs; 00269 } 00270 bool set_int(longlong num, bool unsigned_flag, const CHARSET_INFO *cs); 00271 bool set(longlong num, const CHARSET_INFO *cs) 00272 { return set_int(num, false, cs); } 00273 bool set(ulonglong num, const CHARSET_INFO *cs) 00274 { return set_int((longlong)num, true, cs); } 00275 bool set_real(double num,uint decimals, const CHARSET_INFO *cs); 00276 00277 /* 00278 PMG 2004.11.12 00279 This is a method that works the same as perl's "chop". It simply 00280 drops the last character of a string. This is useful in the case 00281 of the federated storage handler where I'm building a unknown 00282 number, list of values and fields to be used in a sql insert 00283 statement to be run on the remote server, and have a comma after each. 00284 When the list is complete, I "chop" off the trailing comma 00285 00286 ex. 00287 String stringobj; 00288 stringobj.append("VALUES ('foo', 'fi', 'fo',"); 00289 stringobj.chop(); 00290 stringobj.append(")"); 00291 00292 In this case, the value of string was: 00293 00294 VALUES ('foo', 'fi', 'fo', 00295 VALUES ('foo', 'fi', 'fo' 00296 VALUES ('foo', 'fi', 'fo') 00297 00298 */ 00299 inline void chop() 00300 { 00301 str_length--; 00302 Ptr[str_length]= '\0'; 00303 DBUG_ASSERT(strlen(Ptr) == str_length); 00304 } 00305 00306 inline void free() 00307 { 00308 if (alloced) 00309 { 00310 alloced=0; 00311 Alloced_length=0; 00312 my_free(Ptr); 00313 Ptr=0; 00314 str_length=0; /* Safety */ 00315 } 00316 } 00317 inline bool alloc(uint32 arg_length) 00318 { 00319 if (arg_length < Alloced_length) 00320 return 0; 00321 return real_alloc(arg_length); 00322 } 00323 bool real_alloc(uint32 arg_length); // Empties old string 00324 bool realloc(uint32 arg_length); 00325 00326 // Shrink the buffer, but only if it is allocated on the heap. 00327 inline void shrink(uint32 arg_length) 00328 { 00329 if (!is_alloced()) 00330 return; 00331 if (arg_length < Alloced_length) 00332 { 00333 char *new_ptr; 00334 if (!(new_ptr=(char*) my_realloc(Ptr,arg_length,MYF(0)))) 00335 { 00336 Alloced_length = 0; 00337 real_alloc(arg_length); 00338 } 00339 else 00340 { 00341 Ptr=new_ptr; 00342 Alloced_length=arg_length; 00343 } 00344 } 00345 } 00346 bool is_alloced() const { return alloced; } 00347 inline String& operator = (const String &s) 00348 { 00349 if (&s != this) 00350 { 00351 /* 00352 It is forbidden to do assignments like 00353 some_string = substring_of_that_string 00354 */ 00355 DBUG_ASSERT(!s.uses_buffer_owned_by(this)); 00356 free(); 00357 Ptr=s.Ptr ; str_length=s.str_length ; Alloced_length=s.Alloced_length; 00358 str_charset=s.str_charset; 00359 alloced=0; 00360 } 00361 return *this; 00362 } 00371 inline void takeover(String &s) 00372 { 00373 DBUG_ASSERT(this != &s); 00374 // Make sure buffers of the two Strings do not overlap 00375 DBUG_ASSERT(!s.uses_buffer_owned_by(this)); 00376 free(); 00377 Ptr= s.Ptr; 00378 str_length= s.str_length; 00379 Alloced_length= s.Alloced_length; 00380 alloced= s.alloced; 00381 str_charset= s.str_charset; 00382 s.Ptr= NULL; 00383 s.Alloced_length= 0; 00384 s.str_length= 0; 00385 s.alloced= 0; 00386 } 00387 00388 bool copy(); // Alloc string if not alloced 00389 bool copy(const String &s); // Allocate new string 00390 // Allocate new string 00391 bool copy(const char *s,uint32 arg_length, const CHARSET_INFO *cs); 00392 static bool needs_conversion(uint32 arg_length, 00393 const CHARSET_INFO *cs_from, const CHARSET_INFO *cs_to, 00394 uint32 *offset); 00395 static bool needs_conversion_on_storage(uint32 arg_length, 00396 const CHARSET_INFO *cs_from, 00397 const CHARSET_INFO *cs_to); 00398 bool copy_aligned(const char *s, uint32 arg_length, uint32 offset, 00399 const CHARSET_INFO *cs); 00400 bool set_or_copy_aligned(const char *s, uint32 arg_length, 00401 const CHARSET_INFO *cs); 00402 bool copy(const char*s,uint32 arg_length, const CHARSET_INFO *csfrom, 00403 const CHARSET_INFO *csto, uint *errors); 00404 bool append(const String &s); 00405 bool append(const char *s); 00406 bool append(LEX_STRING *ls) 00407 { 00408 return append(ls->str, (uint32) ls->length); 00409 } 00410 bool append(Simple_cstring str) 00411 { 00412 return append(str.ptr(), static_cast<uint>(str.length())); 00413 } 00414 bool append(const char *s, uint32 arg_length); 00415 bool append(const char *s, uint32 arg_length, const CHARSET_INFO *cs); 00416 bool append_ulonglong(ulonglong val); 00417 bool append(IO_CACHE* file, uint32 arg_length); 00418 bool append_with_prefill(const char *s, uint32 arg_length, 00419 uint32 full_length, char fill_char); 00420 bool append_parenthesized(long nr, int radix= 10); 00421 int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 00422 int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 00423 bool replace(uint32 offset,uint32 arg_length,const char *to,uint32 length); 00424 bool replace(uint32 offset,uint32 arg_length,const String &to); 00425 inline bool append(char chr) 00426 { 00427 if (str_length < Alloced_length) 00428 { 00429 Ptr[str_length++]=chr; 00430 } 00431 else 00432 { 00433 if (realloc(str_length+1)) 00434 return 1; 00435 Ptr[str_length++]=chr; 00436 } 00437 return 0; 00438 } 00439 bool fill(uint32 max_length,char fill); 00440 void strip_sp(); 00441 friend int sortcmp(const String *a,const String *b, const CHARSET_INFO *cs); 00442 friend int stringcmp(const String *a,const String *b); 00443 friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); 00444 uint32 numchars() const; 00445 int charpos(int i,uint32 offset=0); 00446 00447 int reserve(uint32 space_needed) 00448 { 00449 return realloc(str_length + space_needed); 00450 } 00451 int reserve(uint32 space_needed, uint32 grow_by); 00452 /* 00453 The following append operations do NOT check alloced memory 00454 q_*** methods writes values of parameters itself 00455 qs_*** methods writes string representation of value 00456 */ 00457 void q_append(const char c) 00458 { 00459 Ptr[str_length++] = c; 00460 } 00461 void q_append(const uint32 n) 00462 { 00463 int4store(Ptr + str_length, n); 00464 str_length += 4; 00465 } 00466 void q_append(double d) 00467 { 00468 float8store(Ptr + str_length, d); 00469 str_length += 8; 00470 } 00471 void q_append(double *d) 00472 { 00473 float8store(Ptr + str_length, *d); 00474 str_length += 8; 00475 } 00476 void q_append(const char *data, uint32 data_len) 00477 { 00478 memcpy(Ptr + str_length, data, data_len); 00479 str_length += data_len; 00480 } 00481 00482 void write_at_position(int position, uint32 value) 00483 { 00484 int4store(Ptr + position,value); 00485 } 00486 00487 void qs_append(const char *str, uint32 len); 00488 void qs_append(double d); 00489 void qs_append(double *d); 00490 inline void qs_append(const char c) 00491 { 00492 Ptr[str_length]= c; 00493 str_length++; 00494 } 00495 void qs_append(int i); 00496 void qs_append(uint i); 00497 00498 /* Inline (general) functions used by the protocol functions */ 00499 00500 inline char *prep_append(uint32 arg_length, uint32 step_alloc) 00501 { 00502 uint32 new_length= arg_length + str_length; 00503 if (new_length > Alloced_length) 00504 { 00505 if (realloc(new_length + step_alloc)) 00506 return 0; 00507 } 00508 uint32 old_length= str_length; 00509 str_length+= arg_length; 00510 return Ptr+ old_length; /* Area to use */ 00511 } 00512 00513 inline bool append(const char *s, uint32 arg_length, uint32 step_alloc) 00514 { 00515 uint32 new_length= arg_length + str_length; 00516 if (new_length > Alloced_length && realloc(new_length + step_alloc)) 00517 return TRUE; 00518 memcpy(Ptr+str_length, s, arg_length); 00519 str_length+= arg_length; 00520 return FALSE; 00521 } 00522 void print(String *print); 00523 00524 /* Swap two string objects. Efficient way to exchange data without memcpy. */ 00525 void swap(String &s); 00526 00527 inline bool uses_buffer_owned_by(const String *s) const 00528 { 00529 return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length); 00530 } 00531 bool is_ascii() const 00532 { 00533 if (length() == 0) 00534 return TRUE; 00535 if (charset()->mbminlen > 1) 00536 return FALSE; 00537 for (const char *c= ptr(), *end= c + length(); c < end; c++) 00538 { 00539 if (!my_isascii(*c)) 00540 return FALSE; 00541 } 00542 return TRUE; 00543 } 00551 char *dup(MEM_ROOT *root) const 00552 { 00553 if (str_length > 0 && Ptr[str_length - 1] == 0) 00554 return static_cast<char *>(memdup_root(root, Ptr, str_length)); 00555 00556 char *ret= static_cast<char*>(alloc_root(root, str_length + 1)); 00557 if (ret != NULL) 00558 { 00559 memcpy(ret, Ptr, str_length); 00560 ret[str_length]= 0; 00561 } 00562 return ret; 00563 } 00564 }; 00565 00566 00578 template<size_t buff_sz> 00579 class StringBuffer : public String 00580 { 00581 char buff[buff_sz]; 00582 00583 public: 00584 StringBuffer() : String(buff, buff_sz, &my_charset_bin) { length(0); } 00585 explicit StringBuffer(const CHARSET_INFO *cs) : String(buff, buff_sz, cs) 00586 { 00587 length(0); 00588 } 00589 StringBuffer(const char *str, size_t length, const CHARSET_INFO *cs) 00590 : String(buff, buff_sz, cs) 00591 { 00592 set(str, length, cs); 00593 } 00594 }; 00595 00596 00597 static inline bool check_if_only_end_space(const CHARSET_INFO *cs, char *str, 00598 char *end) 00599 { 00600 return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end; 00601 } 00602 00603 #endif /* SQL_STRING_INCLUDED */