Author: wyoung
Date: Tue Dec 11 03:05:27 2007
New Revision: 1990

URL: http://svn.gna.org/viewcvs/mysqlpp?rev=1990&view=rev
Log:
- Uninitialized mysqlpp::String no longer crashes if you try to convert it
  to some other type.  Now it converts to 0 for numerics, false for bool,
  and an empty instance for more complex types.
- Added explicit String::conv<bool> specialization.  This probably only
  worked before because no one was using bool in SSQLS.  (Or not
  reporting it if they tried, and it blew up.)  Next item tickled this
  bug.
- Added test/test_string.cpp to test all of these possible conversions.
  (Not certain that it's 100% coverage; it certainly has no negative
  tests, but it's pretty exhaustive.)

Added:
    trunk/test/test_string.cpp
Modified:
    trunk/lib/mystring.cpp
    trunk/lib/mystring.h
    trunk/mysql++.bkl

Modified: trunk/lib/mystring.cpp
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/lib/mystring.cpp?rev=1990&r1=1989&r2=1990&view=diff
==============================================================================
--- trunk/lib/mystring.cpp (original)
+++ trunk/lib/mystring.cpp Tue Dec 11 03:05:27 2007
@@ -108,24 +108,43 @@
 
 
 template <>
+bool
+String::conv(bool dummy) const
+{
+       return *this;   // delegate to operator bool
+}
+
+
+template <>
 std::string
 String::conv(std::string dummy) const
-               { return std::string(data(), length()); }
+{
+       return buffer_ ? std::string(data(), length()) : std::string();
+}
 
 
 template <>
 Date
-String::conv(Date dummy) const { return Date(c_str()); }
+String::conv(Date dummy) const
+{
+       return buffer_ ? Date(c_str()) : Date();
+}
 
 
 template <>
 DateTime
-String::conv(DateTime dummy) const { return DateTime(c_str()); }
+String::conv(DateTime dummy) const
+{
+       return buffer_ ? DateTime(c_str()) : DateTime();
+}
 
 
 template <>
 Time
-String::conv(Time dummy) const { return Time(c_str()); }
+String::conv(Time dummy) const
+{
+       return buffer_ ? Time(c_str()) : Time(); 
+}
 
 #endif // !defined(DOXYGEN_IGNORE)
 

Modified: trunk/lib/mystring.h
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/lib/mystring.h?rev=1990&r1=1989&r2=1990&view=diff
==============================================================================
--- trunk/lib/mystring.h (original)
+++ trunk/lib/mystring.h Tue Dec 11 03:05:27 2007
@@ -462,16 +462,17 @@
                        { return conv(static_cast<double>(0)); }
        
        /// \brief Converts this object's string data to a bool
-       operator bool() const { return conv(0); }
+       operator bool() const { return buffer_ ? atoi(c_str()) : false; }
 
        /// \brief Converts this object's string data to a mysqlpp::Date
-       operator Date() const { return Date(*this); }
+       operator Date() const { return buffer_ ? Date(*this) : Date(); }
 
        /// \brief Converts this object's string data to a mysqlpp::DateTime
-       operator DateTime() const { return DateTime(*this); }
+       operator DateTime() const
+                       { return buffer_ ? DateTime(*this) : DateTime(); }
 
        /// \brief Converts this object's string data to a mysqlpp::Time
-       operator Time() const { return Time(*this); }
+       operator Time() const { return buffer_ ? Time(*this) : Time(); }
 
        /// \brief Converts the String to a nullable data type
        ///
@@ -628,24 +629,29 @@
 Type
 String::conv(Type) const
 {
-       std::string strbuf;
-       strip_leading_blanks(strbuf);
-       std::string::size_type len = strbuf.size();
-       const char* str = strbuf.data();
-       const char* end = str;
-       Type num = internal_string_to_int_proxy<Type>(str, end);
-
-       if (*end == '.') {
-               ++end;
-               for (; *end == '0'; ++end) ;
-       }
-       
-       if (*end != '\0' && end != 0) {
-               throw BadConversion(typeid(Type).name(), data(),
-                               end - str, len);
-       }
-
-       return num;
+       if (buffer_) {
+               std::string strbuf;
+               strip_leading_blanks(strbuf);
+               std::string::size_type len = strbuf.size();
+               const char* str = strbuf.data();
+               const char* end = str;
+               Type num = internal_string_to_int_proxy<Type>(str, end);
+
+               if (*end == '.') {
+                       ++end;
+                       for (; *end == '0'; ++end) ;
+               }
+               
+               if (*end != '\0' && end != 0) {
+                       throw BadConversion(typeid(Type).name(), data(),
+                                       end - str, len);
+               }
+
+               return num;
+       }
+       else {
+               return 0;
+       }
 }
 
 
@@ -653,13 +659,20 @@
 // Doxygen isn't smart enough to recognize these template
 // specializations.  Maybe it's the MYSQLPP_EXPORT tags?
 
+/// \brief Specialization of String::conv<Type>() for bool
+///
+/// We can either do it this way, or define "\c strtob()" (string to
+/// bool, like \c strtol(), \c strtod()...) so we can use
+/// internal_string_to_int_proxy.
+template <> MYSQLPP_EXPORT bool String::conv(bool) const;
+
 /// \brief Specialization of String::conv<Type>() for String
 ///
 /// Yes, I hear you crying, "WTF!?  Why does String need to be able to
 /// convert itself to String?"  SSQLSes with BLOB columns, that's why.
 ///
 /// SSQLSes populate their data members from the raw field data by
-/// calling row[field].conv().  The raw field data is stored in a
+/// calling row["fieldname"].conv().  The raw field data is stored in a
 /// String, and the MySQL++ native BLOB type is String.  Since we're
 /// dealing with generated code, we need this specialization which hand-
 /// written code wouldn't need.  Prove the truth of this to yourself by

Modified: trunk/mysql++.bkl
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/mysql%2B%2B.bkl?rev=1990&r1=1989&r2=1990&view=diff
==============================================================================
--- trunk/mysql++.bkl (original)
+++ trunk/mysql++.bkl Tue Dec 11 03:05:27 2007
@@ -193,6 +193,9 @@
                <exe id="test_manip" template="programs">
                        <sources>test/test_manip.cpp</sources>
                </exe>
+               <exe id="test_string" template="programs">
+                       <sources>test/test_string.cpp</sources>
+               </exe>
                <exe id="test_tcp" template="programs">
                        <sources>test/test_tcp.cpp</sources>
                </exe>

Added: trunk/test/test_string.cpp
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/test/test_string.cpp?rev=1990&view=auto
==============================================================================
--- trunk/test/test_string.cpp (added)
+++ trunk/test/test_string.cpp Tue Dec 11 03:05:27 2007
@@ -1,0 +1,103 @@
+/***********************************************************************
+ test_string.cpp - Tests the behavior of mysqlpp::String, particularly
+       its data conversion methods.
+
+ Copyright (c) 2007 by Educational Technology Resources, Inc.
+ Others may also hold copyrights on code in this file.  See the
+ CREDITS 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
+***********************************************************************/
+
+#include <mysql++.h>
+
+#include <iostream>
+
+
+// Does a simple equality comparison on the value, forcing the string
+// to convert itself to T on the way.
+template <typename T>
+static bool
+test_equality(const mysqlpp::String& s, T value)
+{
+       if (s.conv(value) == value) {
+               return true;
+       }
+       else {
+               std::cerr << "Type conversion to " << typeid(T).name() <<
+                               " failed: \"" << s << "\" != \"" << value << 
"\"." <<
+                               std::endl;
+       }
+}
+
+
+// Runs uses the above functions to test many different types of
+// conversion.
+static bool
+test_numeric(const mysqlpp::String& s, int value)
+{
+       return  test_equality(s, (signed char)value) &&
+                       test_equality(s, (unsigned char)value) &&
+                       test_equality(s, (signed short)value) &&
+                       test_equality(s, (unsigned short)value) &&
+                       test_equality(s, (signed int)value) &&
+                       test_equality(s, (unsigned int)value) &&
+                       test_equality(s, (signed long)value) &&
+                       test_equality(s, (unsigned long)value) &&
+#if !defined(NO_LONG_LONGS)
+                       test_equality(s, (mysqlpp::longlong)value) &&
+                       test_equality(s, (mysqlpp::ulonglong)value) &&
+#endif
+                       test_equality(s, (float)value) &&
+                       test_equality(s, (double)value);
+}
+
+
+int
+main(int argc, char* argv[])
+{
+       try {
+               int failures = 0;
+               mysqlpp::String empty;
+               mysqlpp::String zero("0");
+               mysqlpp::String nonzero("42");
+
+               failures += test_equality(empty, mysqlpp::Date()) == false;
+               failures += test_equality(empty, mysqlpp::DateTime()) == false;
+               failures += test_equality(empty, mysqlpp::Time()) == false;
+               failures += test_equality(empty, false) == false;
+               failures += test_equality(nonzero, true) == false;
+               failures += test_numeric(empty, 0) == false;
+               failures += test_numeric(zero, 0) == false;
+               failures += test_numeric(nonzero, 42) == false;
+
+               return failures;
+       }
+       catch (mysqlpp::Exception& e) {
+               std::cerr << "Unexpected MySQL++ exception caught in " <<
+                               argv[0] << ": " << e.what() << std::endl;
+               return 1;
+       }
+       catch (std::exception& e) {
+               std::cerr << "Unexpected C++ exception caught in " <<
+                               argv[0] << ": " << e.what() << std::endl;
+               return 1;
+       }
+
+}
+


_______________________________________________
Mysqlpp-commits mailing list
[email protected]
https://mail.gna.org/listinfo/mysqlpp-commits

Reply via email to