Commit 82038018 authored by Vadim Zeitlin's avatar Vadim Zeitlin

Merge branch 'refactor-parse-std-tm'

Closes https://github.com/SOCI/soci/pull/559
parents a3685fd0 56bc9f9c
......@@ -373,8 +373,8 @@ macro(soci_backend_test)
target_link_libraries(${TEST_TARGET_STATIC}
${SOCI_CORE_DEPS_LIBS}
${THIS_TEST_DEPENDS_LIBRARIES}
soci_core_static
soci_${BACKENDL}_static)
soci_${BACKENDL}_static
soci_core_static)
add_test(${TEST_TARGET_STATIC}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_TARGET_STATIC}
......
......@@ -39,6 +39,11 @@ mktime_from_ymdhms(tm& t,
mktime(&t);
}
// Helper function for parsing datetime values.
//
// Throws if the string in buf couldn't be parsed as a date or a time string.
SOCI_DECL void parse_std_tm(char const *buf, std::tm &t);
} // namespace details
} // namespace soci
......
......@@ -6,68 +6,11 @@
//
#include "common.h"
#include "soci/soci-backend.h"
#include "soci-mktime.h"
#include <ciso646>
#include <cstdlib>
#include <cstring>
#include <ctime>
namespace // anonymous
{
// helper function for parsing decimal data (for std::tm)
long parse10(char const *&p1, char *&p2, const char *msg)
{
long v = std::strtol(p1, &p2, 10);
if (p2 != p1)
{
p1 = p2 + 1;
return v;
}
else
{
throw soci::soci_error(msg);
}
}
} // namespace anonymous
void soci::details::mysql::parse_std_tm(char const *buf, std::tm &t)
{
char const *p1 = buf;
char *p2;
long year, month, day;
long hour = 0, minute = 0, second = 0;
const char *errMsg = "Cannot convert data to std::tm.";
if (strchr(buf, '-') != NULL)
{
year = parse10(p1, p2, errMsg);
month = parse10(p1, p2, errMsg);
day = parse10(p1, p2, errMsg);
}
else
{
year = 2000;
month = 1;
day = 1;
}
if (strchr(buf, ':') != NULL)
{
// there is also the time of day available
hour = parse10(p1, p2, errMsg);
minute = parse10(p1, p2, errMsg);
second = parse10(p1, p2, errMsg);
}
details::mktime_from_ymdhms(t, year, month, day, hour, minute, second);
}
char * soci::details::mysql::quote(MYSQL * conn, const char *s, size_t len)
{
char *retv = new char[2 * len + 3];
......
......@@ -27,9 +27,6 @@ namespace details
namespace mysql
{
// helper function for parsing datetime values
void parse_std_tm(char const *buf, std::tm &t);
// The idea is that infinity - infinity gives NaN, and NaN != NaN is true.
//
// This should work on any IEEE-754-compliant implementation, which is
......
......@@ -11,6 +11,7 @@
#include "soci/soci-platform.h"
#include "common.h"
#include "soci-exchange-cast.h"
#include "soci-mktime.h"
// std
#include <ciso646>
#include <cstdlib>
......
......@@ -8,6 +8,7 @@
#define SOCI_MYSQL_SOURCE
#include "soci/mysql/soci-mysql.h"
#include "soci-mktime.h"
#include "common.h"
#include "soci/soci-platform.h"
#include <ciso646>
......
......@@ -112,9 +112,6 @@ T string_to_unsigned_integer(char const * buf)
}
}
// helper function for parsing datetime values
void parse_std_tm(char const * buf, std::tm & t);
// helper for vector operations
template <typename T>
std::size_t get_vector_size(void * p)
......
......@@ -9,6 +9,7 @@
#include "soci/soci-platform.h"
#include "soci/postgresql/soci-postgresql.h"
#include "soci-cstrtod.h"
#include "soci-mktime.h"
#include "common.h"
#include "soci/rowid.h"
#include "soci/blob.h"
......
......@@ -9,6 +9,7 @@
#include "soci/soci-platform.h"
#include "soci/postgresql/soci-postgresql.h"
#include "soci-cstrtod.h"
#include "soci-mktime.h"
#include "common.h"
#include "soci/type-wrappers.h"
#include <libpq/libpq-fs.h> // libpq
......
//
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include "soci/soci-platform.h"
#include "common.h"
#include "soci/soci-backend.h"
#include "soci-mktime.h"
// std
#include <cstdlib>
#include <ctime>
namespace // anonymous
{
// helper function for parsing decimal data (for std::tm)
long parse10(char const *&p1, char *&p2, char const* const msg)
{
long v = std::strtol(p1, &p2, 10);
if (p2 != p1)
{
p1 = p2 + 1;
return v;
}
else
{
throw soci::soci_error(msg);
}
}
} // namespace anonymous
void soci::details::sqlite3::parse_std_tm(char const *buf, std::tm &t)
{
char const *p1 = buf;
char *p2 = 0;
char const* const errMsg = "Cannot convert data to std::tm.";
long year = parse10(p1, p2, errMsg);
long month = parse10(p1, p2, errMsg);
long day = parse10(p1, p2, errMsg);
long hour = 0, minute = 0, second = 0;
if (*p2 != '\0')
{
// there is also the time of day available
hour = parse10(p1, p2, errMsg);
minute = parse10(p1, p2, errMsg);
second = parse10(p1, p2, errMsg);
}
details::mktime_from_ymdhms(t, year, month, day, hour, minute, second);
}
......@@ -18,9 +18,6 @@
namespace soci { namespace details { namespace sqlite3 {
// helper function for parsing datetime values
void parse_std_tm(char const *buf, std::tm &t);
// helper for vector operations
template <typename T>
std::size_t get_vector_size(void *p)
......
......@@ -12,6 +12,7 @@
#include "common.h"
#include "soci/blob.h"
#include "soci-cstrtod.h"
#include "soci-mktime.h"
#include "soci-exchange-cast.h"
// std
#include <cstdlib>
......
......@@ -17,6 +17,7 @@
#include "soci/soci-platform.h"
#include "soci/sqlite3/soci-sqlite3.h"
#include "soci-cstrtod.h"
#include "soci-mktime.h"
#include "common.h"
// std
#include <cstddef>
......
//
// Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
// Copyright (C) 2017 Vadim Zeitlin.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include "soci/soci-platform.h"
#include "soci/soci-backend.h"
#define SOCI_SOURCE
#include "soci/error.h"
#include "soci-mktime.h"
#include <climits>
#include <cstdlib>
#include <ctime>
#include "common.h"
namespace // anonymous
{
// helper function for parsing decimal data (for std::tm)
long parse10(char const * & p1, char * & p2, char const * msg)
int parse10(char const * & p1, char * & p2)
{
long v = std::strtol(p1, &p2, 10);
if (p2 != p1)
{
if (v < 0)
throw soci::soci_error("Negative date/time field component.");
if (v > INT_MAX)
throw soci::soci_error("Out of range date/time field component.");
p1 = p2 + 1;
return v;
// Cast is safe due to check above.
return static_cast<int>(v);
}
else
{
throw soci::soci_error(msg);
throw soci::soci_error("Cannot parse date/time field component.");
}
}
} // namespace anonymous
void soci::details::postgresql::parse_std_tm(char const * buf, std::tm & t)
void soci::details::parse_std_tm(char const * buf, std::tm & t)
{
char const * p1 = buf;
char * p2;
char separator;
long a, b, c;
long year = 1900, month = 1, day = 1;
long hour = 0, minute = 0, second = 0;
char const * errMsg = "Cannot convert data to std::tm.";
int a, b, c;
int year = 1900, month = 1, day = 1;
int hour = 0, minute = 0, second = 0;
a = parse10(p1, p2, errMsg);
a = parse10(p1, p2);
separator = *p2;
b = parse10(p1, p2, errMsg);
c = parse10(p1, p2, errMsg);
b = parse10(p1, p2);
c = parse10(p1, p2);
if (*p2 == ' ')
{
......@@ -57,9 +64,9 @@ void soci::details::postgresql::parse_std_tm(char const * buf, std::tm & t)
year = a;
month = b;
day = c;
hour = parse10(p1, p2, errMsg);
minute = parse10(p1, p2, errMsg);
second = parse10(p1, p2, errMsg);
hour = parse10(p1, p2);
minute = parse10(p1, p2);
second = parse10(p1, p2);
}
else
{
......@@ -82,5 +89,5 @@ void soci::details::postgresql::parse_std_tm(char const * buf, std::tm & t)
}
}
details::mktime_from_ymdhms(t, year, month, day, hour, minute, second);
mktime_from_ymdhms(t, year, month, day, hour, minute, second);
}
......@@ -363,7 +363,7 @@ TEST_CASE("MySQL datetime", "[mysql][datetime]")
soci::session sql(backEnd, connectString);
std::tm t = std::tm();
sql << "select maketime(19, 54, 52)", into(t);
CHECK(t.tm_year == 100);
CHECK(t.tm_year == 0);
CHECK(t.tm_mon == 0);
CHECK(t.tm_mday == 1);
CHECK(t.tm_hour == 19);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment