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 #include <drizzled/util/data_ref.h>
00026 
00027 #include <cassert>
00028 #include <cstdlib>
00029 #include <cstring>
00030 #include <string>
00031 
00032 #include <drizzled/visibility.h>
00033 #include <drizzled/common_fwd.h>
00034 
00035 #ifndef NOT_FIXED_DEC
00036 #define NOT_FIXED_DEC     (uint8_t)31
00037 #endif
00038 
00039 namespace drizzled {
00040 
00041 extern DRIZZLED_API String my_empty_string;
00042 extern const String my_null_string;
00043 
00044 int sortcmp(const String *a,const String *b, const charset_info_st * const cs);
00045 int stringcmp(const String *a,const String *b);
00046 String *copy_if_not_alloced(String *a,String *b,size_t arg_length);
00047 size_t well_formed_copy_nchars(const charset_info_st * const to_cs,
00048                                  char *to, size_t to_length,
00049                                  const charset_info_st * const from_cs,
00050                                  const char *from, size_t from_length,
00051                                  size_t nchars,
00052                                  const char **well_formed_error_pos,
00053                                  const char **cannot_convert_error_pos,
00054                                  const char **from_end_pos);
00055 
00056 
00057 class DRIZZLED_API String
00058 {
00059   char *Ptr;
00060   size_t str_length,Alloced_length;
00061   bool alloced;
00062   const charset_info_st *str_charset;
00063 
00064 public:
00065   String();
00066   String(size_t length_arg);
00067   String(const char*, const charset_info_st*);
00068   String(const char*, size_t, const charset_info_st*);
00069   String(char *str, size_t len, const charset_info_st*);
00070   String(str_ref, const charset_info_st*);
00071   String(const String&);
00072 
00073   static void *operator new(size_t size, memory::Root *mem_root);
00074   static void operator delete(void *, size_t)
00075   { }
00076   static void operator delete(void *, memory::Root *)
00077   { }
00078   ~String();
00079 
00080   inline void set_charset(const charset_info_st * const charset_arg)
00081   { str_charset= charset_arg; }
00082   inline const charset_info_st *charset() const { return str_charset; }
00083   inline size_t length() const { return str_length;}
00084   inline size_t alloced_length() const { return Alloced_length;}
00085   inline char& operator [] (size_t i) const { return Ptr[i]; }
00086   inline void length(size_t len) { str_length=len; }
00087   inline bool empty() const { return str_length == 0; }
00088   inline void mark_as_const() { Alloced_length= 0; }
00089   inline char *ptr() { return Ptr; }
00090   inline const char *ptr() const { return Ptr; }
00091   inline char *c_ptr()
00092   {
00093     if (str_length == Alloced_length)
00094       realloc(str_length);
00095     else
00096       Ptr[str_length]= 0;
00097 
00098     return Ptr;
00099   }
00100   inline const char* begin() const
00101   {
00102     return Ptr;
00103   }
00104   inline const char* end() const
00105   {
00106     return begin() + size();
00107   }
00108   inline const char* data() const
00109   {
00110     return Ptr;
00111   }
00112   inline size_t size() const
00113   {
00114     return length();
00115   }
00116   inline const char* c_str()
00117   {
00118     if (Ptr && str_length < Alloced_length)
00119       Ptr[str_length]=0;
00120     else
00121       realloc(str_length);
00122     return Ptr;
00123   }
00124   void append_identifier(const char *name, size_t length);
00125   void append_identifier(str_ref);
00126 
00127   void set(String &str,size_t offset,size_t arg_length)
00128   {
00129     assert(&str != this);
00130     free();
00131     Ptr= str.ptr()+offset; str_length=arg_length; alloced=0;
00132     if (str.Alloced_length)
00133       Alloced_length=str.Alloced_length-offset;
00134     else
00135       Alloced_length=0;
00136     str_charset=str.str_charset;
00137   }
00138   inline void set(char *str,size_t arg_length, const charset_info_st * const cs)
00139   {
00140     free();
00141     Ptr= str; str_length=Alloced_length=arg_length ; alloced=0;
00142     str_charset=cs;
00143   }
00144 
00145   inline void set(const char *str,size_t arg_length, const charset_info_st * const cs)
00146   {
00147     free();
00148     Ptr= const_cast<char*>(str);
00149     str_length=arg_length; Alloced_length=0 ; alloced=0;
00150     str_charset=cs;
00151   }
00152   void set_ascii(const char *str, size_t arg_length);
00153 
00154   inline void set_quick(char *str,size_t arg_length, const charset_info_st * const cs)
00155   {
00156     if (!alloced)
00157     {
00158       Ptr= str; str_length= Alloced_length= arg_length;
00159     }
00160     str_charset= cs;
00161   }
00162 
00163   void set_int(int64_t num, bool unsigned_flag, const charset_info_st * const cs);
00164   void set(int64_t num, const charset_info_st * const cs)
00165   { set_int(num, false, cs); }
00166   void set(uint64_t num, const charset_info_st * const cs)
00167   { set_int(static_cast<int64_t>(num), true, cs); }
00168   void set_real(double num,size_t decimals, const charset_info_st* cs);
00169 
00170   /*
00171     PMG 2004.11.12
00172     This is a method that works the same as perl's "chop". It simply
00173     drops the last character of a string. This is useful in the case
00174     of the federated storage handler where I'm building a unknown
00175     number, list of values and fields to be used in a sql insert
00176     statement to be run on the remote server, and have a comma after each.
00177     When the list is complete, I "chop" off the trailing comma
00178 
00179     ex.
00180       String stringobj;
00181       stringobj.append("VALUES ('foo', 'fi', 'fo',");
00182       stringobj.chop();
00183       stringobj.append(")");
00184 
00185     In this case, the value of string was:
00186 
00187     VALUES ('foo', 'fi', 'fo',
00188     VALUES ('foo', 'fi', 'fo'
00189     VALUES ('foo', 'fi', 'fo')
00190 
00191   */
00192   inline void chop()
00193   {
00194     Ptr[str_length--]= '\0';
00195   }
00196 
00197   inline void free()
00198   {
00199     if (alloced)
00200     {
00201       alloced=0;
00202       Alloced_length=0;
00203       ::free(Ptr);
00204       Ptr=0;
00205       str_length=0;       /* Safety */
00206     }
00207   }
00208   inline void alloc(size_t arg_length)
00209   {
00210     if (arg_length >= Alloced_length)
00211       real_alloc(arg_length);
00212   }
00213   void real_alloc(size_t arg_length);     // Empties old string
00214   void 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; } const
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   void copy();          // Alloc string if not alloced
00250   void copy(const String&);     // Allocate new string
00251   void copy(const std::string&, const charset_info_st*);  // Allocate new string
00252   void copy(const char*, size_t, const charset_info_st*); // Allocate new string
00253   static bool needs_conversion(size_t arg_length, const charset_info_st* cs_from, const charset_info_st* cs_to);
00254   void set_or_copy_aligned(const char *s, size_t arg_length, const charset_info_st*);
00255   void copy(const char*s,size_t arg_length, const charset_info_st& csto);
00256   void append(const char*);
00257   void append(const char*, size_t);
00258   void append(str_ref);
00259   void append_with_prefill(const char *s, size_t arg_length, size_t full_length, char fill_char);
00260   int strstr(const String &search,size_t offset=0); // Returns offset to substring or -1
00261   int strrstr(const String &search,size_t offset=0); // Returns offset to substring or -1
00262   void replace(size_t offset,size_t arg_length,const char *to,size_t length);
00263   void replace(size_t offset,size_t arg_length,const String &to);
00264 
00265   inline void append(char chr)
00266   {
00267     if (str_length < Alloced_length)
00268     {
00269       Ptr[str_length++]=chr;
00270     }
00271     else
00272     {
00273       realloc(str_length+1);
00274       Ptr[str_length++]=chr;
00275     }
00276   }
00277   friend int sortcmp(const String *a,const String *b, const charset_info_st * const cs);
00278   friend int stringcmp(const String *a,const String *b);
00279   friend String *copy_if_not_alloced(String *a,String *b,size_t arg_length);
00280   size_t numchars() const;
00281   int charpos(int i, size_t offset= 0) const;
00282 
00283   void reserve(size_t space_needed)
00284   {
00285     realloc(str_length + space_needed);
00286   }
00287   void reserve(size_t space_needed, size_t grow_by);
00288 
00289   inline void append(const char *s, size_t arg_length, size_t step_alloc)
00290   {
00291     size_t new_length= arg_length + str_length;
00292     if (new_length > Alloced_length)
00293       realloc(new_length + step_alloc);
00294     memcpy(Ptr+str_length, s, arg_length);
00295     str_length+= arg_length;
00296   }
00297 
00298   void print(String&) const;
00299 
00300   /* Swap two string objects. Efficient way to exchange data without memcpy. */
00301   void swap(String &s);
00302 
00303   inline bool uses_buffer_owned_by(const String *s) const
00304   {
00305     return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length);
00306   }
00307 };
00308 
00309 bool check_if_only_end_space(const charset_info_st* const, char *str, char *end);
00310 
00311 std::ostream& operator<<(std::ostream&, const String&);
00312 
00313 } /* namespace drizzled */
00314 
00315 bool operator==(const drizzled::String &s1, const drizzled::String &s2);
00316 bool operator!=(const drizzled::String &s1, const drizzled::String &s2);