1 #ifndef CLIENT_SQL_STRING_INCLUDED 2 #define CLIENT_SQL_STRING_INCLUDED 3 4 /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; version 2 of the License. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 18 19 /* This file is originally from the mysql distribution. Coded by monty */ 20 21 #ifdef USE_PRAGMA_INTERFACE 22 #pragma interface /* gcc class implementation */ 23 #endif 24 25 class String; 26 int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); 27 String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); 28 uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, 29 const char *from, uint32 from_length, 30 CHARSET_INFO *from_cs, uint *errors); 31 32 class String 33 { 34 char *Ptr; 35 uint32 str_length,Alloced_length; 36 bool alloced; 37 CHARSET_INFO *str_charset; 38 public: String()39 String() 40 { 41 Ptr=0; str_length=Alloced_length=0; alloced=0; 42 str_charset= &my_charset_bin; 43 } String(uint32 length_arg)44 String(uint32 length_arg) 45 { 46 alloced=0; Alloced_length=0; (void) real_alloc(length_arg); 47 str_charset= &my_charset_bin; 48 } String(const char * str,CHARSET_INFO * cs)49 String(const char *str, CHARSET_INFO *cs) 50 { 51 Ptr=(char*) str; str_length=(uint) strlen(str); Alloced_length=0; alloced=0; 52 str_charset=cs; 53 } String(const char * str,uint32 len,CHARSET_INFO * cs)54 String(const char *str,uint32 len, CHARSET_INFO *cs) 55 { 56 Ptr=(char*) str; str_length=len; Alloced_length=0; alloced=0; 57 str_charset=cs; 58 } String(char * str,uint32 len,CHARSET_INFO * cs)59 String(char *str,uint32 len, CHARSET_INFO *cs) 60 { 61 Ptr=(char*) str; Alloced_length=str_length=len; alloced=0; 62 str_charset=cs; 63 } String(const String & str)64 String(const String &str) 65 { 66 Ptr=str.Ptr ; str_length=str.str_length ; 67 Alloced_length=str.Alloced_length; alloced=0; 68 str_charset=str.str_charset; 69 } new(size_t size,MEM_ROOT * mem_root)70 static void *operator new(size_t size, MEM_ROOT *mem_root) 71 { return (void*) alloc_root(mem_root, (uint) size); } delete(void * ptr_arg,size_t size)72 static void operator delete(void *ptr_arg, size_t size) 73 { 74 (void) ptr_arg; 75 (void) size; 76 TRASH(ptr_arg, size); 77 } delete(void *,MEM_ROOT *)78 static void operator delete(void *, MEM_ROOT *) 79 { /* never called */ } ~String()80 ~String() { free(); } 81 set_charset(CHARSET_INFO * charset_arg)82 inline void set_charset(CHARSET_INFO *charset_arg) 83 { str_charset= charset_arg; } charset()84 inline CHARSET_INFO *charset() const { return str_charset; } length()85 inline uint32 length() const { return str_length;} alloced_length()86 inline uint32 alloced_length() const { return Alloced_length;} 87 inline char& operator [] (uint32 i) const { return Ptr[i]; } length(uint32 len)88 inline void length(uint32 len) { str_length=len ; } is_empty()89 inline bool is_empty() { return (str_length == 0); } mark_as_const()90 inline void mark_as_const() { Alloced_length= 0;} ptr()91 inline const char *ptr() const { return Ptr; } c_ptr()92 inline char *c_ptr() 93 { 94 if (!Ptr || Ptr[str_length]) /* Should be safe */ 95 (void) realloc(str_length); 96 return Ptr; 97 } c_ptr_quick()98 inline char *c_ptr_quick() 99 { 100 if (Ptr && str_length < Alloced_length) 101 Ptr[str_length]=0; 102 return Ptr; 103 } c_ptr_safe()104 inline char *c_ptr_safe() 105 { 106 if (Ptr && str_length < Alloced_length) 107 Ptr[str_length]=0; 108 else 109 (void) realloc(str_length); 110 return Ptr; 111 } 112 set(String & str,uint32 offset,uint32 arg_length)113 void set(String &str,uint32 offset,uint32 arg_length) 114 { 115 DBUG_ASSERT(&str != this); 116 free(); 117 Ptr=(char*) str.ptr()+offset; str_length=arg_length; alloced=0; 118 if (str.Alloced_length) 119 Alloced_length=str.Alloced_length-offset; 120 else 121 Alloced_length=0; 122 str_charset=str.str_charset; 123 } set(char * str,uint32 arg_length,CHARSET_INFO * cs)124 inline void set(char *str,uint32 arg_length, CHARSET_INFO *cs) 125 { 126 free(); 127 Ptr=(char*) str; str_length=Alloced_length=arg_length ; alloced=0; 128 str_charset=cs; 129 } set(const char * str,uint32 arg_length,CHARSET_INFO * cs)130 inline void set(const char *str,uint32 arg_length, CHARSET_INFO *cs) 131 { 132 free(); 133 Ptr=(char*) str; str_length=arg_length; Alloced_length=0 ; alloced=0; 134 str_charset=cs; 135 } 136 bool set_ascii(const char *str, uint32 arg_length); set_quick(char * str,uint32 arg_length,CHARSET_INFO * cs)137 inline void set_quick(char *str,uint32 arg_length, CHARSET_INFO *cs) 138 { 139 if (!alloced) 140 { 141 Ptr=(char*) str; str_length=Alloced_length=arg_length; 142 } 143 str_charset=cs; 144 } 145 bool set(longlong num, CHARSET_INFO *cs); 146 bool set(ulonglong num, CHARSET_INFO *cs); 147 bool set(double num,uint decimals, CHARSET_INFO *cs); 148 149 /* 150 PMG 2004.11.12 151 This is a method that works the same as perl's "chop". It simply 152 drops the last character of a string. This is useful in the case 153 of the federated storage handler where I'm building a unknown 154 number, list of values and fields to be used in a sql insert 155 statement to be run on the remote server, and have a comma after each. 156 When the list is complete, I "chop" off the trailing comma 157 158 ex. 159 String stringobj; 160 stringobj.append("VALUES ('foo', 'fi', 'fo',"); 161 stringobj.chop(); 162 stringobj.append(")"); 163 164 In this case, the value of string was: 165 166 VALUES ('foo', 'fi', 'fo', 167 VALUES ('foo', 'fi', 'fo' 168 VALUES ('foo', 'fi', 'fo') 169 170 */ chop()171 inline void chop() 172 { 173 Ptr[str_length--]= '\0'; 174 } 175 free()176 inline void free() 177 { 178 if (alloced) 179 { 180 alloced=0; 181 Alloced_length=0; 182 my_free(Ptr); 183 Ptr=0; 184 str_length=0; /* Safety */ 185 } 186 } alloc(uint32 arg_length)187 inline bool alloc(uint32 arg_length) 188 { 189 if (arg_length < Alloced_length) 190 return 0; 191 return real_alloc(arg_length); 192 } 193 bool real_alloc(uint32 arg_length); // Empties old string 194 bool realloc(uint32 arg_length); 195 196 // Shrink the buffer, but only if it is allocated on the heap. shrink(uint32 arg_length)197 inline void shrink(uint32 arg_length) 198 { 199 if (!is_alloced()) 200 return; 201 if (arg_length < Alloced_length) 202 { 203 char *new_ptr; 204 if (!(new_ptr=(char*) my_realloc(Ptr,arg_length,MYF(0)))) 205 { 206 Alloced_length = 0; 207 real_alloc(arg_length); 208 } 209 else 210 { 211 Ptr=new_ptr; 212 Alloced_length=arg_length; 213 } 214 } 215 } is_alloced()216 bool is_alloced() const { return alloced; } 217 inline String& operator = (const String &s) 218 { 219 if (&s != this) 220 { 221 /* 222 It is forbidden to do assignments like 223 some_string = substring_of_that_string 224 */ 225 DBUG_ASSERT(!s.uses_buffer_owned_by(this)); 226 free(); 227 Ptr=s.Ptr ; str_length=s.str_length ; Alloced_length=s.Alloced_length; 228 str_charset=s.str_charset; 229 alloced=0; 230 } 231 return *this; 232 } 233 234 bool copy(); // Alloc string if not alloced 235 bool copy(const String &s); // Allocate new string 236 bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string 237 static bool needs_conversion(uint32 arg_length, 238 CHARSET_INFO *cs_from, CHARSET_INFO *cs_to, 239 uint32 *offset); 240 bool copy_aligned(const char *s, uint32 arg_length, uint32 offset, 241 CHARSET_INFO *cs); 242 bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs); 243 bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, 244 CHARSET_INFO *csto, uint *errors); 245 bool append(const String &s); 246 bool append(const char *s); 247 bool append(const char *s,uint32 arg_length); 248 bool append(const char *s,uint32 arg_length, CHARSET_INFO *cs); 249 bool append(IO_CACHE* file, uint32 arg_length); 250 bool append_with_prefill(const char *s, uint32 arg_length, 251 uint32 full_length, char fill_char); 252 int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 253 int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 254 bool replace(uint32 offset,uint32 arg_length,const char *to,uint32 length); 255 bool replace(uint32 offset,uint32 arg_length,const String &to); append(char chr)256 inline bool append(char chr) 257 { 258 if (str_length < Alloced_length) 259 { 260 Ptr[str_length++]=chr; 261 } 262 else 263 { 264 if (realloc(str_length+1)) 265 return 1; 266 Ptr[str_length++]=chr; 267 } 268 return 0; 269 } 270 bool fill(uint32 max_length,char fill); 271 void strip_sp(); 272 friend int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); 273 friend int stringcmp(const String *a,const String *b); 274 friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); 275 uint32 numchars(); 276 int charpos(int i,uint32 offset=0); 277 reserve(uint32 space_needed)278 int reserve(uint32 space_needed) 279 { 280 return realloc(str_length + space_needed); 281 } 282 int reserve(uint32 space_needed, uint32 grow_by); 283 284 /* 285 The following append operations do NOT check alloced memory 286 q_*** methods writes values of parameters itself 287 qs_*** methods writes string representation of value 288 */ q_append(const char c)289 void q_append(const char c) 290 { 291 Ptr[str_length++] = c; 292 } q_append(const uint32 n)293 void q_append(const uint32 n) 294 { 295 int4store(Ptr + str_length, n); 296 str_length += 4; 297 } q_append(double d)298 void q_append(double d) 299 { 300 float8store(Ptr + str_length, d); 301 str_length += 8; 302 } q_append(double * d)303 void q_append(double *d) 304 { 305 float8store(Ptr + str_length, *d); 306 str_length += 8; 307 } q_append(const char * data,uint32 data_len)308 void q_append(const char *data, uint32 data_len) 309 { 310 memcpy(Ptr + str_length, data, data_len); 311 str_length += data_len; 312 } 313 write_at_position(int position,uint32 value)314 void write_at_position(int position, uint32 value) 315 { 316 int4store(Ptr + position,value); 317 } 318 319 void qs_append(const char *str, uint32 len); 320 void qs_append(double d); 321 void qs_append(double *d); qs_append(const char c)322 inline void qs_append(const char c) 323 { 324 Ptr[str_length]= c; 325 str_length++; 326 } 327 void qs_append(int i); 328 void qs_append(uint i); 329 330 /* Inline (general) functions used by the protocol functions */ 331 prep_append(uint32 arg_length,uint32 step_alloc)332 inline char *prep_append(uint32 arg_length, uint32 step_alloc) 333 { 334 uint32 new_length= arg_length + str_length; 335 if (new_length > Alloced_length) 336 { 337 if (realloc(new_length + step_alloc)) 338 return 0; 339 } 340 uint32 old_length= str_length; 341 str_length+= arg_length; 342 return Ptr+ old_length; /* Area to use */ 343 } 344 append(const char * s,uint32 arg_length,uint32 step_alloc)345 inline bool append(const char *s, uint32 arg_length, uint32 step_alloc) 346 { 347 uint32 new_length= arg_length + str_length; 348 if (new_length > Alloced_length && realloc(new_length + step_alloc)) 349 return TRUE; 350 memcpy(Ptr+str_length, s, arg_length); 351 str_length+= arg_length; 352 return FALSE; 353 } 354 void print(String *print); 355 356 /* Swap two string objects. Efficient way to exchange data without memcpy. */ 357 void swap(String &s); 358 uses_buffer_owned_by(const String * s)359 inline bool uses_buffer_owned_by(const String *s) const 360 { 361 return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length); 362 } 363 }; 364 365 #endif /* CLIENT_SQL_STRING_INCLUDED */ 366