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 file in
00009  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         
00377         const_iterator end() const;
00378 
00381         bool escape_q() const;
00382 
00384         bool is_null() const;
00385 
00387         void it_is_null();
00388 
00397         size_type length() const;
00398         
00404         size_type max_size() const { return size(); }
00405 
00408         bool quote_q() const;
00409 
00414         size_type size() const { return length(); }
00415         
00418     void strip_leading_blanks(std::string& s) const
00419     {
00420         const char* pc = data();
00421         if (pc) {
00422             size_type n = length();
00423             while (n && (*pc == ' ')) {
00424                 ++pc;
00425                 --n;
00426             }
00427 
00428             s.assign(pc, n);
00429         }
00430         else {
00431             s.clear();
00432         }
00433     }
00434 
00442         void to_string(std::string& s) const;
00443 
00445         mysql_type_info type() const
00446         {
00447                 return buffer_ ? buffer_->type() : mysql_type_info::string_type;
00448         }
00449 
00451         String& operator =(const std::string& rhs)
00452         {
00453                 buffer_ = new SQLBuffer(rhs.data(), 
00454                                 static_cast<size_type>(rhs.length()),
00455                                 mysql_type_info::string_type, false);
00456 
00457                 return *this;
00458         }
00459 
00464         String& operator =(const char* str)
00465         {
00466                 buffer_ = new SQLBuffer(str, 
00467                                 static_cast<size_type>(strlen(str)),
00468                                 mysql_type_info::string_type, false);
00469 
00470                 return *this;
00471         }
00472 
00478         String& operator =(const String& other)
00479         {
00480                 buffer_ = other.buffer_;
00481 
00482                 return *this;
00483         }
00484 
00489         template <typename T>
00490         bool operator ==(const T& rhs) const
00491         {
00492                 return compare(rhs) == 0;
00493         }
00494 
00498         bool operator ==(const mysqlpp::null_type&) const
00499         {
00500                 return is_null();
00501         }
00502 
00507         template <typename T>
00508         bool operator !=(const T& rhs) const
00509         {
00510                 return compare(rhs) != 0;
00511         }
00512 
00516         bool operator !=(const mysqlpp::null_type&) const
00517         {
00518                 return !is_null();
00519         }
00520 
00525         char operator [](size_type pos) const;
00526 
00528         operator const char*() const { return data(); }
00529         
00531         operator signed char() const
00532                         { return conv(static_cast<signed char>(0)); }
00533         
00535         operator unsigned char() const
00536                         { return conv(static_cast<unsigned char>(0)); }
00537         
00539         operator int() const
00540                         { return conv(static_cast<int>(0)); }
00541         
00543         operator unsigned int() const
00544                         { return conv(static_cast<unsigned int>(0)); }
00545         
00547         operator short int() const
00548                         { return conv(static_cast<short int>(0)); }
00549         
00552         operator unsigned short int() const
00553                         { return conv(static_cast<unsigned short int>(0)); }
00554         
00556         operator long int() const
00557                         { return conv(static_cast<long int>(0)); }
00558         
00561         operator unsigned long int() const
00562                         { return conv(static_cast<unsigned long int>(0)); }
00563         
00564 #if !defined(NO_LONG_LONGS)
00567         operator longlong() const
00568                         { return conv(static_cast<longlong>(0)); }
00569         
00572         operator ulonglong() const
00573                         { return conv(static_cast<ulonglong>(0)); }
00574 #endif
00575         
00577         operator float() const
00578                         { return conv(static_cast<float>(0)); }
00579         
00581         operator double() const
00582                         { return conv(static_cast<double>(0)); }
00583         
00585         operator bool() const { return buffer_ ? atoi(c_str()) : false; }
00586 
00588         operator Date() const { return buffer_ ? Date(*this) : Date(); }
00589 
00591         operator DateTime() const
00592                         { return buffer_ ? DateTime(*this) : DateTime(); }
00593 
00595         operator Time() const { return buffer_ ? Time(*this) : Time(); }
00596 
00600         template <class T, class B>
00601         operator Null<T, B>() const { return conv(Null<T, B>()); }
00602 
00603 private:
00605         template <class Type>
00606         Type do_conv(const char* type_name) const
00607         {
00608                 if (buffer_) {
00609                         std::stringstream buf;
00610                         buf.write(data(), static_cast<std::streamsize>(length()));
00611                         buf.imbue(std::locale::classic()); // "C" locale
00612                         Type num = Type();
00613                         
00614                         if (buf >> num) {
00615                                 char c;
00616                                 if (!(buf >> c)) {
00617                                         // Nothing left in buffer, so conversion complete,
00618                                         // and thus successful.
00619                                         return num;
00620                                 }
00621 
00622                                 if (c == '.' &&
00623                                                 (typeid(Type) != typeid(float)) &&
00624                                                 (typeid(Type) != typeid(double))) {
00625                                         // Conversion stopped on a decimal point -- locale
00626                                         // doesn't matter to MySQL -- so only way to succeed
00627                                         // is if it's an integer and everything following
00628                                         // the decimal is inconsequential.
00629                                         c = '0';        // handles '.' at end of string
00630                                         while (buf >> c && c == '0') /* spin */ ;
00631                                         if (buf.eof() && c == '0') {
00632                                                 return num;  // only zeros after decimal point
00633                                         }
00634                                 }
00635                         }
00636                         else if (buf.eof()) {
00637                                 return num;  // nothing to convert, return default value
00638                         }
00639 
00640                         throw BadConversion(type_name, data(), 0, length());
00641                 }
00642                 else {
00643                         return 0;
00644                 }
00645         }
00646 
00647         RefCountedBuffer buffer_;       
00648 
00649         friend class SQLTypeAdapter;
00650 };
00651 
00652 MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& o,
00653                 const String& in);
00654 
00655 
00656 #if !defined(MYSQLPP_NO_BINARY_OPERS) && !defined(DOXYGEN_IGNORE)
00657 // Ignore this section is MYSQLPP_NO_BINARY_OPERS is defined, or if this
00658 // section is being parsed by Doxygen.  In the latter case, it's ignored
00659 // because Doxygen doesn't understand it correctly, and we can't be
00660 // bothered to explain it to Doxygen.
00661 
00662 #define oprsw(opr, other, conv) \
00663         inline other operator opr (String x, other y) \
00664                         { return static_cast<conv>(x) opr y; } \
00665         inline other operator opr (other x, String y) \
00666                         { return x opr static_cast<conv>(y); }
00667 
00668 #define operator_binary(other, conv) \
00669   oprsw(+, other, conv) \
00670   oprsw(-, other, conv) \
00671   oprsw(*, other, conv) \
00672   oprsw(/, other, conv)
00673 
00674 #define operator_binary_int(other, conv) \
00675   operator_binary(other, conv) \
00676   oprsw(%, other, conv) \
00677   oprsw(&, other, conv) \
00678   oprsw(^, other, conv) \
00679   oprsw(|, other, conv) \
00680   oprsw(<<, other, conv) \
00681   oprsw(>>, other, conv)
00682 
00683 // Squish more complaints about possible loss of data
00684 #if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
00685 #       pragma warning(disable: 4244)
00686 #endif
00687 
00688 operator_binary(float, double)
00689 operator_binary(double, double)
00690 
00691 operator_binary_int(char, long int)
00692 operator_binary_int(int, long int)
00693 operator_binary_int(short int, long int)
00694 operator_binary_int(long int, long int)
00695 
00696 operator_binary_int(unsigned char, unsigned long int)
00697 operator_binary_int(unsigned int, unsigned long int)
00698 operator_binary_int(unsigned short int, unsigned long int)
00699 operator_binary_int(unsigned long int, unsigned long int)
00700 
00701 #if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
00702 #       pragma warning(default: 4244)
00703 #endif
00704 
00705 #if !defined(NO_LONG_LONGS)
00706 operator_binary_int(longlong, longlong)
00707 operator_binary_int(ulonglong, ulonglong)
00708 #endif // !defined(NO_LONG_LONGS)
00709 #endif // !defined(MYSQLPP_NO_BINARY_OPERS) && !defined(DOXYGEN_IGNORE)
00710 
00711 
00712 #if !defined(DOXYGEN_IGNORE)
00713 // Doxygen isn't smart enough to recognize these template
00714 // specializations.  Maybe it's the MYSQLPP_EXPORT tags?
00715 
00721 template <> MYSQLPP_EXPORT bool String::conv(bool) const;
00722 
00735 template <> MYSQLPP_EXPORT String String::conv(String) const;
00736 
00738 template <> MYSQLPP_EXPORT std::string String::conv(std::string) const;
00739 
00745 template <> MYSQLPP_EXPORT Date String::conv(Date) const;
00746 
00752 template <> MYSQLPP_EXPORT DateTime String::conv(DateTime) const;
00753 
00759 template <> MYSQLPP_EXPORT Time String::conv(Time) const;
00760 
00761 #endif // !defined(DOXYGEN_IGNORE)
00762 
00763 } // end namespace mysqlpp
00764 
00765 #endif // !defined(MYSQLPP_MYSTRING_H)

Generated on Wed Aug 6 17:19:07 2008 for MySQL++ by  doxygen 1.4.6