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