# mystring.h

Go to the documentation of this file.

    00001
    00002
    00003
    00004
    00005 /***********************************************************************
    00006  Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
    00007  (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
    00008  also hold copyrights on code in this file.  See the CREDITS.txt file
    00009  in the top directory of the distribution for details.
    00010
    00011  This file is part of MySQL++.
    00012
    00013  MySQL++ is free software; you can redistribute it and/or modify it
    00014  under the terms of the GNU Lesser General Public License as published
    00015  by the Free Software Foundation; either version 2.1 of the License, or
    00016  (at your option) any later version.
    00017
    00018  MySQL++ is distributed in the hope that it will be useful, but WITHOUT
    00019  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    00020  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
    00021  License for more details.
    00022
    00023  You should have received a copy of the GNU Lesser General Public
    00024  License along with MySQL++; if not, write to the Free Software
    00025  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
    00026  USA
    00027 ***********************************************************************/
    00028
    00029 #if !defined(MYSQLPP_MYSTRING_H)
    00030 #define MYSQLPP_MYSTRING_H
    00031
    00032 #include "common.h"
    00033
    00034 #include "datetime.h"
    00035 #include "exceptions.h"
    00036 #include "null.h"
    00037 #include "sql_buffer.h"
    00038
    00039 #include <string>
    00040 #include <sstream>
    00041 #include <limits>
    00042
    00043 #include <stdlib.h>
    00044 #include <string.h>
    00045
    00046 namespace mysqlpp {
    00047
    00048 #if !defined(DOXYGEN_IGNORE)
    00049 // Doxygen will not generate documentation for this section.
    00050
    00051 namespace detail
    00052 {
    00053         template<typename T, bool is_signed = std::numeric_limits<T>::is_signed>
    00054         struct conv_promotion;
    00055
    00056         template<>
    00057         struct conv_promotion<float>
    00058         {
    00059                 typedef double type;
    00060         };
    00061
    00062         template<>
    00063         struct conv_promotion<double>
    00064         {
    00065                 typedef double type;
    00066         };
    00067
    00068 #       if !defined(NO_LONG_LONGS)
    00069         template<>
    00070         struct conv_promotion<unsigned long long>
    00071         {
    00072                 typedef unsigned long long type;
    00073         };
    00074
    00075         template<>
    00076         struct conv_promotion<long long>
    00077         {
    00078                 typedef long long type;
    00079         };
    00080 #       endif
    00081
    00082         // preserve existing behaviour, char converted as signed long
    00083         template<>
    00084         struct conv_promotion<char>
    00085         {
    00086                 typedef long type;
    00087         };
    00088
    00089         // all other types use signed/unsigned long
    00090
    00091         template<typename T>
    00092         struct conv_promotion<T, true>
    00093         {
    00094                 typedef long type;
    00095         };
    00096
    00097         template<typename T>
    00098         struct conv_promotion<T, false>
    00099         {
    00100                 typedef unsigned long type;
    00101         };
    00102 } // namespace detail
    00103
    00104 class MYSQLPP_EXPORT SQLTypeAdapter;
    00105 #endif // !defined(DOXYGEN_IGNORE)
    00106
    00138
    00139 class MYSQLPP_EXPORT String
    00140 {
    00141 public:
    00144         typedef const char value_type;
    00145
    00147         typedef size_t size_type;
    00148
    00150         typedef const char* const_iterator;
    00151
    00154         typedef const_iterator iterator;
    00155
    00156 #if !defined(DOXYGEN_IGNORE)
    00157 // Doxygen will not generate documentation for this section.
    00158         typedef int difference_type;
    00159         typedef const char* const_pointer;
    00160         typedef const_pointer pointer;
    00161 #endif // !defined(DOXYGEN_IGNORE)
    00162
    00167         String() :
    00168         buffer_()
    00169         {
    00170         }
    00171
    00179         String(const String& other) :
    00180         buffer_(other.buffer_)
    00181         {
    00182         }
    00183
    00196         explicit String(const char* str, size_type len,
    00197                         mysql_type_info type = mysql_type_info::string_type,
    00198                         bool is_null = false) :
    00199         buffer_(new SQLBuffer(str, len, type, is_null))
    00200         {
    00201         }
    00202
    00210         explicit String(const std::string& str,
    00211                         mysql_type_info type = mysql_type_info::string_type,
    00212                         bool is_null = false) :
    00213         buffer_(new SQLBuffer(str.data(), static_cast<size_type>(str.length()),
    00214                         type, is_null))
    00215         {
    00216         }
    00217
    00225         explicit String(const char* str,
    00226                         mysql_type_info type = mysql_type_info::string_type,
    00227                         bool is_null = false) :
    00228         buffer_(new SQLBuffer(str, static_cast<size_type>(strlen(str)),
    00229                         type, is_null))
    00230         {
    00231         }
    00232
    00234         ~String() { }
    00235
    00242         void assign(const char* str, size_type len,
    00243                         mysql_type_info type = mysql_type_info::string_type,
    00244                         bool is_null = false)
    00245         {
    00246                 buffer_ = new SQLBuffer(str, len, type, is_null);
    00247         }
    00248
    00255         void assign(const std::string& str,
    00256                         mysql_type_info type = mysql_type_info::string_type,
    00257                         bool is_null = false)
    00258         {
    00259                 buffer_ = new SQLBuffer(str.data(),
    00260                                 static_cast<size_type>(str.length()), type, is_null);
    00261         }
    00262
    00269         void assign(const char* str,
    00270                         mysql_type_info type = mysql_type_info::string_type,
    00271                         bool is_null = false)
    00272         {
    00273                 buffer_ = new SQLBuffer(str, static_cast<size_type>(strlen(str)),
    00274                                 type, is_null);
    00275         }
    00276
    00281         char at(size_type pos) const;
    00282
    00285         const_iterator begin() const { return data(); }
    00286
    00288         const char* c_str() const { return data(); }
    00289
    00290 #if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
    00291 // Squish VC++ warning about "possible loss of data" for these conversions
    00292 #   pragma warning(disable: 4244)
    00293 #endif
    00294
    00297         template <class Type>
    00298         Type conv(Type) const
    00299         {
    00300                 // Conversions are done using one of double/long/ulong/llong/ullong
    00301                 // so we call a helper function to do the work using that type.
    00302                 // This reduces the amount of template code instantiated.
    00303                 typedef typename detail::conv_promotion<Type>::type conv_type;
    00304                 return do_conv<conv_type>(typeid(Type).name());
    00305         }
    00306
    00307 #if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
    00308 #   pragma warning(default: 4244)
    00309 #endif
    00310
    00317         template <class T, class B>
    00318         Null<T, B> conv(Null<T, B>) const
    00319         {
    00320                 if (is_null()) {
    00321                         return Null<T, B>(null);
    00322                 }
    00323                 else {
    00324                         return Null<T, B>(conv(T()));
    00325                 }
    00326         }
    00327
    00333         int compare(const String& other) const;
    00334
    00340         int compare(const std::string& other) const;
    00341
    00350         int compare(size_type pos, size_type num, std::string& other) const;
    00351
    00357         int compare(const char* other) const;
    00358
    00369         int compare(size_type pos, size_type num, const char* other) const;
    00370
    00373         const char* data() const;
    00374
    00376         bool empty() const { return size() == 0; }
    00377
    00380         const_iterator end() const;
    00381
    00384         bool escape_q() const;
    00385
    00387         bool is_null() const;
    00388
    00390         void it_is_null();
    00391
    00400         size_type length() const;
    00401
    00407         size_type max_size() const { return size(); }
    00408
    00411         bool quote_q() const;
    00412
    00417         size_type size() const { return length(); }
    00418
    00421         void strip_leading_blanks(std::string& s) const
    00422         {
    00423                 const char* pc = data();
    00424                 if (pc) {
    00425                         size_type n = length();
    00426                         while (n && (*pc == ' ')) {
    00427                                 ++pc;
    00428                                 --n;
    00429                         }
    00430
    00431                         s.assign(pc, n);
    00432                 }
    00433                 else {
    00434                         s.clear();
    00435                 }
    00436         }
    00437
    00445         void to_string(std::string& s) const;
    00446
    00448         mysql_type_info type() const
    00449         {
    00450                 return buffer_ ? buffer_->type() : mysql_type_info::string_type;
    00451         }
    00452
    00454         String& operator =(const std::string& rhs)
    00455         {
    00456                 buffer_ = new SQLBuffer(rhs.data(),
    00457                                 static_cast<size_type>(rhs.length()),
    00458                                 mysql_type_info::string_type, false);
    00459
    00460                 return *this;
    00461         }
    00462
    00467         String& operator =(const char* str)
    00468         {
    00469                 buffer_ = new SQLBuffer(str,
    00470                                 static_cast<size_type>(strlen(str)),
    00471                                 mysql_type_info::string_type, false);
    00472
    00473                 return *this;
    00474         }
    00475
    00481         String& operator =(const String& other)
    00482         {
    00483                 buffer_ = other.buffer_;
    00484
    00485                 return *this;
    00486         }
    00487
    00492         template <typename T>
    00493         bool operator ==(const T& rhs) const
    00494         {
    00495                 return compare(rhs) == 0;
    00496         }
    00497
    00501         bool operator ==(const mysqlpp::null_type&) const
    00502         {
    00503                 return is_null();
    00504         }
    00505
    00510         template <typename T>
    00511         bool operator !=(const T& rhs) const
    00512         {
    00513                 return compare(rhs) != 0;
    00514         }
    00515
    00519         bool operator !=(const mysqlpp::null_type&) const
    00520         {
    00521                 return !is_null();
    00522         }
    00523
    00530         char operator [](size_type pos) const { return at(pos); }
    00531
    00533         operator const char*() const { return data(); }
    00534
    00536         operator signed char() const
    00537                         { return conv(static_cast<signed char>(0)); }
    00538
    00540         operator unsigned char() const
    00541                         { return conv(static_cast<unsigned char>(0)); }
    00542
    00544         operator int() const
    00545                         { return conv(static_cast<int>(0)); }
    00546
    00548         operator unsigned int() const
    00549                         { return conv(static_cast<unsigned int>(0)); }
    00550
    00552         operator short int() const
    00553                         { return conv(static_cast<short int>(0)); }
    00554
    00557         operator unsigned short int() const
    00558                         { return conv(static_cast<unsigned short int>(0)); }
    00559
    00561         operator long int() const
    00562                         { return conv(static_cast<long int>(0)); }
    00563
    00566         operator unsigned long int() const
    00567                         { return conv(static_cast<unsigned long int>(0)); }
    00568
    00569 #if !defined(NO_LONG_LONGS)
    00572         operator longlong() const
    00573                         { return conv(static_cast<longlong>(0)); }
    00574
    00577         operator ulonglong() const
    00578                         { return conv(static_cast<ulonglong>(0)); }
    00579 #endif
    00580
    00582         operator float() const
    00583                         { return conv(static_cast<float>(0)); }
    00584
    00586         operator double() const
    00587                         { return conv(static_cast<double>(0)); }
    00588
    00590         operator bool() const { return buffer_ ? atoi(c_str()) : false; }
    00591
    00593         operator Date() const { return buffer_ ? Date(*this) : Date(); }
    00594
    00596         operator DateTime() const
    00597                         { return buffer_ ? DateTime(*this) : DateTime(); }
    00598
    00600         operator Time() const { return buffer_ ? Time(*this) : Time(); }
    00601
    00605         template <class T, class B>
    00606         operator Null<T, B>() const { return conv(Null<T, B>()); }
    00607
    00608 private:
    00610         template <class Type>
    00611         Type do_conv(const char* type_name) const
    00612         {
    00613                 if (buffer_) {
    00614                         std::stringstream buf;
    00615                         buf.write(data(), static_cast<std::streamsize>(length()));
    00616                         buf.imbue(std::locale::classic()); // "C" locale
    00617                         Type num = Type();
    00618
    00619                         if (buf >> num) {
    00620                                 char c;
    00621                                 if (!(buf >> c)) {
    00622                                         // Nothing left in buffer, so conversion complete,
    00623                                         // and thus successful.
    00624                                         return num;
    00625                                 }
    00626
    00627                                 if (c == '.' &&
    00628                                                 (typeid(Type) != typeid(float)) &&
    00629                                                 (typeid(Type) != typeid(double))) {
    00630                                         // Conversion stopped on a decimal point -- locale
    00631                                         // doesn't matter to MySQL -- so only way to succeed
    00632                                         // is if it's an integer and everything following
    00633                                         // the decimal is inconsequential.
    00634                                         c = '0';        // handles '.' at end of string
    00635                                         while (buf >> c && c == '0') /* spin */ ;
    00636                                         if (buf.eof() && c == '0') {
    00637                                                 return num;  // only zeros after decimal point
    00638                                         }
    00639                                 }
    00640                         }
    00641                         else if (buf.eof()) {
    00642                                 return num;  // nothing to convert, return default value
    00643                         }
    00644
    00645                         throw BadConversion(type_name, data(), 0, length());
    00646                 }
    00647                 else {
    00648                         return 0;
    00649                 }
    00650         }
    00651
    00652         RefCountedBuffer buffer_;
    00653
    00654         friend class SQLTypeAdapter;
    00655 };
    00656
    00657 MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& o,
    00658                 const String& in);
    00659
    00660
    00661 #if !defined(MYSQLPP_NO_BINARY_OPERS) && !defined(DOXYGEN_IGNORE)
    00662 // Ignore this section is MYSQLPP_NO_BINARY_OPERS is defined, or if this
    00663 // section is being parsed by Doxygen.  In the latter case, it's ignored
    00664 // because Doxygen doesn't understand it correctly, and we can't be
    00665 // bothered to explain it to Doxygen.
    00666
    00667 #define oprsw(opr, other, conv) \
    00668         inline other operator opr (String x, other y) \
    00669                         { return static_cast<conv>(x) opr y; } \
    00670         inline other operator opr (other x, String y) \
    00671                         { return x opr static_cast<conv>(y); }
    00672
    00673 #define operator_binary(other, conv) \
    00674         oprsw(+, other, conv) \
    00675         oprsw(-, other, conv) \
    00676         oprsw(*, other, conv) \
    00677         oprsw(/, other, conv)
    00678
    00679 #define operator_binary_int(other, conv) \
    00680         operator_binary(other, conv) \
    00681         oprsw(%, other, conv) \
    00682         oprsw(&, other, conv) \
    00683         oprsw(^, other, conv) \
    00684         oprsw(|, other, conv) \
    00685         oprsw(<<, other, conv) \
    00686         oprsw(>>, other, conv)
    00687
    00688 // Squish more complaints about possible loss of data
    00689 #if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
    00690 #       pragma warning(disable: 4244)
    00691 #endif
    00692
    00693 operator_binary(float, double)
    00694 operator_binary(double, double)
    00695
    00696 operator_binary_int(char, long int)
    00697 operator_binary_int(int, long int)
    00698 operator_binary_int(short int, long int)
    00699 operator_binary_int(long int, long int)
    00700
    00701 operator_binary_int(unsigned char, unsigned long int)
    00702 operator_binary_int(unsigned int, unsigned long int)
    00703 operator_binary_int(unsigned short int, unsigned long int)
    00704 operator_binary_int(unsigned long int, unsigned long int)
    00705
    00706 #if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
    00707 #       pragma warning(default: 4244)
    00708 #endif
    00709
    00710 #if !defined(NO_LONG_LONGS)
    00711 operator_binary_int(longlong, longlong)
    00712 operator_binary_int(ulonglong, ulonglong)
    00713 #endif // !defined(NO_LONG_LONGS)
    00714 #endif // !defined(MYSQLPP_NO_BINARY_OPERS) && !defined(DOXYGEN_IGNORE)
    00715
    00716
    00717 #if !defined(DOXYGEN_IGNORE)
    00718 // Doxygen isn't smart enough to recognize these template
    00719 // specializations.  Maybe it's the MYSQLPP_EXPORT tags?
    00720
    00726 template <> MYSQLPP_EXPORT bool String::conv(bool) const;
    00727
    00740 template <> MYSQLPP_EXPORT String String::conv(String) const;
    00741
    00743 template <> MYSQLPP_EXPORT std::string String::conv(std::string) const;
    00744
    00750 template <> MYSQLPP_EXPORT Date String::conv(Date) const;
    00751
    00757 template <> MYSQLPP_EXPORT DateTime String::conv(DateTime) const;
    00758
    00764 template <> MYSQLPP_EXPORT Time String::conv(Time) const;
    00765
    00766 #endif // !defined(DOXYGEN_IGNORE)
    00767
    00768 } // end namespace mysqlpp
    00769
    00770 #endif // !defined(MYSQLPP_MYSTRING_H)