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