Use cstring_to_integer() in other backends too

Replace all the other uses of sscanf("%lld") and "%llu" with the calls
to cstring_to_integer() and cstring_to_unsigned() respectively, which
should be faster and provide better error checking.

There should be no change in behaviour.
This commit is contained in:
Vadim Zeitlin
2020-04-05 01:03:39 +02:00
parent 4e3d9e99c7
commit 4d1b30586d
4 changed files with 14 additions and 54 deletions
+3 -3
View File
@@ -8,10 +8,10 @@
#define SOCI_ODBC_SOURCE
#include "soci/soci-platform.h"
#include "soci/odbc/soci-odbc.h"
#include "soci-cstrtoi.h"
#include "soci-exchange-cast.h"
#include "soci-mktime.h"
#include <ctime>
#include <stdio.h> // sscanf()
using namespace soci;
using namespace soci::details;
@@ -182,7 +182,7 @@ void odbc_standard_into_type_backend::post_fetch(
else if (type_ == x_long_long && use_string_for_bigint())
{
long long& ll = exchange_type_cast<x_long_long>(data_);
if (sscanf(buf_, "%" LL_FMT_FLAGS "d", &ll) != 1)
if (!cstring_to_integer(ll, buf_))
{
throw soci_error("Failed to parse the returned 64-bit integer value");
}
@@ -190,7 +190,7 @@ void odbc_standard_into_type_backend::post_fetch(
else if (type_ == x_unsigned_long_long && use_string_for_bigint())
{
unsigned long long& ll = exchange_type_cast<x_unsigned_long_long>(data_);
if (sscanf(buf_, "%" LL_FMT_FLAGS "u", &ll) != 1)
if (!cstring_to_unsigned(ll, buf_))
{
throw soci_error("Failed to parse the returned 64-bit integer value");
}
+3 -3
View File
@@ -8,6 +8,7 @@
#define SOCI_ODBC_SOURCE
#include "soci/soci-platform.h"
#include "soci/odbc/soci-odbc.h"
#include "soci-cstrtoi.h"
#include "soci-mktime.h"
#include "soci-static-assert.h"
#include <cctype>
@@ -15,7 +16,6 @@
#include <cstring>
#include <ctime>
#include <sstream>
#include <stdio.h> // sscanf()
using namespace soci;
using namespace soci::details;
@@ -285,7 +285,7 @@ void odbc_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
std::size_t const vsize = v.size();
for (std::size_t i = 0; i != vsize; ++i)
{
if (sscanf(pos, "%" LL_FMT_FLAGS "d", &v[i]) != 1)
if (!cstring_to_integer(v[i], pos))
{
throw soci_error("Failed to parse the returned 64-bit integer value");
}
@@ -301,7 +301,7 @@ void odbc_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
std::size_t const vsize = v.size();
for (std::size_t i = 0; i != vsize; ++i)
{
if (sscanf(pos, "%" LL_FMT_FLAGS "u", &v[i]) != 1)
if (!cstring_to_unsigned(v[i], pos))
{
throw soci_error("Failed to parse the returned 64-bit integer value");
}
-47
View File
@@ -14,7 +14,6 @@
#include <cstring>
#include <ctime>
#include <vector>
#include <limits>
namespace soci { namespace details { namespace sqlite3 {
@@ -33,52 +32,6 @@ void resize_vector(void *p, std::size_t sz)
v->resize(sz);
}
// helper function for parsing integers
template <typename T>
T string_to_integer(char const * buf)
{
long long t(0);
int n(0);
int const converted = std::sscanf(buf, "%" LL_FMT_FLAGS "d%n", &t, &n);
if (converted == 1 && static_cast<std::size_t>(n) == std::strlen(buf))
{
// successfully converted to long long
// and no other characters were found in the buffer
const T max = (std::numeric_limits<T>::max)();
const T min = (std::numeric_limits<T>::min)();
if (t <= static_cast<long long>(max) &&
t >= static_cast<long long>(min))
{
return static_cast<T>(t);
}
}
throw soci_error("Cannot convert data.");
}
// helper function for parsing unsigned integers
template <typename T>
T string_to_unsigned_integer(char const * buf)
{
unsigned long long t(0);
int n(0);
int const converted = std::sscanf(buf, "%" LL_FMT_FLAGS "u%n", &t, &n);
if (converted == 1 && static_cast<std::size_t>(n) == std::strlen(buf))
{
// successfully converted to unsigned long long
// and no other characters were found in the buffer
T const max = (std::numeric_limits<T>::max)();
if (t <= static_cast<unsigned long long>(max))
{
return static_cast<T>(t);
}
}
throw soci_error("Cannot convert data.");
}
}}} // namespace soci::details::sqlite3
#endif // SOCI_SQLITE3_COMMON_H_INCLUDED
+8 -1
View File
@@ -10,6 +10,7 @@
#endif
#define SOCI_SQLITE3_SOURCE
#include "soci-cstrtoi.h"
#include "soci-dtocstr.h"
#include "soci-exchange-cast.h"
#include "soci/blob.h"
@@ -64,7 +65,13 @@ void set_number_in_vector(void *p, int idx, const sqlite3_column &col)
case dt_date:
case dt_string:
case dt_blob:
set_in_vector(p, idx, string_to_integer<T>(col.buffer_.size_ > 0 ? col.buffer_.constData_ : ""));
{
T value;
if (!details::cstring_to_integer(value, col.buffer_.size_ > 0 ? col.buffer_.constData_ : ""))
throw soci_error("Cannot convert data");
set_in_vector(p, idx, value);
}
break;
case dt_double: