Drizzled Public API Documentation

sql_string.h

00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
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 
00020 #pragma once
00021 
00022 /* This file is originally from the mysql distribution. Coded by monty */
00023 
00024 #include <drizzled/common.h>
00025 
00026 #include <cassert>
00027 #include <cstdlib>
00028 #include <cstring>
00029 #include <string>
00030 
00031 #include <drizzled/visibility.h>
00032 
00033 #ifndef NOT_FIXED_DEC
00034 #define NOT_FIXED_DEC     (uint8_t)31
00035 #endif
00036 
00037 namespace drizzled
00038 {
00039 
00040 class String;
00041 
00042 extern DRIZZLED_API String my_empty_string;
00043 extern const String my_null_string;
00044 namespace memory { class Root; }
00045 typedef struct charset_info_st CHARSET_INFO;
00046 
00047 DRIZZLED_API std::string String_to_std_string(String const& s);
00048 DRIZZLED_API String* set_String_from_std_string(String* s, std::string const& cs);
00049 
00050 int sortcmp(const String *a,const String *b, const CHARSET_INFO * const cs);
00051 int stringcmp(const String *a,const String *b);
00052 String *copy_if_not_alloced(String *a,String *b,size_t arg_length);
00053 size_t well_formed_copy_nchars(const CHARSET_INFO * const to_cs,
00054                                  char *to, size_t to_length,
00055                                  const CHARSET_INFO * const from_cs,
00056                                  const char *from, size_t from_length,
00057                                  size_t nchars,
00058                                  const char **well_formed_error_pos,
00059                                  const char **cannot_convert_error_pos,
00060                                  const char **from_end_pos);
00061 
00062 
00063 class DRIZZLED_API String
00064 {
00065   char *Ptr;
00066   size_t str_length,Alloced_length;
00067   bool alloced;
00068   const CHARSET_INFO *str_charset;
00069 
00070 public:
00071   String();
00072   String(size_t length_arg);
00073   String(const char *str, const CHARSET_INFO * const cs);
00074   String(const char *str, size_t len, const CHARSET_INFO * const cs);
00075   String(char *str, size_t len, const CHARSET_INFO * const cs);
00076   String(const String &str);
00077 
00078   static void *operator new(size_t size, memory::Root *mem_root);
00079   static void operator delete(void *, size_t)
00080   { }
00081   static void operator delete(void *, memory::Root *)
00082   { }
00083   ~String();
00084 
00085   inline void set_charset(const CHARSET_INFO * const charset_arg)
00086   { str_charset= charset_arg; }
00087   inline const CHARSET_INFO *charset() const { return str_charset; }
00088   inline size_t length() const { return str_length;}
00089   inline size_t alloced_length() const { return Alloced_length;}
00090   inline char& operator [] (size_t i) const { return Ptr[i]; }
00091   inline void length(size_t len) { str_length=len ; }
00092   inline bool is_empty() { return (str_length == 0); }
00093   inline void mark_as_const() { Alloced_length= 0;}
00094   inline char *ptr() { return Ptr; }
00095   inline const char *ptr() const { return Ptr; }
00096   inline char *c_ptr()
00097   {
00098     if (str_length == Alloced_length)
00099       (void) realloc(str_length);
00100     else
00101       Ptr[str_length]= 0;
00102 
00103     return Ptr;
00104   }
00105   inline char *c_ptr_quick()
00106   {
00107     if (Ptr && str_length < Alloced_length)
00108       Ptr[str_length]=0;
00109     return Ptr;
00110   }
00111   inline char *c_ptr_safe()
00112   {
00113     if (Ptr && str_length < Alloced_length)
00114       Ptr[str_length]=0;
00115     else
00116       (void) realloc(str_length);
00117     return Ptr;
00118   }
00119   inline char *c_str()
00120   {
00121     if (Ptr && str_length < Alloced_length)
00122       Ptr[str_length]=0;
00123     else
00124       (void) realloc(str_length);
00125     return Ptr;
00126   }
00127   void append_identifier(const char *name, size_t length);
00128 
00129   void set(String &str,size_t offset,size_t arg_length)
00130   {
00131     assert(&str != this);
00132     free();
00133     Ptr= str.ptr()+offset; str_length=arg_length; alloced=0;
00134     if (str.Alloced_length)
00135       Alloced_length=str.Alloced_length-offset;
00136     else
00137       Alloced_length=0;
00138     str_charset=str.str_charset;
00139   }
00140   inline void set(char *str,size_t arg_length, const CHARSET_INFO * const cs)
00141   {
00142     free();
00143     Ptr= str; str_length=Alloced_length=arg_length ; alloced=0;
00144     str_charset=cs;
00145   }
00146   inline void set(const char *str,size_t arg_length, const CHARSET_INFO * const cs)
00147   {
00148     free();
00149     Ptr= const_cast<char*>(str);
00150     str_length=arg_length; Alloced_length=0 ; alloced=0;
00151     str_charset=cs;
00152   }
00153   bool set_ascii(const char *str, size_t arg_length);
00154   inline void set_quick(char *str,size_t arg_length, const CHARSET_INFO * const cs)
00155   {
00156     if (!alloced)
00157     {
00158       Ptr= str; str_length= Alloced_length= arg_length;
00159     }
00160     str_charset= cs;
00161   }
00162   bool set_int(int64_t num, bool unsigned_flag, const CHARSET_INFO * const cs);
00163   bool set(int64_t num, const CHARSET_INFO * const cs)
00164   { return set_int(num, false, cs); }
00165   bool set(uint64_t num, const CHARSET_INFO * const cs)
00166   { return set_int(static_cast<int64_t>(num), true, cs); }
00167   bool set_real(double num,size_t decimals, const CHARSET_INFO * const cs);
00168 
00169   /*
00170     PMG 2004.11.12
00171     This is a method that works the same as perl's "chop". It simply
00172     drops the last character of a string. This is useful in the case
00173     of the federated storage handler where I'm building a unknown
00174     number, list of values and fields to be used in a sql insert
00175     statement to be run on the remote server, and have a comma after each.
00176     When the list is complete, I "chop" off the trailing comma
00177 
00178     ex.
00179       String stringobj;
00180       stringobj.append("VALUES ('foo', 'fi', 'fo',");
00181       stringobj.chop();
00182       stringobj.append(")");
00183 
00184     In this case, the value of string was:
00185 
00186     VALUES ('foo', 'fi', 'fo',
00187     VALUES ('foo', 'fi', 'fo'
00188     VALUES ('foo', 'fi', 'fo')
00189 
00190   */
00191   inline void chop()
00192   {
00193     Ptr[str_length--]= '\0';
00194   }
00195 
00196   inline void free()
00197   {
00198     if (alloced)
00199     {
00200       alloced=0;
00201       Alloced_length=0;
00202       ::free(Ptr);
00203       Ptr=0;
00204       str_length=0;       /* Safety */
00205     }
00206   }
00207   inline bool alloc(size_t arg_length)
00208   {
00209     if (arg_length < Alloced_length)
00210       return 0;
00211     return real_alloc(arg_length);
00212   }
00213   bool real_alloc(size_t arg_length);     // Empties old string
00214   bool realloc(size_t arg_length);
00215   inline void shrink(size_t arg_length)   // Shrink buffer
00216   {
00217     if (arg_length < Alloced_length)
00218     {
00219       char *new_ptr;
00220       if (!(new_ptr= reinterpret_cast<char*>(::realloc(Ptr,arg_length))))
00221       {
00222         Alloced_length = 0;
00223         real_alloc(arg_length);
00224       }
00225       else
00226       {
00227         Ptr=new_ptr;
00228         Alloced_length=arg_length;
00229       }
00230     }
00231   }
00232   bool is_alloced() { return alloced; }
00233   inline String& operator = (const String &s)
00234   {
00235     if (&s != this)
00236     {
00237       /*
00238         It is forbidden to do assignments like
00239         some_string = substring_of_that_string
00240        */
00241       assert(!s.uses_buffer_owned_by(this));
00242       free();
00243       Ptr=s.Ptr ; str_length=s.str_length ; Alloced_length=s.Alloced_length;
00244       alloced=0;
00245     }
00246     return *this;
00247   }
00248 
00249   bool copy();          // Alloc string if not alloced
00250   bool copy(const String &s);     // Allocate new string
00251   bool copy(const std::string&, const CHARSET_INFO * const cs); // Allocate new string
00252   bool copy(const char *s,size_t arg_length, const CHARSET_INFO * const cs);  // Allocate new string
00253   static bool needs_conversion(size_t arg_length,
00254                const CHARSET_INFO * const cs_from, const CHARSET_INFO * const cs_to,
00255              size_t *offset);
00256   bool set_or_copy_aligned(const char *s, size_t arg_length, const CHARSET_INFO * const cs);
00257   bool copy(const char*s,size_t arg_length, const CHARSET_INFO * const csfrom,
00258             const CHARSET_INFO * const csto, size_t *errors);
00259   bool append(const String &s);
00260   bool append(const char *s);
00261   bool append(const char *s,size_t arg_length);
00262   bool append(const char *s,size_t arg_length, const CHARSET_INFO * const cs);
00263   bool append_with_prefill(const char *s, size_t arg_length,
00264          size_t full_length, char fill_char);
00265   int strstr(const String &search,size_t offset=0); // Returns offset to substring or -1
00266   int strrstr(const String &search,size_t offset=0); // Returns offset to substring or -1
00267   bool replace(size_t offset,size_t arg_length,const char *to,size_t length);
00268   bool replace(size_t offset,size_t arg_length,const String &to);
00269   inline bool append(char chr)
00270   {
00271     if (str_length < Alloced_length)
00272     {
00273       Ptr[str_length++]=chr;
00274     }
00275     else
00276     {
00277       if (realloc(str_length+1))
00278         return 1;
00279       Ptr[str_length++]=chr;
00280     }
00281     return 0;
00282   }
00283   friend int sortcmp(const String *a,const String *b, const CHARSET_INFO * const cs);
00284   friend int stringcmp(const String *a,const String *b);
00285   friend String *copy_if_not_alloced(String *a,String *b,size_t arg_length);
00286   size_t numchars();
00287   int charpos(int i,size_t offset=0);
00288 
00289   int reserve(size_t space_needed)
00290   {
00291     return realloc(str_length + space_needed);
00292   }
00293   int reserve(size_t space_needed, size_t grow_by);
00294 
00295   /*
00296     The following append operations do NOT check alloced memory
00297     q_*** methods writes values of parameters itself
00298     qs_*** methods writes string representation of value
00299   */
00300   void q_append(const char c);
00301   void q_append(const size_t n);
00302   void q_append(double d);
00303   void q_append(double *d);
00304   void q_append(const char *data, size_t data_len);
00305   void write_at_position(int position, size_t value);
00306 
00307   /* Inline (general) functions used by the protocol functions */
00308 
00309   inline char *prep_append(size_t arg_length, size_t step_alloc)
00310   {
00311     size_t new_length= arg_length + str_length;
00312     if (new_length > Alloced_length)
00313     {
00314       if (realloc(new_length + step_alloc))
00315         return 0;
00316     }
00317     size_t old_length= str_length;
00318     str_length+= arg_length;
00319     return Ptr+ old_length;     /* Area to use */
00320   }
00321 
00322   inline bool append(const char *s, size_t arg_length, size_t step_alloc)
00323   {
00324     size_t new_length= arg_length + str_length;
00325     if (new_length > Alloced_length && realloc(new_length + step_alloc))
00326       return true;
00327     memcpy(Ptr+str_length, s, arg_length);
00328     str_length+= arg_length;
00329     return false;
00330   }
00331   void print(String *print);
00332 
00333   /* Swap two string objects. Efficient way to exchange data without memcpy. */
00334   void swap(String &s);
00335 
00336   inline bool uses_buffer_owned_by(const String *s) const
00337   {
00338     return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length);
00339   }
00340 };
00341 
00342 bool check_if_only_end_space(const CHARSET_INFO * const cs, char *str,
00343                              char *end);
00344 
00345 std::ostream& operator<<(std::ostream& output, const String &str);
00346 
00347 } /* namespace drizzled */
00348 
00349 bool operator==(const drizzled::String &s1, const drizzled::String &s2);
00350 bool operator!=(const drizzled::String &s1, const drizzled::String &s2);
00351 
00352