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