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