MySQL++: mystring.h Source File
mystring.h
Go to the documentation of this file.
/***********************************************************************
Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
(c) 2004-2008 by Educational Technology Resources, Inc. Others may
also hold copyrights on code in this file. See the CREDITS.txt file
in the top directory of the distribution for details.
This file is part of MySQL++.
MySQL++ is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
MySQL++ is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with MySQL++; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA
***********************************************************************/
#if !defined(MYSQLPP_MYSTRING_H)
#define MYSQLPP_MYSTRING_H
#include "common.h"
#include "datetime.h"
#include "exceptions.h"
#include "null.h"
#include "sql_buffer.h"
#include <string>
#include <sstream>
#include <limits>
#include <stdlib.h>
#include <string.h>
namespace mysqlpp {
#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.
namespace detail
{
template<typename T, bool is_signed = std::numeric_limits<T>::is_signed>
struct conv_promotion;
template<>
struct conv_promotion<float>
{
typedef double type;
};
template<>
struct conv_promotion<double>
{
typedef double type;
};
# if !defined(NO_LONG_LONGS)
template<>
struct conv_promotion<unsigned long long>
{
typedef unsigned long long type;
};
template<>
struct conv_promotion<long long>
{
typedef long long type;
};
# endif
// preserve existing behaviour, char converted as signed long
template<>
struct conv_promotion<char>
{
typedef long type;
};
// all other types use signed/unsigned long
template<typename T>
struct conv_promotion<T, true>
{
typedef long type;
};
template<typename T>
struct conv_promotion<T, false>
{
typedef unsigned long type;
};
} // namespace detail
class MYSQLPP_EXPORT SQLTypeAdapter;
#endif // !defined(DOXYGEN_IGNORE)
class MYSQLPP_EXPORT String
{
public:
typedef const char value_type;
typedef size_t size_type;
typedef const char* const_iterator;
typedef const_iterator iterator;
#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.
typedef int difference_type;
typedef const char* const_pointer;
typedef const_pointer pointer;
#endif // !defined(DOXYGEN_IGNORE)
String() :
buffer_()
{
}
String(const String& other) :
buffer_(other.buffer_)
{
}
explicit String(const char* str, size_type len,
mysql_type_info type = mysql_type_info::string_type,
bool is_null = false) :
buffer_(new SQLBuffer(str, len, type, is_null))
{
}
explicit String(const std::string& str,
mysql_type_info type = mysql_type_info::string_type,
bool is_null = false) :
buffer_(new SQLBuffer(str.data(), static_cast<size_type>(str.length()),
type, is_null))
{
}
explicit String(const char* str,
mysql_type_info type = mysql_type_info::string_type,
bool is_null = false) :
buffer_(new SQLBuffer(str, static_cast<size_type>(strlen(str)),
type, is_null))
{
}
~String() { }
void assign(const char* str, size_type len,
mysql_type_info type = mysql_type_info::string_type,
bool is_null = false)
{
buffer_ = new SQLBuffer(str, len, type, is_null);
}
void assign(const std::string& str,
mysql_type_info type = mysql_type_info::string_type,
bool is_null = false)
{
buffer_ = new SQLBuffer(str.data(),
static_cast<size_type>(str.length()), type, is_null);
}
void assign(const char* str,
mysql_type_info type = mysql_type_info::string_type,
bool is_null = false)
{
buffer_ = new SQLBuffer(str, static_cast<size_type>(strlen(str)),
type, is_null);
}
char at(size_type pos) const;
const_iterator begin() const { return data(); }
const char* c_str() const { return data(); }
#if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
// Squish VC++ warning about "possible loss of data" for these conversions
# pragma warning(disable: 4244)
#endif
template <class Type>
Type conv(Type) const
{
// Conversions are done using one of double/long/ulong/llong/ullong
// so we call a helper function to do the work using that type.
// This reduces the amount of template code instantiated.
typedef typename detail::conv_promotion<Type>::type conv_type;
return do_conv<conv_type>(typeid(Type).name());
}
#if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
# pragma warning(default: 4244)
#endif
template <class T, class B>
Null<T, B> conv(Null<T, B>) const
{
if (is_null()) {
return Null<T, B>(null);
}
else {
return Null<T, B>(conv(T()));
}
}
int compare(const String& other) const;
int compare(const std::string& other) const;
int compare(size_type pos, size_type num, std::string& other) const;
int compare(const char* other) const;
int compare(size_type pos, size_type num, const char* other) const;
const char* data() const;
bool empty() const { return size() == 0; }
const_iterator end() const;
bool escape_q() const;
bool is_null() const;
void it_is_null();
size_type length() const;
size_type max_size() const { return size(); }
bool quote_q() const;
size_type size() const { return length(); }
void strip_leading_blanks(std::string& s) const
{
const char* pc = data();
if (pc) {
size_type n = length();
while (n && (*pc == ' ')) {
++pc;
--n;
}
s.assign(pc, n);
}
else {
s.clear();
}
}
void to_string(std::string& s) const;
mysql_type_info type() const
{
return buffer_ ? buffer_->type() : mysql_type_info::string_type;
}
String& operator =(const std::string& rhs)
{
buffer_ = new SQLBuffer(rhs.data(),
static_cast<size_type>(rhs.length()),
mysql_type_info::string_type, false);
return *this;
}
String& operator =(const char* str)
{
buffer_ = new SQLBuffer(str,
static_cast<size_type>(strlen(str)),
mysql_type_info::string_type, false);
return *this;
}
String& operator =(const String& other)
{
buffer_ = other.buffer_;
return *this;
}
template <typename T>
bool operator ==(const T& rhs) const
{
return compare(rhs) == 0;
}
bool operator ==(const mysqlpp::null_type&) const
{
return is_null();
}
template <typename T>
bool operator !=(const T& rhs) const
{
return compare(rhs) != 0;
}
bool operator !=(const mysqlpp::null_type&) const
{
return !is_null();
}
char operator [](size_type pos) const { return at(pos); }
operator const char*() const { return data(); }
operator signed char() const
{ return conv(static_cast<signed char>(0)); }
operator unsigned char() const
{ return conv(static_cast<unsigned char>(0)); }
operator int() const
{ return conv(static_cast<int>(0)); }
operator unsigned int() const
{ return conv(static_cast<unsigned int>(0)); }
operator short int() const
{ return conv(static_cast<short int>(0)); }
operator unsigned short int() const
{ return conv(static_cast<unsigned short int>(0)); }
operator long int() const
{ return conv(static_cast<long int>(0)); }
operator unsigned long int() const
{ return conv(static_cast<unsigned long int>(0)); }
#if !defined(NO_LONG_LONGS)
operator longlong() const
{ return conv(static_cast<longlong>(0)); }
operator ulonglong() const
{ return conv(static_cast<ulonglong>(0)); }
#endif
operator float() const
{ return conv(static_cast<float>(0)); }
operator double() const
{ return conv(static_cast<double>(0)); }
operator bool() const { return buffer_ ? atoi(c_str()) : false; }
operator Date() const { return buffer_ ? Date(*this) : Date(); }
operator DateTime() const
{ return buffer_ ? DateTime(*this) : DateTime(); }
operator Time() const { return buffer_ ? Time(*this) : Time(); }
template <class T, class B>
operator Null<T, B>() const { return conv(Null<T, B>()); }
private:
template <class Type>
Type do_conv(const char* type_name) const
{
if (buffer_) {
std::stringstream buf;
buf.write(data(), static_cast<std::streamsize>(length()));
buf.imbue(std::locale::classic()); // "C" locale
Type num = Type();
if (buf >> num) {
char c;
if (!(buf >> c)) {
// Nothing left in buffer, so conversion complete,
// and thus successful.
return num;
}
if (c == '.' &&
(typeid(Type) != typeid(float)) &&
(typeid(Type) != typeid(double))) {
// Conversion stopped on a decimal point -- locale
// doesn't matter to MySQL -- so only way to succeed
// is if it's an integer and everything following
// the decimal is inconsequential.
c = '0'; // handles '.' at end of string
while (buf >> c && c == '0') /* spin */ ;
if (buf.eof() && c == '0') {
return num; // only zeros after decimal point
}
}
}
else if (buf.eof()) {
return num; // nothing to convert, return default value
}
throw BadConversion(type_name, data(), 0, length());
}
else {
return 0;
}
}
RefCountedBuffer buffer_;
friend class SQLTypeAdapter;
};
MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& o,
const String& in);
#if !defined(MYSQLPP_NO_BINARY_OPERS) && !defined(DOXYGEN_IGNORE)
// Ignore this section is MYSQLPP_NO_BINARY_OPERS is defined, or if this
// section is being parsed by Doxygen. In the latter case, it's ignored
// because Doxygen doesn't understand it correctly, and we can't be
// bothered to explain it to Doxygen.
#define oprsw(opr, other, conv) \
inline other operator opr (String x, other y) \
{ return static_cast<conv>(x) opr y; } \
inline other operator opr (other x, String y) \
{ return x opr static_cast<conv>(y); }
#define operator_binary(other, conv) \
oprsw(+, other, conv) \
oprsw(-, other, conv) \
oprsw(*, other, conv) \
oprsw(/, other, conv)
#define operator_binary_int(other, conv) \
operator_binary(other, conv) \
oprsw(%, other, conv) \
oprsw(&, other, conv) \
oprsw(^, other, conv) \
oprsw(|, other, conv) \
oprsw(<<, other, conv) \
oprsw(>>, other, conv)
// Squish more complaints about possible loss of data
#if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
# pragma warning(disable: 4244)
#endif
operator_binary(float, double)
operator_binary(double, double)
operator_binary_int(char, long int)
operator_binary_int(int, long int)
operator_binary_int(short int, long int)
operator_binary_int(long int, long int)
operator_binary_int(unsigned char, unsigned long int)
operator_binary_int(unsigned int, unsigned long int)
operator_binary_int(unsigned short int, unsigned long int)
operator_binary_int(unsigned long int, unsigned long int)
#if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
# pragma warning(default: 4244)
#endif
#if !defined(NO_LONG_LONGS)
operator_binary_int(longlong, longlong)
operator_binary_int(ulonglong, ulonglong)
#endif // !defined(NO_LONG_LONGS)
#endif // !defined(MYSQLPP_NO_BINARY_OPERS) && !defined(DOXYGEN_IGNORE)
#if !defined(DOXYGEN_IGNORE)
// Doxygen isn't smart enough to recognize these template
// specializations. Maybe it's the MYSQLPP_EXPORT tags?
template <> MYSQLPP_EXPORT bool String::conv(bool) const;
template <> MYSQLPP_EXPORT String String::conv(String) const;
template <> MYSQLPP_EXPORT std::string String::conv(std::string) const;
template <> MYSQLPP_EXPORT Date String::conv(Date) const;
template <> MYSQLPP_EXPORT DateTime String::conv(DateTime) const;
template <> MYSQLPP_EXPORT Time String::conv(Time) const;
#endif // !defined(DOXYGEN_IGNORE)
} // end namespace mysqlpp
#endif // !defined(MYSQLPP_MYSTRING_H)
mysqlpp::DateTime
C++ form of SQL's DATETIME type.
Definition: datetime.h:49
mysqlpp::Date
C++ form of SQL's DATE type.
Definition: datetime.h:226
mysqlpp::Null
Class for holding data from a SQL column with the NULL attribute.
Definition: null.h:171
mysqlpp::SQLBuffer
Holds SQL data in string form plus type information for use in converting the string to compatible C+...
Definition: sql_buffer.h:42
mysqlpp::String
A std::string work-alike that can convert itself from SQL text data formats to C++ data types.
Definition: mystring.h:140
mysqlpp::String::assign
void assign(const char *str, size_type len, mysql_type_info type=mysql_type_info::string_type, bool is_null=false)
Assign raw data to this object.
Definition: mystring.h:242
mysqlpp::String::assign
void assign(const std::string &str, mysql_type_info type=mysql_type_info::string_type, bool is_null=false)
Assign a C++ string to this object.
Definition: mystring.h:255
mysqlpp::String::assign
void assign(const char *str, mysql_type_info type=mysql_type_info::string_type, bool is_null=false)
Assign a C string to this object.
Definition: mystring.h:269
mysqlpp::String::size
size_type size() const
Return number of bytes in string.
Definition: mystring.h:417
mysqlpp::String::~String
~String()
Destroy string.
Definition: mystring.h:234
mysqlpp::String::max_size
size_type max_size() const
Return the maximum number of characters in the string.
Definition: mystring.h:407
mysqlpp::String::String
String(const String &other)
Copy ctor.
Definition: mystring.h:179
mysqlpp::String::empty
bool empty() const
Returns true if size() == 0.
Definition: mystring.h:376
mysqlpp::String::const_iterator
const char * const_iterator
Type of iterators.
Definition: mystring.h:150
mysqlpp::String::c_str
const char * c_str() const
Return a const pointer to the string data.
Definition: mystring.h:288
mysqlpp::String::conv
Null< T, B > conv(Null< T, B >) const
Overload of conv() for types wrapped with Null<>
Definition: mystring.h:318
mysqlpp::String::conv
Type conv(Type) const
Template for converting the column data to most any numeric data type.
Definition: mystring.h:298
mysqlpp::String::begin
const_iterator begin() const
Return iterator pointing to the first character of the string.
Definition: mystring.h:285
mysqlpp::String::iterator
const_iterator iterator
Same as const_iterator because the data cannot be changed.
Definition: mystring.h:154
mysqlpp::String::strip_leading_blanks
void strip_leading_blanks(std::string &s) const
Returns a copy of our internal string without leading blanks.
Definition: mystring.h:421
mysqlpp::String::String
String()
Default constructor.
Definition: mystring.h:167
mysqlpp::String::type
mysql_type_info type() const
Get this object's current MySQL type.
Definition: mystring.h:448
mysqlpp::String::value_type
const char value_type
Type of the data stored in this object, when it is not equal to SQL null.
Definition: mystring.h:144
mysqlpp::String::size_type
size_t size_type
Type of "size" integers.
Definition: mystring.h:147
mysqlpp::String::String
String(const char *str, size_type len, mysql_type_info type=mysql_type_info::string_type, bool is_null=false)
Full constructor.
Definition: mystring.h:196
mysqlpp::String::String
String(const std::string &str, mysql_type_info type=mysql_type_info::string_type, bool is_null=false)
C++ string version of full ctor.
Definition: mystring.h:210
mysqlpp::String::String
String(const char *str, mysql_type_info type=mysql_type_info::string_type, bool is_null=false)
Null-terminated C string version of full ctor.
Definition: mystring.h:225
mysqlpp::Time
C++ form of SQL's TIME type.
Definition: datetime.h:348
mysqlpp::mysql_type_info
SQL field type information.
Definition: type_info.h:159
mysqlpp::mysql_type_info::string_type
static const enum_field_types string_type
The internal constant we use for our string type.
Definition: type_info.h:280
mysqlpp::null_type
The type of the global mysqlpp::null object.
Definition: null.h:50
common.h
This file includes top-level definitions for use both internal to the library, and outside it....
datetime.h
Declares classes to add SQL-compatible date and time types to C++'s type system.
exceptions.h
Declares the MySQL++-specific exception classes.
null.h
Declares classes that implement SQL "null" semantics within C++'s type system.
sql_buffer.h
Declares the SQLBuffer class.
mysqlpp::RefCountedBuffer
RefCountedPointer< SQLBuffer > RefCountedBuffer
Reference-counted version of SQLBuffer.
Definition: sql_buffer.h:136