MySQL++  3.3.0
mystring.h
Go to the documentation of this file.
1 
5 /***********************************************************************
6  Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
7  (c) 2004-2008 by Educational Technology Resources, Inc. Others may
8  also hold copyrights on code in this file. See the CREDITS.txt file
9  in the top directory of the distribution for details.
10 
11  This file is part of MySQL++.
12 
13  MySQL++ is free software; you can redistribute it and/or modify it
14  under the terms of the GNU Lesser General Public License as published
15  by the Free Software Foundation; either version 2.1 of the License, or
16  (at your option) any later version.
17 
18  MySQL++ is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
21  License for more details.
22 
23  You should have received a copy of the GNU Lesser General Public
24  License along with MySQL++; if not, write to the Free Software
25  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
26  USA
27 ***********************************************************************/
28 
29 #if !defined(MYSQLPP_MYSTRING_H)
30 #define MYSQLPP_MYSTRING_H
31 
32 #include "common.h"
33 
34 #include "datetime.h"
35 #include "exceptions.h"
36 #include "null.h"
37 #include "sql_buffer.h"
38 
39 #include <string>
40 #include <sstream>
41 #include <limits>
42 
43 #include <stdlib.h>
44 #include <string.h>
45 
46 namespace mysqlpp {
47 
48 #if !defined(DOXYGEN_IGNORE)
49 // Doxygen will not generate documentation for this section.
50 
51 namespace detail
52 {
53  template<typename T, bool is_signed = std::numeric_limits<T>::is_signed>
54  struct conv_promotion;
55 
56  template<>
57  struct conv_promotion<float>
58  {
59  typedef double type;
60  };
61 
62  template<>
63  struct conv_promotion<double>
64  {
65  typedef double type;
66  };
67 
68 # if !defined(NO_LONG_LONGS)
69  template<>
70  struct conv_promotion<unsigned long long>
71  {
72  typedef unsigned long long type;
73  };
74 
75  template<>
76  struct conv_promotion<long long>
77  {
78  typedef long long type;
79  };
80 # endif
81 
82  // preserve existing behaviour, char converted as signed long
83  template<>
84  struct conv_promotion<char>
85  {
86  typedef long type;
87  };
88 
89  // all other types use signed/unsigned long
90 
91  template<typename T>
92  struct conv_promotion<T, true>
93  {
94  typedef long type;
95  };
96 
97  template<typename T>
98  struct conv_promotion<T, false>
99  {
100  typedef unsigned long type;
101  };
102 } // namespace detail
103 
104 class MYSQLPP_EXPORT SQLTypeAdapter;
105 #endif // !defined(DOXYGEN_IGNORE)
106 
138 
139 class MYSQLPP_EXPORT String
140 {
141 public:
144  typedef const char value_type;
145 
147  typedef size_t size_type;
148 
150  typedef const char* const_iterator;
151 
155 
156 #if !defined(DOXYGEN_IGNORE)
157 // Doxygen will not generate documentation for this section.
158  typedef int difference_type;
159  typedef const char* const_pointer;
160  typedef const_pointer pointer;
161 #endif // !defined(DOXYGEN_IGNORE)
162 
167  String() :
168  buffer_()
169  {
170  }
171 
179  String(const String& other) :
180  buffer_(other.buffer_)
181  {
182  }
183 
196  explicit String(const char* str, size_type len,
198  bool is_null = false) :
199  buffer_(new SQLBuffer(str, len, type, is_null))
200  {
201  }
202 
210  explicit String(const std::string& str,
212  bool is_null = false) :
213  buffer_(new SQLBuffer(str.data(), static_cast<size_type>(str.length()),
214  type, is_null))
215  {
216  }
217 
225  explicit String(const char* str,
227  bool is_null = false) :
228  buffer_(new SQLBuffer(str, static_cast<size_type>(strlen(str)),
229  type, is_null))
230  {
231  }
232 
234  ~String() { }
235 
242  void assign(const char* str, size_type len,
244  bool is_null = false)
245  {
246  buffer_ = new SQLBuffer(str, len, type, is_null);
247  }
248 
255  void assign(const std::string& str,
257  bool is_null = false)
258  {
259  buffer_ = new SQLBuffer(str.data(),
260  static_cast<size_type>(str.length()), type, is_null);
261  }
262 
269  void assign(const char* str,
271  bool is_null = false)
272  {
273  buffer_ = new SQLBuffer(str, static_cast<size_type>(strlen(str)),
274  type, is_null);
275  }
276 
281  char at(size_type pos) const;
282 
285  const_iterator begin() const { return data(); }
286 
288  const char* c_str() const { return data(); }
289 
290 #if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
291 // Squish VC++ warning about "possible loss of data" for these conversions
292 # pragma warning(disable: 4244)
293 #endif
294 
297  template <class Type>
298  Type conv(Type) const
299  {
300  // Conversions are done using one of double/long/ulong/llong/ullong
301  // so we call a helper function to do the work using that type.
302  // This reduces the amount of template code instantiated.
303  typedef typename detail::conv_promotion<Type>::type conv_type;
304  return do_conv<conv_type>(typeid(Type).name());
305  }
306 
307 #if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
308 # pragma warning(default: 4244)
309 #endif
310 
317  template <class T, class B>
319  {
320  if (is_null()) {
321  return Null<T, B>(null);
322  }
323  else {
324  return Null<T, B>(conv(T()));
325  }
326  }
327 
333  int compare(const String& other) const;
334 
340  int compare(const std::string& other) const;
341 
350  int compare(size_type pos, size_type num, std::string& other) const;
351 
357  int compare(const char* other) const;
358 
369  int compare(size_type pos, size_type num, const char* other) const;
370 
373  const char* data() const;
374 
376  bool empty() const { return size() == 0; }
377 
380  const_iterator end() const;
381 
384  bool escape_q() const;
385 
387  bool is_null() const;
388 
390  void it_is_null();
391 
400  size_type length() const;
401 
407  size_type max_size() const { return size(); }
408 
411  bool quote_q() const;
412 
417  size_type size() const { return length(); }
418 
421  void strip_leading_blanks(std::string& s) const
422  {
423  const char* pc = data();
424  if (pc) {
425  size_type n = length();
426  while (n && (*pc == ' ')) {
427  ++pc;
428  --n;
429  }
430 
431  s.assign(pc, n);
432  }
433  else {
434  s.clear();
435  }
436  }
437 
445  void to_string(std::string& s) const;
446 
449  {
450  return buffer_ ? buffer_->type() : mysql_type_info::string_type;
451  }
452 
454  String& operator =(const std::string& rhs)
455  {
456  buffer_ = new SQLBuffer(rhs.data(),
457  static_cast<size_type>(rhs.length()),
459 
460  return *this;
461  }
462 
467  String& operator =(const char* str)
468  {
469  buffer_ = new SQLBuffer(str,
470  static_cast<size_type>(strlen(str)),
472 
473  return *this;
474  }
475 
481  String& operator =(const String& other)
482  {
483  buffer_ = other.buffer_;
484 
485  return *this;
486  }
487 
492  template <typename T>
493  bool operator ==(const T& rhs) const
494  {
495  return compare(rhs) == 0;
496  }
497 
501  bool operator ==(const mysqlpp::null_type&) const
502  {
503  return is_null();
504  }
505 
510  template <typename T>
511  bool operator !=(const T& rhs) const
512  {
513  return compare(rhs) != 0;
514  }
515 
519  bool operator !=(const mysqlpp::null_type&) const
520  {
521  return !is_null();
522  }
523 
530  char operator [](size_type pos) const { return at(pos); }
531 
533  operator const char*() const { return data(); }
534 
536  operator signed char() const
537  { return conv(static_cast<signed char>(0)); }
538 
540  operator unsigned char() const
541  { return conv(static_cast<unsigned char>(0)); }
542 
544  operator int() const
545  { return conv(static_cast<int>(0)); }
546 
548  operator unsigned int() const
549  { return conv(static_cast<unsigned int>(0)); }
550 
552  operator short int() const
553  { return conv(static_cast<short int>(0)); }
554 
557  operator unsigned short int() const
558  { return conv(static_cast<unsigned short int>(0)); }
559 
561  operator long int() const
562  { return conv(static_cast<long int>(0)); }
563 
566  operator unsigned long int() const
567  { return conv(static_cast<unsigned long int>(0)); }
568 
569 #if !defined(NO_LONG_LONGS)
572  operator longlong() const
573  { return conv(static_cast<longlong>(0)); }
574 
577  operator ulonglong() const
578  { return conv(static_cast<ulonglong>(0)); }
579 #endif
580 
582  operator float() const
583  { return conv(static_cast<float>(0)); }
584 
586  operator double() const
587  { return conv(static_cast<double>(0)); }
588 
590  operator bool() const { return buffer_ ? atoi(c_str()) : false; }
591 
593  operator Date() const { return buffer_ ? Date(*this) : Date(); }
594 
596  operator DateTime() const
597  { return buffer_ ? DateTime(*this) : DateTime(); }
598 
600  operator Time() const { return buffer_ ? Time(*this) : Time(); }
601 
605  template <class T, class B>
606  operator Null<T, B>() const { return conv(Null<T, B>()); }
607 
608 private:
610  template <class Type>
611  Type do_conv(const char* type_name) const
612  {
613  if (buffer_) {
614  std::stringstream buf;
615  buf.write(data(), static_cast<std::streamsize>(length()));
616  buf.imbue(std::locale::classic()); // "C" locale
617  Type num = Type();
618 
619  if (buf >> num) {
620  char c;
621  if (!(buf >> c)) {
622  // Nothing left in buffer, so conversion complete,
623  // and thus successful.
624  return num;
625  }
626 
627  if (c == '.' &&
628  (typeid(Type) != typeid(float)) &&
629  (typeid(Type) != typeid(double))) {
630  // Conversion stopped on a decimal point -- locale
631  // doesn't matter to MySQL -- so only way to succeed
632  // is if it's an integer and everything following
633  // the decimal is inconsequential.
634  c = '0'; // handles '.' at end of string
635  while (buf >> c && c == '0') /* spin */ ;
636  if (buf.eof() && c == '0') {
637  return num; // only zeros after decimal point
638  }
639  }
640  }
641  else if (buf.eof()) {
642  return num; // nothing to convert, return default value
643  }
644 
645  throw BadConversion(type_name, data(), 0, length());
646  }
647  else {
648  return 0;
649  }
650  }
651 
652  RefCountedBuffer buffer_;
653 
654  friend class SQLTypeAdapter;
655 };
656 
657 MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& o,
658  const String& in);
659 
660 
661 #if !defined(MYSQLPP_NO_BINARY_OPERS) && !defined(DOXYGEN_IGNORE)
662 // Ignore this section is MYSQLPP_NO_BINARY_OPERS is defined, or if this
663 // section is being parsed by Doxygen. In the latter case, it's ignored
664 // because Doxygen doesn't understand it correctly, and we can't be
665 // bothered to explain it to Doxygen.
666 
667 #define oprsw(opr, other, conv) \
668  inline other operator opr (String x, other y) \
669  { return static_cast<conv>(x) opr y; } \
670  inline other operator opr (other x, String y) \
671  { return x opr static_cast<conv>(y); }
672 
673 #define operator_binary(other, conv) \
674  oprsw(+, other, conv) \
675  oprsw(-, other, conv) \
676  oprsw(*, other, conv) \
677  oprsw(/, other, conv)
678 
679 #define operator_binary_int(other, conv) \
680  operator_binary(other, conv) \
681  oprsw(%, other, conv) \
682  oprsw(&, other, conv) \
683  oprsw(^, other, conv) \
684  oprsw(|, other, conv) \
685  oprsw(<<, other, conv) \
686  oprsw(>>, other, conv)
687 
688 // Squish more complaints about possible loss of data
689 #if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
690 # pragma warning(disable: 4244)
691 #endif
692 
693 operator_binary(float, double)
694 operator_binary(double, double)
695 
696 operator_binary_int(char, long int)
697 operator_binary_int(int, long int)
698 operator_binary_int(short int, long int)
699 operator_binary_int(long int, long int)
700 
701 operator_binary_int(unsigned char, unsigned long int)
702 operator_binary_int(unsigned int, unsigned long int)
703 operator_binary_int(unsigned short int, unsigned long int)
704 operator_binary_int(unsigned long int, unsigned long int)
705 
706 #if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
707 # pragma warning(default: 4244)
708 #endif
709 
710 #if !defined(NO_LONG_LONGS)
711 operator_binary_int(longlong, longlong)
712 operator_binary_int(ulonglong, ulonglong)
713 #endif // !defined(NO_LONG_LONGS)
714 #endif // !defined(MYSQLPP_NO_BINARY_OPERS) && !defined(DOXYGEN_IGNORE)
715 
716 
717 #if !defined(DOXYGEN_IGNORE)
718 // Doxygen isn't smart enough to recognize these template
719 // specializations. Maybe it's the MYSQLPP_EXPORT tags?
720 
726 template <> MYSQLPP_EXPORT bool String::conv(bool) const;
727 
740 template <> MYSQLPP_EXPORT String String::conv(String) const;
741 
743 template <> MYSQLPP_EXPORT std::string String::conv(std::string) const;
744 
750 template <> MYSQLPP_EXPORT Date String::conv(Date) const;
751 
757 template <> MYSQLPP_EXPORT DateTime String::conv(DateTime) const;
758 
764 template <> MYSQLPP_EXPORT Time String::conv(Time) const;
765 
766 #endif // !defined(DOXYGEN_IGNORE)
767 
768 } // end namespace mysqlpp
769 
770 #endif // !defined(MYSQLPP_MYSTRING_H)
C++ form of SQL's DATETIME type.
Definition: datetime.h:49
C++ form of SQL's DATE type.
Definition: datetime.h:226
Class for holding data from a SQL column with the NULL attribute.
Definition: null.h:171
Holds SQL data in string form plus type information for use in converting the string to compatible C+...
Definition: sql_buffer.h:42
A std::string work-alike that can convert itself from SQL text data formats to C++ data types.
Definition: mystring.h:140
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
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
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
size_type size() const
Return number of bytes in string.
Definition: mystring.h:417
~String()
Destroy string.
Definition: mystring.h:234
size_type max_size() const
Return the maximum number of characters in the string.
Definition: mystring.h:407
String(const String &other)
Copy ctor.
Definition: mystring.h:179
bool empty() const
Returns true if size() == 0.
Definition: mystring.h:376
const char * const_iterator
Type of iterators.
Definition: mystring.h:150
const char * c_str() const
Return a const pointer to the string data.
Definition: mystring.h:288
Null< T, B > conv(Null< T, B >) const
Overload of conv() for types wrapped with Null<>
Definition: mystring.h:318
Type conv(Type) const
Template for converting the column data to most any numeric data type.
Definition: mystring.h:298
const_iterator begin() const
Return iterator pointing to the first character of the string.
Definition: mystring.h:285
const_iterator iterator
Same as const_iterator because the data cannot be changed.
Definition: mystring.h:154
void strip_leading_blanks(std::string &s) const
Returns a copy of our internal string without leading blanks.
Definition: mystring.h:421
String()
Default constructor.
Definition: mystring.h:167
mysql_type_info type() const
Get this object's current MySQL type.
Definition: mystring.h:448
const char value_type
Type of the data stored in this object, when it is not equal to SQL null.
Definition: mystring.h:144
size_t size_type
Type of "size" integers.
Definition: mystring.h:147
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
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
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
C++ form of SQL's TIME type.
Definition: datetime.h:348
SQL field type information.
Definition: type_info.h:159
static const enum_field_types string_type
The internal constant we use for our string type.
Definition: type_info.h:280
The type of the global mysqlpp::null object.
Definition: null.h:50
This file includes top-level definitions for use both internal to the library, and outside it....
Declares classes to add SQL-compatible date and time types to C++'s type system.
Declares the MySQL++-specific exception classes.
Declares classes that implement SQL "null" semantics within C++'s type system.
Declares the SQLBuffer class.
RefCountedPointer< SQLBuffer > RefCountedBuffer
Reference-counted version of SQLBuffer.
Definition: sql_buffer.h:136