My Project
sql_string.h
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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines