gnucash master: Multiple changes pushed
Geert Janssens
gjanssens at code.gnucash.org
Fri Apr 28 14:50:25 EDT 2017
Updated via https://github.com/Gnucash/gnucash/commit/1a3595cb (commit)
via https://github.com/Gnucash/gnucash/commit/7a037932 (commit)
via https://github.com/Gnucash/gnucash/commit/586b89c6 (commit)
via https://github.com/Gnucash/gnucash/commit/610f6309 (commit)
via https://github.com/Gnucash/gnucash/commit/209f9715 (commit)
via https://github.com/Gnucash/gnucash/commit/9b30bb2b (commit)
via https://github.com/Gnucash/gnucash/commit/b7bcd792 (commit)
via https://github.com/Gnucash/gnucash/commit/b5530bd4 (commit)
from https://github.com/Gnucash/gnucash/commit/39195597 (commit)
commit 1a3595cbeb6b6cb3b5771d0e303c0139949169aa
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri Apr 28 16:42:54 2017 +0200
Convert gnc_dmy2timespec{,_end,_neutral} to use the equivalent GncDateTime constructor
This required a couple of tweaks to the tests because:
- the invalid date returned for impossible conversions is different between the old implementation and the cpp edition
- unhandled glib warnings caused the tests to abort
diff --git a/src/engine/test/test-date.cpp b/src/engine/test/test-date.cpp
index 6efc39b..3600e3e 100644
--- a/src/engine/test/test-date.cpp
+++ b/src/engine/test/test-date.cpp
@@ -99,8 +99,10 @@ check_conversion (const char * str, Timespec expected_ts)
|| (g_date_get_year(&d1) != year))
{
fprintf (stderr,
- "\nmis-converted \"%s\" to GDate\n",
- str);
+ "\nmis-converted \"%s\" to GDate. "
+ "Got d1(Y-M-D) = %i-%i-%i, d2(Y-M-D) = %i-%i-%i\n",
+ str, year, month, day,
+ g_date_get_year(&d2), g_date_get_month(&d2), g_date_get_day(&d2));
failure ("misconverted timespec");
return FALSE;
}
diff --git a/src/engine/test/utest-gnc-pricedb.c b/src/engine/test/utest-gnc-pricedb.c
index 691e4bf..b8f5d85 100644
--- a/src/engine/test/utest-gnc-pricedb.c
+++ b/src/engine/test/utest-gnc-pricedb.c
@@ -968,6 +968,11 @@ gnc_pricedb_lookup_day(GNCPriceDB *db,// C: 4 in 2 SCM: 2 in 1 Local: 1:0:0
static void
test_gnc_pricedb_lookup_day (PriceDBFixture *fixture, gconstpointer pData)
{
+ gchar *msg1 = "[gnc_dmy2timespec_internal()] Date computation error from Y-M-D 12-11-18: Year is out of valid range: 1400..10000";
+ gint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
+ gchar *logdomain = "qof.engine";
+ TestErrorStruct check = {loglevel, logdomain, msg1, 0};
+ GLogFunc hdlr = g_log_set_default_handler ((GLogFunc)test_null_handler, &check);
Timespec t = gnc_dmy2timespec(17, 11, 2012);
GNCPrice *price = gnc_pricedb_lookup_day(fixture->pricedb,
fixture->com->usd,
@@ -978,11 +983,13 @@ test_gnc_pricedb_lookup_day (PriceDBFixture *fixture, gconstpointer pData)
fixture->com->usd,
fixture->com->gbp, t);
g_assert_cmpstr(GET_COM_NAME(price), ==, "GBP");
+ g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check);
t = gnc_dmy2timespec(18, 11, 12);
price = gnc_pricedb_lookup_day(fixture->pricedb,
fixture->com->usd,
fixture->com->gbp, t);
g_assert(price == NULL);
+ g_log_set_default_handler (hdlr, 0);
}
// Not Used
diff --git a/src/libqof/qof/gnc-date.cpp b/src/libqof/qof/gnc-date.cpp
index 066a34a..b078da8 100644
--- a/src/libqof/qof/gnc-date.cpp
+++ b/src/libqof/qof/gnc-date.cpp
@@ -1255,78 +1255,44 @@ gnc_timespec2dmy (Timespec t, int *day, int *month, int *year)
#define THIRTY_TWO_YEARS 0x3c30fc00LL
static Timespec
-gnc_dmy2timespec_internal (int day, int month, int year, gboolean start_of_day)
+gnc_dmy2timespec_internal (int day, int month, int year, DayPart day_part)
{
- Timespec result;
- struct tm date;
- long long secs = 0;
-
- date.tm_year = year - 1900;
- date.tm_mon = month - 1;
- date.tm_mday = day;
-
- if (start_of_day)
- gnc_tm_set_day_start(&date);
- else
- gnc_tm_set_day_end(&date);
-
- /* compute number of seconds */
- secs = gnc_mktime (&date);
-
- result.tv_sec = secs;
- result.tv_nsec = 0;
-
- return result;
+ try
+ {
+ auto date = GncDate(year, month, day);
+ return { static_cast<time64>(GncDateTime (date, day_part)), 0 };
+ }
+ catch(const std::logic_error& err)
+ {
+ PWARN("Date computation error from Y-M-D %d-%d-%d: %s",
+ year, month, day, err.what());
+ return {INT64_MAX, 0};
+ }
+ catch(const std::runtime_error& err)
+ {
+ PWARN("Date computation error from Y-M-D %d-%d-%d: %s",
+ year, month, day, err.what());
+ return {INT64_MAX, 0};
+ }
}
Timespec
gnc_dmy2timespec (int day, int month, int year)
{
- return gnc_dmy2timespec_internal (day, month, year, TRUE);
+ return gnc_dmy2timespec_internal (day, month, year, DayPart::start);
}
Timespec
gnc_dmy2timespec_end (int day, int month, int year)
{
- return gnc_dmy2timespec_internal (day, month, year, FALSE);
+ return gnc_dmy2timespec_internal (day, month, year, DayPart::end);
}
Timespec
gnc_dmy2timespec_neutral (int day, int month, int year)
{
- struct tm date;
- memset (&date, 0, sizeof(struct tm));
- date.tm_year = year - 1900;
- date.tm_mon = month - 1;
- date.tm_mday = day;
- date.tm_hour = 10;
- date.tm_min = 59;
- date.tm_sec = 0;
-
- try
- {
- GncDateTime gncdt(date);
- auto offset = gncdt.offset() / 3600;
- if (offset < -11)
- date.tm_hour = -offset;
- if (offset > 13)
- date.tm_hour = 23 - offset;
-
- return {gnc_timegm(&date), 0};
- }
- catch(const std::logic_error& err)
- {
- PWARN("Date computation error from Y-M-D %d-%d-%d: %s",
- year, month, day, err.what());
- return {INT64_MAX, 0};
- }
- catch(const std::runtime_error& err)
- {
- PWARN("Date computation error from Y-M-D %d-%d-%d: %s",
- year, month, day, err.what());
- return {INT64_MAX, 0};
- }
+ return gnc_dmy2timespec_internal (day, month, year, DayPart::neutral);
}
/********************************************************************\
\********************************************************************/
diff --git a/src/libqof/qof/test/test-gnc-date.c b/src/libqof/qof/test/test-gnc-date.c
index 3e00d8c..489bf9b 100644
--- a/src/libqof/qof/test/test-gnc-date.c
+++ b/src/libqof/qof/test/test-gnc-date.c
@@ -114,10 +114,10 @@ setup_begin(FixtureB *f, gconstpointer pData)
f->test[1] = (TimeMap){1918, 3, 31, INT64_C(-1633305600)};
f->test[2] = (TimeMap){1918, 4, 1, INT64_C(-1633219200)};
f->test[3] = (TimeMap){2057, 11, 20, INT64_C(2773440000)};
- f->test[4] = (TimeMap){1257, 07, 02, INT64_C(21695385600)}; /*invalid year*/
- f->test[5] = (TimeMap){2017, 02, 29, INT64_C(1488326400)}; /*invalid day*/
- f->test[6] = (TimeMap){2017, 02, 33, INT64_C(1488672000)}; /*invalid day*/
- f->test[7] = (TimeMap){2017, 13, 29, INT64_C(1517184000)}; /*invalid month*/
+ f->test[4] = (TimeMap){1257, 07, 02, INT64_MAX}; /*invalid year*/
+ f->test[5] = (TimeMap){2017, 02, 29, INT64_MAX}; /*invalid day*/
+ f->test[6] = (TimeMap){2017, 02, 33, INT64_MAX}; /*invalid day*/
+ f->test[7] = (TimeMap){2017, 13, 29, INT64_MAX}; /*invalid month*/
f->test[8] = (TimeMap){2017, 03, 16, INT64_C(1489622400)};
}
@@ -142,10 +142,10 @@ setup_end(FixtureB *f, gconstpointer pData)
f->test[1] = (TimeMap){1918, 3, 31, INT64_C(-1633219201)};
f->test[2] = (TimeMap){1918, 4, 1, INT64_C(-1633132801)};
f->test[3] = (TimeMap){2057, 11, 20, INT64_C(2773526399)};
- f->test[4] = (TimeMap){1257, 07, 02, INT64_C(21695471999)};
- f->test[5] = (TimeMap){2017, 02, 29, INT64_C(1488412799)};
- f->test[6] = (TimeMap){2017, 02, 33, INT64_C(1488758399)};
- f->test[7] = (TimeMap){2017, 13, 29, INT64_C(1517270399)};
+ f->test[4] = (TimeMap){1257, 07, 02, INT64_MAX};
+ f->test[5] = (TimeMap){2017, 02, 29, INT64_MAX};
+ f->test[6] = (TimeMap){2017, 02, 33, INT64_MAX};
+ f->test[7] = (TimeMap){2017, 13, 29, INT64_MAX};
f->test[8] = (TimeMap){2017, 03, 16, INT64_C(1489708799)};
}
@@ -1807,7 +1807,12 @@ gnc_dmy2timespec (int day, int month, int year)// C: 8 in 5 Local: 1:0:0
static void
test_gnc_dmy2timespec (FixtureB *f, gconstpointer pData)
{
-
+ gchar *msg1 = "[qof_dmy2timespec()] Date computation error from Y-M-D 1257-7-2: Time value is outside the supported year range.";
+ gint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
+ gchar *logdomain = "qof.engine";
+ TestErrorStruct check = {loglevel, logdomain, msg1, 0};
+ GLogFunc hdlr = g_log_set_default_handler ((GLogFunc)test_null_handler, &check);
+ g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check);
for (int i = 0; i < sizeof(f->test)/sizeof(TimeMap); ++i)
{
#ifdef HAVE_STRUCT_TM_GMTOFF
@@ -1820,8 +1825,14 @@ test_gnc_dmy2timespec (FixtureB *f, gconstpointer pData)
Timespec r_t = gnc_dmy2timespec (f->test[i].day, f->test[i].mon,
f->test[i].yr);
int offset = gnc_mktime(&tm) - gnc_timegm(&tm);
- g_assert_cmpint (r_t.tv_sec, ==, f->test[i].secs + offset);
+ if (f->test[i].secs == INT64_MAX)
+ /* We use INT64_MAX as invalid timespec.secs.
+ * As we can't *add* to the max, we can ignore the tz offset in this case. */
+ g_assert_cmpint (r_t.tv_sec, ==, INT64_MAX);
+ else
+ g_assert_cmpint (r_t.tv_sec, ==, f->test[i].secs + offset);
}
+ g_log_set_default_handler (hdlr, 0);
}
/* gnc_dmy2timespec_end
Timespec
@@ -1830,6 +1841,12 @@ gnc_dmy2timespec_end (int day, int month, int year)// C: 1 Local: 0:0:0
static void
test_gnc_dmy2timespec_end (FixtureB *f, gconstpointer pData)
{
+ gchar *msg1 = "[qof_dmy2timespec_end()] Date computation error from Y-M-D 1257-7-2: Time value is outside the supported year range.";
+ gint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
+ gchar *logdomain = "qof.engine";
+ TestErrorStruct check = {loglevel, logdomain, msg1, 0};
+ GLogFunc hdlr = g_log_set_default_handler ((GLogFunc)test_null_handler, &check);
+ g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check);
for (int i = 0; i < sizeof(f->test)/sizeof(TimeMap); ++i)
{
#ifdef HAVE_STRUCT_TM_GMTOFF
@@ -1842,8 +1859,14 @@ test_gnc_dmy2timespec_end (FixtureB *f, gconstpointer pData)
Timespec r_t = gnc_dmy2timespec_end (f->test[i].day, f->test[i].mon,
f->test[i].yr);
int offset = gnc_mktime(&tm) - gnc_timegm(&tm);
- g_assert_cmpint (r_t.tv_sec, ==, f->test[i].secs + offset);
+ if (f->test[i].secs == INT64_MAX)
+ /* We use INT64_MAX as invalid timespec.secs.
+ * As we can't *add* to the max, we can ignore the tz offset in this case. */
+ g_assert_cmpint (r_t.tv_sec, ==, INT64_MAX);
+ else
+ g_assert_cmpint (r_t.tv_sec, ==, f->test[i].secs + offset);
}
+ g_log_set_default_handler (hdlr, 0);
}
static GDateTime*
commit 7a037932ae3a5a6aa3304344aa5138715168150d
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri Apr 28 16:38:30 2017 +0200
Align day end time as used in the GncDateTime constructor and gnc_dmy2timespec_end
The former was using 23:59:00 while existing code was using 23:59:59. To avoid
disruptions, stick with the latter in our cpp code as well.
diff --git a/src/libqof/qof/gnc-datetime.cpp b/src/libqof/qof/gnc-datetime.cpp
index a83fc04..6191cf7 100644
--- a/src/libqof/qof/gnc-datetime.cpp
+++ b/src/libqof/qof/gnc-datetime.cpp
@@ -223,7 +223,7 @@ GncDateTimeImpl::GncDateTimeImpl(const GncDateImpl& date, DayPart part) :
using TD = boost::posix_time::time_duration;
static const TD start(0, 0, 0);
static const TD neutral(10, 59, 0);
- static const TD end(23,59, 0);
+ static const TD end(23,59, 59);
TD time_of_day;
switch (part)
{
diff --git a/src/libqof/qof/test/gtest-gnc-datetime.cpp b/src/libqof/qof/test/gtest-gnc-datetime.cpp
index 5f7c676..0730bd3 100644
--- a/src/libqof/qof/test/gtest-gnc-datetime.cpp
+++ b/src/libqof/qof/test/gtest-gnc-datetime.cpp
@@ -236,7 +236,7 @@ TEST(gnc_datetime_constructors, test_gncdate_end_constructor)
const ymd aymd = { 2046, 11, 06 };
GncDateTime atime(GncDate(aymd.year, aymd.month, aymd.day), DayPart::end);
//Skipping timezone information as this can't be controlled.
- EXPECT_EQ(atime.format("%d-%m-%Y %H:%M:%S"), "06-11-2046 23:59:00");
+ EXPECT_EQ(atime.format("%d-%m-%Y %H:%M:%S"), "06-11-2046 23:59:59");
}
TEST(gnc_datetime_constructors, test_gncdate_neutral_constructor)
commit 586b89c6ca7f647b54da4e26f97f060c80b084ec
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri Apr 28 14:17:33 2017 +0200
Fix John's remarks
diff --git a/src/import-export/csv-imp/gnc-tx-import.hpp b/src/import-export/csv-imp/gnc-tx-import.hpp
index c9eb8ca..fbded6e 100644
--- a/src/import-export/csv-imp/gnc-tx-import.hpp
+++ b/src/import-export/csv-imp/gnc-tx-import.hpp
@@ -68,16 +68,23 @@ extern const gchar* currency_format_user[];
extern const int num_date_formats;
extern const gchar* date_format_user[];
-/** Tuple to hold
+/** An enum describing the columns found in a parse_line_t. Currently these are:
* - a tokenized line of input
* - an optional error string
* - a struct to hold user selected properties for a transaction
- * - a struct to hold user selected properties for one or two splits in the above transaction */
-#define PL_INPUT 0
-#define PL_ERROR 1
-#define PL_PRETRANS 2
-#define PL_PRESPLIT 3
-#define PL_SKIP 4
+ * - a struct to hold user selected properties for one or two splits in the above transaction
+ * - a boolean to mark the line as skipped by error and/or user or not */
+enum parse_line_cols {
+ PL_INPUT,
+ PL_ERROR,
+ PL_PRETRANS,
+ PL_PRESPLIT,
+ PL_SKIP
+};
+
+/** Tuple to hold all internal state for one parsed line. The contents of each
+ * colummn is described by the parse_line_cols enum. This enum should be used
+ * with std::get to access the columns. */
using parse_line_t = std::tuple<StrVec,
std::string,
std::shared_ptr<GncPreTrans>,
diff --git a/src/libqof/qof/gnc-datetime.hpp b/src/libqof/qof/gnc-datetime.hpp
index 11880e1..59fb059 100644
--- a/src/libqof/qof/gnc-datetime.hpp
+++ b/src/libqof/qof/gnc-datetime.hpp
@@ -153,23 +153,61 @@ private:
std::unique_ptr<GncDateTimeImpl> m_impl;
};
+/** GnuCash DateFormat class
+ *
+ * A helper class to represent a date format understood
+ * by the GncDate string/format constructor. Consumers
+ * of this header file are not supposed to create
+ * objects of this class themselves. Instead they
+ * can get a list of the understood formats from the
+ * GncDate::c_formats class variable and work with those.
+ */
+
class GncDateFormat
{
public:
+ /** Construct a GncDateFormat with a given format and corresponding
+ * regular expression. This should only be used internally by the
+ * GncDate implementation. Consumers should never construct a GncDateFormat
+ * themselves!
+ */
GncDateFormat (const char* fmt, const char* re) :
m_fmt(fmt), m_re(re) {}
+ /** A string representing the format. */
const std::string m_fmt;
private:
+ /** Regular expression associated with the format string. This is to and
+ * only be used internally by the gnc-datetime code.
+ */
const std::string m_re;
friend class GncDateImpl;
};
+/** GnuCash Date class
+ *
+ * The represented date is limited to the period
+ * between 1400 and 9999 CE.
+ */
class GncDate
{
public:
- /** A vector with all the date formats supported by the string constructor
+ /** A vector with all the date formats supported by the string constructor.
+ * The currently supported formats are:
+ * "y-m-d" (including yyyymmdd)
+ * "d-m-y" (including ddmmyyyy)
+ * "m-d-y" (including mmddyyyy)
+ * "d-m" (including ddmm)
+ * "m-d" (including mmdd)
+ *
+ * Notes:
+ * - while the format names are using a "-" as separator, the
+ * regexes will accept any of "-/.' " and will also work for dates
+ * without separators.
+ * - the format strings are marked for translation so it is possible
+ * to use a localized version of a format string using gettext. Example:
+ * gettext(GncDate::c_formats[0])
*/
static const std::vector<GncDateFormat> c_formats;
/** Construct a GncDate representing the current day.
commit 610f6309a378b03d18e33315f29efaf3dd966ddd
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri Apr 28 18:39:31 2017 +0200
Fix double free abort in gtest-gnc-datetime.cpp
This double free happened after the introduction of a class variable (static member variable
to GndDate and the test compiling in gnc-datetime.cpp *and* at the same time linking to
gnc-qof. This apparently threw off internal memory management. Removing either of linking to
gnc-qof or compiling in the source file solved it.
Credits go to John Ralls for debugging this.
diff --git a/src/libqof/qof/test/CMakeLists.txt b/src/libqof/qof/test/CMakeLists.txt
index 0b1cdf7..0749157 100644
--- a/src/libqof/qof/test/CMakeLists.txt
+++ b/src/libqof/qof/test/CMakeLists.txt
@@ -129,8 +129,11 @@ IF (NOT WIN32)
SET(test_gnc_datetime_SOURCES
${MODULEPATH}/gnc-datetime.cpp
+ ${MODULEPATH}/gnc-timezone.cpp
+ ${MODULEPATH}/gnc-date.cpp
+ ${MODULEPATH}/qoflog.cpp
gtest-gnc-datetime.cpp
${GTEST_SRC})
GNC_ADD_TEST(test-gnc-datetime "${test_gnc_datetime_SOURCES}"
- gtest_qof_INCLUDES gtest_old_qof_LIBS)
+ gtest_qof_INCLUDES gtest_qof_LIBS)
ENDIF()
diff --git a/src/libqof/qof/test/Makefile.am b/src/libqof/qof/test/Makefile.am
index 53f3cec..1f43940 100644
--- a/src/libqof/qof/test/Makefile.am
+++ b/src/libqof/qof/test/Makefile.am
@@ -212,6 +212,8 @@ check_PROGRAMS += test-gnc-timezone
test_gnc_datetime_SOURCES = \
$(top_srcdir)/$(MODULEPATH)/gnc-datetime.cpp \
$(top_srcdir)/$(MODULEPATH)/gnc-timezone.cpp \
+ $(top_srcdir)/$(MODULEPATH)/gnc-date.cpp \
+ $(top_srcdir)/${MODULEPATH}/qoflog.cpp \
gtest-gnc-datetime.cpp
test_gnc_datetime_CPPFLAGS =\
-I$(GTEST_HEADERS) \
@@ -221,10 +223,9 @@ test_gnc_datetime_CPPFLAGS =\
$(BOOST_CPPFLAGS)
test_gnc_datetime_LDADD = \
- -lboost_date_time \
- ${top_builddir}/${MODULEPATH}/libgnc-qof.la \
$(GLIB_LIBS) \
- $(GTEST_LIBS)
+ $(GTEST_LIBS) \
+ ${BOOST_LDFLAGS} -lboost_regex -lboost_date_time
if !GOOGLE_TEST_LIBS
nodist_test_gnc_datetime_SOURCES = \
$(GTEST_SRC)/src/gtest_main.cc
commit 209f97158974d9120e311de5d9bb70a5a10efc49
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri Apr 21 16:58:20 2017 +0200
Add constructor to create GncDate from string and predefined date format
Primary use case is for parsing dates from external sources (importers)
diff --git a/src/libqof/qof/gnc-datetime.cpp b/src/libqof/qof/gnc-datetime.cpp
index f367d45..a83fc04 100644
--- a/src/libqof/qof/gnc-datetime.cpp
+++ b/src/libqof/qof/gnc-datetime.cpp
@@ -29,13 +29,19 @@ extern "C"
}
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/regex.hpp>
+#include <libintl.h>
+#include <map>
#include <memory>
#include <iostream>
#include <sstream>
#include <string>
+#include <vector>
#include "gnc-timezone.hpp"
#include "gnc-datetime.hpp"
+#define N_(string) string //So that xgettext will find it
+
using Date = boost::gregorian::date;
using Month = boost::gregorian::greg_month;
using PTime = boost::posix_time::ptime;
@@ -58,6 +64,77 @@ static constexpr auto ticks_per_second = INT64_C(1000000);
static constexpr auto ticks_per_second = INT64_C(1000000000);
#endif
+/* Vector of date formats understood by gnucash and corresponding regex
+ * to parse each from an external source
+ * Note: while the format names are using a "-" as separator, the
+ * regexes will accept any of "-/.' " and will also work for dates
+ * without separators.
+ */
+const std::vector<GncDateFormat> GncDate::c_formats ({
+ GncDateFormat {
+ N_("y-m-d"),
+ "(?:" // either y-m-d
+ "(?<YEAR>[0-9]+)[-/.' ]+"
+ "(?<MONTH>[0-9]+)[-/.' ]+"
+ "(?<DAY>[0-9]+)"
+ "|" // or CCYYMMDD
+ "(?<YEAR>[0-9]{4})"
+ "(?<MONTH>[0-9]{2})"
+ "(?<DAY>[0-9]{2})"
+ ")"
+ },
+ GncDateFormat {
+ N_("d-m-y"),
+ "(?:" // either d-m-y
+ "(?<DAY>[0-9]+)[-/.' ]+"
+ "(?<MONTH>[0-9]+)[-/.' ]+"
+ "(?<YEAR>[0-9]+)"
+ "|" // or DDMMCCYY
+ "(?<DAY>[0-9]{2})"
+ "(?<MONTH>[0-9]{2})"
+ "(?<YEAR>[0-9]{4})"
+ ")"
+ },
+ GncDateFormat {
+ N_("m-d-y"),
+ "(?:" // either m-d-y
+ "(?<MONTH>[0-9]+)[-/.' ]+"
+ "(?<DAY>[0-9]+)[-/.' ]+"
+ "(?<YEAR>[0-9]+)"
+ "|" // or MMDDCCYY
+ "(?<MONTH>[0-9]{2})"
+ "(?<DAY>[0-9]{2})"
+ "(?<YEAR>[0-9]{4})"
+ ")"
+ },
+ // Note year is still checked for in the regexes below
+ // This is to be able to raise an error if one is found for a yearless date format
+ GncDateFormat {
+ (N_("d-m")),
+ "(?:" // either d-m(-y)
+ "(?<DAY>[0-9]+)[-/.' ]+"
+ "(?<MONTH>[0-9]+)(?:[-/.' ]+"
+ "(?<YEAR>[0-9]+))?"
+ "|" // or DDMM(CCYY)
+ "(?<DAY>[0-9]{2})"
+ "(?<MONTH>[0-9]{2})"
+ "(?<YEAR>[0-9]+)?"
+ ")"
+ },
+ GncDateFormat {
+ (N_("m-d")),
+ "(?:" // either m-d(-y)
+ "(?<MONTH>[0-9]+)[-/.' ]+"
+ "(?<DAY>[0-9]+)(?:[-/.' ]+"
+ "(?<YEAR>[0-9]+))?"
+ "|" // or MMDD(CCYY)
+ "(?<MONTH>[0-9]{2})"
+ "(?<DAY>[0-9]{2})"
+ "(?<YEAR>[0-9]+)?"
+ ")"
+ }
+});
+
/** Private implementation of GncDateTime. See the documentation for that class.
*/
static LDT
@@ -126,6 +203,7 @@ public:
GncDateImpl(const int year, const int month, const int day) :
m_greg(year, static_cast<Month>(month), day) {}
GncDateImpl(Date d) : m_greg(d) {}
+ GncDateImpl(const std::string str, const std::string fmt);
void today() { m_greg = boost::gregorian::day_clock::local_day(); }
ymd year_month_day() const;
@@ -290,8 +368,46 @@ GncDateTimeImpl::format_zulu(const char* format) const
return ss.str();
}
-/* Member function definitions for GncDateTimeImpl.
+/* Member function definitions for GncDateImpl.
*/
+GncDateImpl::GncDateImpl(const std::string str, const std::string fmt) :
+ m_greg(boost::gregorian::day_clock::local_day()) /* Temporarily initialized to today, will be used and adjusted in the code below */
+{
+ auto iter = std::find_if(GncDate::c_formats.cbegin(), GncDate::c_formats.cend(),
+ [&fmt](const GncDateFormat& v){ return (v.m_fmt == fmt); } );
+ if (iter == GncDate::c_formats.cend())
+ throw std::invalid_argument(N_("Unknown date format specifier passed as argument."));
+
+ boost::regex r(iter->m_re);
+ boost::smatch what;
+ if(!boost::regex_search(str, what, r)) // regex didn't find a match
+ throw std::invalid_argument (N_("Value can't be parsed into a date using the selected date format."));
+
+ // Bail out if a year was found with a yearless format specifier
+ auto fmt_has_year = (fmt.find('y') != std::string::npos);
+ if (!fmt_has_year && (what.length("YEAR") != 0))
+ throw std::invalid_argument (N_("Value appears to contain a year while the selected format forbids this."));
+
+ int year;
+ if (fmt_has_year)
+ {
+ /* The input dates have a year, so use that one */
+ year = std::stoi (what.str("YEAR"));
+
+ /* We assume two-digit years to be in the range 1969 - 2068. */
+ if (year < 69)
+ year += 2000;
+ else if (year < 100)
+ year += 1900;
+ }
+ else /* The input dates have no year, so use current year */
+ year = m_greg.year(); // Can use m_greg here as it was already initialized in the initializer list earlier
+
+ m_greg = Date(year,
+ static_cast<Month>(std::stoi (what.str("MONTH"))),
+ std::stoi (what.str("DAY")));
+}
+
ymd
GncDateImpl::year_month_day() const
{
@@ -376,6 +492,8 @@ GncDateTime::format_zulu(const char* format) const
GncDate::GncDate() : m_impl{new GncDateImpl} {}
GncDate::GncDate(int year, int month, int day) :
m_impl(new GncDateImpl(year, month, day)) {}
+GncDate::GncDate(const std::string str, const std::string fmt) :
+m_impl(new GncDateImpl(str, fmt)) {}
GncDate::GncDate(std::unique_ptr<GncDateImpl> impl) :
m_impl(std::move(impl)) {}
GncDate::GncDate(GncDate&&) = default;
diff --git a/src/libqof/qof/gnc-datetime.hpp b/src/libqof/qof/gnc-datetime.hpp
index 74a3bad..11880e1 100644
--- a/src/libqof/qof/gnc-datetime.hpp
+++ b/src/libqof/qof/gnc-datetime.hpp
@@ -28,6 +28,7 @@
#include <cstdint>
#include <memory>
#include <string>
+#include <vector>
typedef struct
{
@@ -152,11 +153,28 @@ private:
std::unique_ptr<GncDateTimeImpl> m_impl;
};
+class GncDateFormat
+{
+public:
+ GncDateFormat (const char* fmt, const char* re) :
+ m_fmt(fmt), m_re(re) {}
+ const std::string m_fmt;
+private:
+ const std::string m_re;
+
+ friend class GncDateImpl;
+};
+
+
class GncDate
{
- public:/** Construct a GncDate representing the current day.
- */
- GncDate();;
+ public:
+ /** A vector with all the date formats supported by the string constructor
+ */
+ static const std::vector<GncDateFormat> c_formats;
+ /** Construct a GncDate representing the current day.
+ */
+ GncDate();
/** Construct a GncDate representing the given year, month, and day in
* the proleptic Gregorian calendar.
*
@@ -171,6 +189,23 @@ class GncDate
* of the constrained range.
*/
GncDate(int year, int month, int day);
+ /** Construct a GncDate by parsing a string assumed to be in the format
+ * passed in.
+ *
+ * The currently recognized formats are d-m-y, m-d-y, y-m-d, m-d, d-m.
+ * Note while the format descriptions use "-" as separator any of
+ * "-" (hyphen), "/" (slash), "'" (single quote), " " (space) or
+ * "." will be accepted.
+ *
+ * @param str The string to be interpreted.
+ * @param fmt The expected date format of the string passed in.
+ * @exception std::invalid_argument if
+ * - the string couldn't be parsed using the provided format
+ * - any of the date components is outside of its limit
+ * (like month being 13, or day being 31 in February)
+ * - fmt doesn't specify a year, yet a year was found in the string
+ */
+ GncDate(const std::string str, const std::string fmt);
GncDate(std::unique_ptr<GncDateImpl> impl);
GncDate(GncDate&&);
~GncDate();
diff --git a/src/libqof/qof/test/gtest-gnc-datetime.cpp b/src/libqof/qof/test/gtest-gnc-datetime.cpp
index 59b19e4..5f7c676 100644
--- a/src/libqof/qof/test/gtest-gnc-datetime.cpp
+++ b/src/libqof/qof/test/gtest-gnc-datetime.cpp
@@ -37,6 +37,152 @@ TEST(gnc_date_constructors, test_ymd_constructor)
EXPECT_FALSE(date.isnull());
}
+typedef struct
+{
+ const char* date_fmt;
+ const char* date_str;
+ int exp_year;
+ int exp_month;
+ int exp_day;
+} parse_date_data;
+
+/* parse_date
+ * time64 parse_date (const char* date_str, int format)// C: 14 in 7 SCM: 9 in 2 Local: 1:0:0
+ */
+TEST(gnc_date_constructors, test_str_format_constructor)
+{
+ auto today = GncDate();
+ auto today_ymd = today.year_month_day();
+ auto curr_year = today_ymd.year;
+
+ parse_date_data test_dates[] =
+ {
+ // supported combinations -/.'
+ { "y-m-d", "2013-08-01", 2013, 8, 1},
+ { "y-m-d", "2013-8-01", 2013, 8, 1},
+ { "y-m-d", "2013-08-1", 2013, 8, 1},
+ { "y-m-d", "2013-8-1", 2013, 8, 1},
+ { "y-m-d", "13-08-01", 2013, 8, 1},
+ { "y-m-d", "13-8-01", 2013, 8, 1},
+ { "y-m-d", "13-08-1", 2013, 8, 1},
+ { "y-m-d", "13-8-1", 2013, 8, 1},
+ { "y-m-d", "2009/11/04", 2009, 11, 4},
+ { "y-m-d", "1985.3.12", 1985, 3, 12},
+ { "y-m-d", "3'6'8", 2003, 6, 8},
+ { "y-m-d", "20130801", 2013, 8, 1},
+ { "d-m-y", "01-08-2013", 2013, 8, 1},
+ { "d-m-y", "01-8-2013", 2013, 8, 1},
+ { "d-m-y", "1-08-2013", 2013, 8, 1},
+ { "d-m-y", "1-8-2013", 2013, 8, 1},
+ { "d-m-y", "01-08-13", 2013, 8, 1},
+ { "d-m-y", "01-8-13", 2013, 8, 1},
+ { "d-m-y", "1-08-13", 2013, 8, 1},
+ { "d-m-y", "1-8-13", 2013, 8, 1},
+ { "d-m-y", "04/11/2009", 2009, 11, 4},
+ { "d-m-y", "12.3.1985", 1985, 3, 12},
+ { "d-m-y", "8'6'3", 2003, 6, 8},
+ { "d-m-y", "01082013", 2013, 8, 1},
+ { "m-d-y", "08-01-2013", 2013, 8, 1},
+ { "m-d-y", "8-01-2013", 2013, 8, 1},
+ { "m-d-y", "08-1-2013", 2013, 8, 1},
+ { "m-d-y", "8-1-2013", 2013, 8, 1},
+ { "m-d-y", "08-01-13", 2013, 8, 1},
+ { "m-d-y", "8-01-13", 2013, 8, 1},
+ { "m-d-y", "08-1-13", 2013, 8, 1},
+ { "m-d-y", "8-1-13", 2013, 8, 1},
+ { "m-d-y", "11/04/2009", 2009, 11, 4},
+ { "m-d-y", "3.12.1985", 1985, 3, 12},
+ { "m-d-y", "6'8'3", 2003, 6, 8},
+ { "m-d-y", "08012013", 2013, 8, 1},
+ { "d-m", "01-08", curr_year, 8, 1},
+ { "d-m", "01-8", curr_year, 8, 1},
+ { "d-m", "1-08", curr_year, 8, 1},
+ { "d-m", "1-8", curr_year, 8, 1},
+ { "d-m", "04/11", curr_year, 11, 4},
+ { "d-m", "12.3", curr_year, 3, 12},
+ { "d-m", "8'6", curr_year, 6, 8},
+ { "d-m", "0108", curr_year, 8, 1},
+ { "m-d", "08-01", curr_year, 8, 1},
+ { "m-d", "8-01", curr_year, 8, 1},
+ { "m-d", "08-1", curr_year, 8, 1},
+ { "m-d", "8-1", curr_year, 8, 1},
+ { "m-d", "11/04", curr_year, 11, 4},
+ { "m-d", "3.12", curr_year, 3, 12},
+ { "m-d", "6'8", curr_year, 6, 8},
+ { "m-d", "0801", curr_year, 8, 1},
+
+ // ambiguous date formats
+ // current parser doesn't know how to disambiguate
+ // and hence refuses to parse
+ // can possibly improved with a smarter parser
+ { "y-m-d", "130801", -1, -1, -1},
+ { "d-m-y", "010813", -1, -1, -1},
+ { "m-d-y", "080113", -1, -1, -1},
+
+ // Combinations that don't make sense
+ // but can still be entered by a user
+ // Should ideally all result in refusal to parse...
+ { "y-m-d", "08-01", -1, -1, -1},
+ { "y-m-d", "0801", -1, -1, -1},
+ { "d-m-y", "01-08", -1, -1, -1},
+ { "d-m-y", "0108", -1, -1, -1},
+ { "m-d-y", "08-01", -1, -1, -1},
+ { "m-d-y", "0801", -1, -1, -1},
+ { "d-m", "01-08-2013", -1, -1, -1},
+ { "d-m", "01-08-13", -1, -1, -1},
+ { "d-m", "08-08-08", -1, -1, -1},
+ { "d-m", "01082013", -1, -1, -1},
+ { "d-m", "010813", -1, -1, -1},
+ { "d-m", "20130108", -1, -1, -1},
+ { "m-d", "08-01-2013", -1, -1, -1},
+ { "m-d", "08-01-13", -1, -1, -1},
+ { "m-d", "2013-08-01", -1, -1, -1},
+ { "m-d", "09-08-01", -1, -1, -1},
+ { "m-d", "08012013", -1, -1, -1},
+ { "m-d", "080113", -1, -1, -1},
+ { "m-d", "20130801", -1, -1, -1},
+
+ // Unknown date format specifier should also trigger an exception
+ { "y-d-m H:M:S", "20130801", -1, -1, -1},
+
+ // Sentinel to mark the end of available tests
+ { "y-m-d", NULL, 0, 0, 0},
+
+ };
+ int i = 0;
+
+ while (test_dates[i].date_str)
+ {
+ int got_year = 0, got_month = 0, got_day = 0;
+
+ try
+ {
+ auto test_date = GncDate (std::string(test_dates[i].date_str), test_dates[i].date_fmt);
+ auto test_ymd = test_date.year_month_day();
+ got_year = test_ymd.year;
+ got_month = test_ymd.month;
+ got_day = test_ymd.day;
+ }
+ catch (const std::invalid_argument& e)
+ {
+ got_year = got_month = got_day = -1;
+ }
+
+ EXPECT_TRUE ((got_year == test_dates[i].exp_year) &&
+ (got_month == test_dates[i].exp_month) &&
+ (got_day == test_dates[i].exp_day))
+ << "GncDate constructor failed for str " << test_dates[i].date_str
+ << " and fmt " << test_dates[i].date_fmt << ".\n"
+ << "Expected: year " << test_dates[i].exp_year
+ << ", month " << test_dates[i].exp_month
+ << ", day " << test_dates[i].exp_day << "\n"
+ << "Actual: year " << got_year << ", month "
+ << got_month << ", day " << got_day << "\n";
+
+ i++;
+ }
+}
+
TEST(gnc_datetime_constructors, test_default_constructor)
{
GncDateTime atime;
commit 9b30bb2b629edbaaf7fa12854f3a7ba3ded84d36
Author: Geert Janssens <geert at kobaltwit.be>
Date: Sat Apr 22 17:00:34 2017 +0200
Various small fixups in csv importer
- Use descriptive names instead of numbers in std::get<>
- Remove unused parameters
- Fix some doxigen comments
diff --git a/src/import-export/csv-imp/assistant-csv-trans-import.cpp b/src/import-export/csv-imp/assistant-csv-trans-import.cpp
index ce4ff79..05219da 100644
--- a/src/import-export/csv-imp/assistant-csv-trans-import.cpp
+++ b/src/import-export/csv-imp/assistant-csv-trans-import.cpp
@@ -793,7 +793,6 @@ CsvImpTransAssist::preview_settings_delete ()
void
CsvImpTransAssist::preview_settings_save ()
{
- auto title = _("Save the Import Settings.");
auto new_name = tx_imp->settings_name();
/* Check if the entry text matches an already existing preset */
@@ -889,7 +888,6 @@ void CsvImpTransAssist::preview_multi_split (bool multi)
* separator checkbuttons or the custom separator entry) is
* changed.
* @param widget The widget that was changed
- * @param info The data that is being configured
*/
void CsvImpTransAssist::preview_update_separators (GtkWidget* widget)
{
@@ -952,8 +950,6 @@ void CsvImpTransAssist::preview_update_separators (GtkWidget* widget)
/** Event handler for clicking one of the format type radio
* buttons. This occurs if the format (Fixed-Width or CSV) is changed.
- * @param csv_button The "Separated" radio button
- * @param info The display of the data being imported
*/
void CsvImpTransAssist::preview_update_file_format ()
{
@@ -1007,7 +1003,6 @@ void CsvImpTransAssist::preview_update_account ()
/** Event handler for a new encoding. This is called when the user
* selects a new encoding; the data is reparsed and shown to the
* user.
- * @param selector The widget the user uses to select a new encoding
* @param encoding The encoding that the user selected
*/
void
@@ -1080,10 +1075,7 @@ enum PreviewDataTableCols {
* user selects a new column type, that column's text must be changed
* to the selection, and any other columns containing that selection
* must be changed to "None" because we don't allow duplicates.
- * @param renderer The renderer of the column the user changed
- * @param path There is only 1 row in info->ctreeview, so this is always 0.
- * @param new_text The text the user selected
- * @param info The display of the data being imported
+ * @param cbox The combo box the user just clicked to make a change
*/
void CsvImpTransAssist::preview_update_col_type (GtkComboBox* cbox)
{
@@ -1470,12 +1462,12 @@ void CsvImpTransAssist::preview_refresh_table ()
GtkTreeIter iter;
gtk_list_store_append (store, &iter);
preview_row_fill_state_cells (store, &iter,
- std::get<1>(parse_line), std::get<4>(parse_line));
+ std::get<PL_ERROR>(parse_line), std::get<PL_SKIP>(parse_line));
/* Fill the data cells. */
- for (auto cell_str_it = std::get<0>(parse_line).cbegin(); cell_str_it != std::get<0>(parse_line).cend(); cell_str_it++)
+ for (auto cell_str_it = std::get<PL_INPUT>(parse_line).cbegin(); cell_str_it != std::get<PL_INPUT>(parse_line).cend(); cell_str_it++)
{
- uint32_t pos = PREV_N_FIXED_COLS + cell_str_it - std::get<0>(parse_line).cbegin();
+ uint32_t pos = PREV_N_FIXED_COLS + cell_str_it - std::get<PL_INPUT>(parse_line).cbegin();
gtk_list_store_set (store, &iter, pos, cell_str_it->c_str(), -1);
}
}
diff --git a/src/import-export/csv-imp/gnc-csv-trans-settings.cpp b/src/import-export/csv-imp/gnc-csv-trans-settings.cpp
index 82b436e..f3456f0 100644
--- a/src/import-export/csv-imp/gnc-csv-trans-settings.cpp
+++ b/src/import-export/csv-imp/gnc-csv-trans-settings.cpp
@@ -245,7 +245,7 @@ CsvTransSettings::load (void)
if (key_char && *key_char != '\0')
m_encoding = key_char;
else
- "UTF-8";
+ m_encoding = "UTF-8";
m_load_error |= handle_load_error (&key_error, group);
if (key_char)
g_free (key_char);
diff --git a/src/import-export/csv-imp/gnc-csv-trans-settings.hpp b/src/import-export/csv-imp/gnc-csv-trans-settings.hpp
index 490eb66..6bcb4a4 100644
--- a/src/import-export/csv-imp/gnc-csv-trans-settings.hpp
+++ b/src/import-export/csv-imp/gnc-csv-trans-settings.hpp
@@ -75,9 +75,6 @@ void remove (void);
* The internally generated presets are read-only. The others
* can be saved to the state file or deleted.
*
- * @param group The group name where the settings are stored in the
- * key file.
- *
* @return true if there was a problem.
*/
bool read_only (void);
@@ -89,8 +86,8 @@ std::string m_encoding; // File encoding
bool m_multi_split; // Assume multiple lines per transaction
int m_date_format; // Date Active id
int m_currency_format; // Currency Active id
-uint32_t m_skip_start_lines; // Number of header rows to skip
-uint32_t m_skip_end_lines; // Number of footer rows to skip
+uint32_t m_skip_start_lines; // Number of header rows to skip
+uint32_t m_skip_end_lines; // Number of footer rows to skip
bool m_skip_alt_lines; // Skip alternate rows
std::string m_separators; // Separators for csv format
diff --git a/src/import-export/csv-imp/gnc-tx-import.cpp b/src/import-export/csv-imp/gnc-tx-import.cpp
index 2e102d4..7dbaff8 100644
--- a/src/import-export/csv-imp/gnc-tx-import.cpp
+++ b/src/import-export/csv-imp/gnc-tx-import.cpp
@@ -59,7 +59,6 @@ const gchar* currency_format_user[] = {N_("Locale"),
/** Constructor for GncTxImport.
- * @return Pointer to a new GncCSvParseData
*/
GncTxImport::GncTxImport(GncImpFileFormat format)
{
@@ -139,7 +138,7 @@ GncImpFileFormat GncTxImport::file_format()
* will force a reparsing of the transaction properties (if there are
* any) by resetting the first column with a transaction property
* it encounters.
- * @param multi_split_val Boolean value with desired state (multi-split
+ * @param multi_split Boolean value with desired state (multi-split
* vs two-split).
*/
void GncTxImport::multi_split (bool multi_split)
@@ -172,7 +171,7 @@ bool GncTxImport::multi_split () { return m_settings.m_multi_split; }
* in the import data.
* In multi-split mode the user has to select an account column so in
* that mode the base_account can't be set.
- * @param base_acct Pointer to an account or NULL.
+ * @param base_account Pointer to an account or NULL.
*/
void GncTxImport::base_account (Account* base_account)
{
@@ -194,7 +193,7 @@ void GncTxImport::base_account (Account* base_account)
/* Set default account for each line's split properties */
for (auto line : m_parsed_lines)
- std::get<3>(line)->set_account (m_settings.m_base_account);
+ std::get<PL_PRESPLIT>(line)->set_account (m_settings.m_base_account);
}
@@ -276,12 +275,12 @@ void GncTxImport::update_skipped_lines(boost::optional<uint32_t> start, boost::o
for (uint32_t i = 0; i < m_parsed_lines.size(); i++)
{
- std::get<4>(m_parsed_lines[i]) =
+ std::get<PL_SKIP>(m_parsed_lines[i]) =
((i < skip_start_lines()) || // start rows to skip
(i >= m_parsed_lines.size() - skip_end_lines()) || // end rows to skip
(((i - skip_start_lines()) % 2 == 1) && // skip every second row...
skip_alt_lines()) || // ...if requested
- (m_skip_errors && !std::get<1>(m_parsed_lines[i]).empty())); // skip lines with errors
+ (m_skip_errors && !std::get<PL_ERROR>(m_parsed_lines[i]).empty())); // skip lines with errors
}
}
@@ -425,7 +424,7 @@ void GncTxImport::tokenize (bool guessColTypes)
if (m_settings.m_base_account)
{
for (auto line : m_parsed_lines)
- std::get<3>(line)->set_account (m_settings.m_base_account);
+ std::get<PL_PRESPLIT>(line)->set_account (m_settings.m_base_account);
}
if (guessColTypes)
@@ -539,7 +538,7 @@ std::string GncTxImport::verify ()
auto have_line_errors = false;
for (auto line : m_parsed_lines)
{
- if (!std::get<4>(line) && !std::get<1>(line).empty())
+ if (!std::get<PL_SKIP>(line) && !std::get<PL_ERROR>(line).empty())
{
have_line_errors = true;
break;
@@ -720,7 +719,7 @@ void GncTxImport::create_transactions ()
++parsed_lines_it)
{
/* Skip current line if the user specified so */
- if ((std::get<4>(*parsed_lines_it)))
+ if ((std::get<PL_SKIP>(*parsed_lines_it)))
continue;
/* Should not throw anymore, otherwise verify needs revision */
@@ -743,11 +742,11 @@ void GncTxImport::update_pre_trans_props (uint32_t row, uint32_t col, GncTransPr
if ((prop_type == GncTransPropType::NONE) || (prop_type > GncTransPropType::TRANS_PROPS))
return; /* Only deal with transaction related properties. */
- auto trans_props = std::make_shared<GncPreTrans> (*(std::get<2>(m_parsed_lines[row])).get());
+ auto trans_props = std::make_shared<GncPreTrans> (*(std::get<PL_PRETRANS>(m_parsed_lines[row])).get());
auto value = std::string();
- if (col < std::get<0>(m_parsed_lines[row]).size())
- value = std::get<0>(m_parsed_lines[row]).at(col);
+ if (col < std::get<PL_INPUT>(m_parsed_lines[row]).size())
+ value = std::get<PL_INPUT>(m_parsed_lines[row]).at(col);
if (value.empty())
trans_props->reset (prop_type);
@@ -762,13 +761,13 @@ void GncTxImport::update_pre_trans_props (uint32_t row, uint32_t col, GncTransPr
/* Do nothing, just prevent the exception from escalating up
* However log the error if it happens on a row that's not skipped
*/
- if (!std::get<4>(m_parsed_lines[row]))
+ if (!std::get<PL_SKIP>(m_parsed_lines[row]))
PINFO("User warning: %s", e.what());
}
}
/* Store the result */
- std::get<2>(m_parsed_lines[row]) = trans_props;
+ std::get<PL_PRETRANS>(m_parsed_lines[row]) = trans_props;
/* For multi-split input data, we need to check whether this line is part of
* a transaction that has already been started by a previous line. */
@@ -779,7 +778,7 @@ void GncTxImport::update_pre_trans_props (uint32_t row, uint32_t col, GncTransPr
/* This line is part of an already started transaction
* continue with that one instead to make sure the split from this line
* gets added to the proper transaction */
- std::get<2>(m_parsed_lines[row]) = m_parent;
+ std::get<PL_PRETRANS>(m_parsed_lines[row]) = m_parent;
}
else
{
@@ -796,11 +795,11 @@ void GncTxImport::update_pre_split_props (uint32_t row, uint32_t col, GncTransPr
if ((prop_type > GncTransPropType::SPLIT_PROPS) || (prop_type <= GncTransPropType::TRANS_PROPS))
return; /* Only deal with split related properties. */
- auto split_props = std::get<3>(m_parsed_lines[row]);
+ auto split_props = std::get<PL_PRESPLIT>(m_parsed_lines[row]);
auto value = std::string();
- if (col < std::get<0>(m_parsed_lines[row]).size())
- value = std::get<0>(m_parsed_lines[row]).at(col);
+ if (col < std::get<PL_INPUT>(m_parsed_lines[row]).size())
+ value = std::get<PL_INPUT>(m_parsed_lines[row]).at(col);
if (value.empty())
split_props->reset (prop_type);
@@ -815,7 +814,7 @@ void GncTxImport::update_pre_split_props (uint32_t row, uint32_t col, GncTransPr
/* Do nothing, just prevent the exception from escalating up
* However log the error if it happens on a row that's not skipped
*/
- if (!std::get<4>(m_parsed_lines[row]))
+ if (!std::get<PL_SKIP>(m_parsed_lines[row]))
PINFO("User warning: %s", e.what());
}
}
@@ -851,9 +850,9 @@ GncTxImport::set_column_type (uint32_t position, GncTransPropType type, bool for
/* Reset date and currency formats for each trans/split props object
* to ensure column updates use the most recent one
*/
- std::get<2>(*parsed_lines_it)->set_date_format (m_settings.m_date_format);
- std::get<3>(*parsed_lines_it)->set_date_format (m_settings.m_date_format);
- std::get<3>(*parsed_lines_it)->set_currency_format (m_settings.m_currency_format);
+ std::get<PL_PRETRANS>(*parsed_lines_it)->set_date_format (m_settings.m_date_format);
+ std::get<PL_PRESPLIT>(*parsed_lines_it)->set_date_format (m_settings.m_date_format);
+ std::get<PL_PRESPLIT>(*parsed_lines_it)->set_currency_format (m_settings.m_currency_format);
uint32_t row = parsed_lines_it - m_parsed_lines.begin();
@@ -862,7 +861,7 @@ GncTxImport::set_column_type (uint32_t position, GncTransPropType type, bool for
*/
if (old_type != type)
{
- auto old_col = std::get<0>(*parsed_lines_it).size(); // Deliberately out of bounds to trigger a reset!
+ auto old_col = std::get<PL_INPUT>(*parsed_lines_it).size(); // Deliberately out of bounds to trigger a reset!
if ((old_type > GncTransPropType::NONE)
&& (old_type <= GncTransPropType::TRANS_PROPS))
update_pre_trans_props (row, old_col, old_type);
@@ -880,9 +879,9 @@ GncTxImport::set_column_type (uint32_t position, GncTransPropType type, bool for
update_pre_split_props (row, position, type);
/* Report errors if there are any */
- auto trans_errors = std::get<2>(*parsed_lines_it)->errors();
- auto split_errors = std::get<3>(*parsed_lines_it)->errors(m_req_mapped_accts);
- std::get<1>(*parsed_lines_it) =
+ auto trans_errors = std::get<PL_PRETRANS>(*parsed_lines_it)->errors();
+ auto split_errors = std::get<PL_PRESPLIT>(*parsed_lines_it)->errors(m_req_mapped_accts);
+ std::get<PL_ERROR>(*parsed_lines_it) =
trans_errors +
(trans_errors.empty() && split_errors.empty() ? std::string() : "\n") +
split_errors;
@@ -907,14 +906,13 @@ GncTxImport::accounts ()
uint32_t tacct_col = tacct_col_it - m_settings.m_column_types.begin();
/* Iterate over all parsed lines */
- auto odd_line = false;
for (auto parsed_line : m_parsed_lines)
{
/* Skip current line if the user specified so */
- if ((std::get<4>(parsed_line)))
+ if ((std::get<PL_SKIP>(parsed_line)))
continue;
- auto col_strs = std::get<0>(parsed_line);
+ auto col_strs = std::get<PL_INPUT>(parsed_line);
if ((acct_col_it != m_settings.m_column_types.end()) && !col_strs[acct_col].empty())
accts.insert(col_strs[acct_col]);
if ((tacct_col_it != m_settings.m_column_types.end()) && !col_strs[tacct_col].empty())
diff --git a/src/import-export/csv-imp/gnc-tx-import.hpp b/src/import-export/csv-imp/gnc-tx-import.hpp
index c763827..c9eb8ca 100644
--- a/src/import-export/csv-imp/gnc-tx-import.hpp
+++ b/src/import-export/csv-imp/gnc-tx-import.hpp
@@ -73,6 +73,11 @@ extern const gchar* date_format_user[];
* - an optional error string
* - a struct to hold user selected properties for a transaction
* - a struct to hold user selected properties for one or two splits in the above transaction */
+#define PL_INPUT 0
+#define PL_ERROR 1
+#define PL_PRETRANS 2
+#define PL_PRESPLIT 3
+#define PL_SKIP 4
using parse_line_t = std::tuple<StrVec,
std::string,
std::shared_ptr<GncPreTrans>,
commit b7bcd792f6e4ff050c26c5ceeab3606b4581eebb
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri Apr 28 18:25:34 2017 +0200
Align cmake rational/numeric test invocation with Makefile based one
This invocation avoids linking in gnc-qof and instead will
directly pull in all sources required.
diff --git a/src/libqof/qof/test/CMakeLists.txt b/src/libqof/qof/test/CMakeLists.txt
index 1e9ab7d..0b1cdf7 100644
--- a/src/libqof/qof/test/CMakeLists.txt
+++ b/src/libqof/qof/test/CMakeLists.txt
@@ -50,9 +50,18 @@ IF (NOT WIN32)
GNC_ADD_TEST(test-qof "${test_qof_SOURCES}" TEST_QOF_INCLUDE_DIRS TEST_QOF_LIBS)
TARGET_COMPILE_DEFINITIONS(test-qof PRIVATE TESTPROG=test_qof)
SET(MODULEPATH ${CMAKE_SOURCE_DIR}/src/libqof/qof)
- SET(gtest_qof_LIBS gnc-qof ${GLIB2_LDFLAGS} ${Boost_LIBRARIES} ${GTEST_LIB})
+ SET(gtest_old_qof_LIBS gnc-qof ${GLIB2_LDFLAGS} ${Boost_LIBRARIES} ${GTEST_LIB})
+ SET(gtest_qof_LIBS
+ ${GLIB2_LDFLAGS}
+ ${GOBJECT_LDFLAGS}
+ ${GMODULE_LDFLAGS}
+ ${GTHREAD_LDFLAGS}
+ ${Boost_LIBRARIES}
+ ${GTEST_LIB})
SET(gtest_qof_INCLUDES
${MODULEPATH}
+ ${CMAKE_BINARY_DIR}/src # for config.h
+ ${CMAKE_SOURCE_DIR}/src # for platform.h
${GLIB2_INCLUDE_DIRS}
${GTEST_INCLUDE_DIR})
@@ -61,7 +70,7 @@ IF (NOT WIN32)
test-gnc-guid.cpp
${GTEST_SRC})
GNC_ADD_TEST(test-gnc-guid "${test_gnc_guid_SOURCES}"
- gtest_qof_INCLUDES gtest_qof_LIBS)
+ gtest_qof_INCLUDES gtest_old_qof_LIBS)
SET(test_kvp_value_SOURCES
${MODULEPATH}/kvp-value.cpp
@@ -69,14 +78,14 @@ IF (NOT WIN32)
test-kvp-frame.cpp
${GTEST_SRC})
GNC_ADD_TEST(test-kvp-value "${test_kvp_value_SOURCES}"
- gtest_qof_INCLUDES gtest_qof_LIBS)
+ gtest_qof_INCLUDES gtest_old_qof_LIBS)
SET(test_qofsession_SOURCES
${MODULEPATH}/qofsession.cpp
test-qofsession.cpp
${GTEST_SRC})
GNC_ADD_TEST(test-qofsession "${test_qofsession_SOURCES}"
- gtest_qof_INCLUDES gtest_qof_LIBS)
+ gtest_qof_INCLUDES gtest_old_qof_LIBS)
SET(test_gnc_int128_SOURCES
${MODULEPATH}/gnc-int128.cpp
@@ -87,13 +96,25 @@ IF (NOT WIN32)
SET(test_gnc_rational_SOURCES
${MODULEPATH}/gnc-rational.cpp
+ ${MODULEPATH}/gnc-numeric.cpp
+ ${MODULEPATH}/gnc-int128.cpp
+ ${MODULEPATH}/gnc-datetime.cpp
+ ${MODULEPATH}/gnc-timezone.cpp
+ ${MODULEPATH}/gnc-date.cpp
+ ${MODULEPATH}/qoflog.cpp
gtest-gnc-rational.cpp
${GTEST_SRC})
GNC_ADD_TEST(test-gnc-rational "${test_gnc_rational_SOURCES}"
gtest_qof_INCLUDES gtest_qof_LIBS)
SET(test_gnc_numeric_SOURCES
+ ${MODULEPATH}/gnc-rational.cpp
+ ${MODULEPATH}/gnc-int128.cpp
${MODULEPATH}/gnc-numeric.cpp
+ ${MODULEPATH}/gnc-datetime.cpp
+ ${MODULEPATH}/gnc-timezone.cpp
+ ${MODULEPATH}/gnc-date.cpp
+ ${MODULEPATH}/qoflog.cpp
gtest-gnc-numeric.cpp
${GTEST_SRC})
GNC_ADD_TEST(test-gnc-numeric "${test_gnc_numeric_SOURCES}"
@@ -104,12 +125,12 @@ IF (NOT WIN32)
gtest-gnc-timezone.cpp
${GTEST_SRC})
GNC_ADD_TEST(test-gnc-timezone "${test_gnc_timezone_SOURCES}"
- gtest_qof_INCLUDES gtest_qof_LIBS)
+ gtest_qof_INCLUDES gtest_old_qof_LIBS)
SET(test_gnc_datetime_SOURCES
${MODULEPATH}/gnc-datetime.cpp
gtest-gnc-datetime.cpp
${GTEST_SRC})
GNC_ADD_TEST(test-gnc-datetime "${test_gnc_datetime_SOURCES}"
- gtest_qof_INCLUDES gtest_qof_LIBS)
+ gtest_qof_INCLUDES gtest_old_qof_LIBS)
ENDIF()
commit b5530bd41fd2d2cc4b738fdfcdd139f17bae49ce
Author: Geert Janssens <geert at kobaltwit.be>
Date: Wed Apr 26 10:59:46 2017 +0200
Fix autotools based build
For some reason gnc-vcs-info.h isn't found properly any more although
the relevant parts of the Makefiles haven't changed compared to the
maint branch. Perhaps a compiler option has changed ? Anyway simply
adding its path explicitly does fix it.
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
index c85a63d..d52fdf1 100644
--- a/src/bin/Makefile.am
+++ b/src/bin/Makefile.am
@@ -16,6 +16,7 @@ AM_CPPFLAGS = -I${top_builddir} ${GLIB_CFLAGS} ${GNOME_CFLAGS} ${GTK_CFLAGS} \
-I${top_srcdir}/src/engine \
-I${top_srcdir}/src/gnome \
-I${top_builddir}/src \
+ -I${top_builddir}/src/core-utils \
-I${top_srcdir}/src/gnc-module \
-I${top_srcdir}/src/libqof/qof \
-I${top_srcdir}/src/report/report-system \
diff --git a/src/gnome-utils/Makefile.am b/src/gnome-utils/Makefile.am
index 8593462..d11c762 100644
--- a/src/gnome-utils/Makefile.am
+++ b/src/gnome-utils/Makefile.am
@@ -12,6 +12,7 @@ AM_CPPFLAGS = \
-I${top_srcdir}/src/app-utils \
-I${top_srcdir}/src \
-I${top_builddir}/src \
+ -I${top_builddir}/src/core-utils \
-I${top_srcdir}/lib/libc \
-I${top_srcdir}/src/libqof/qof \
${GLIB_CFLAGS} \
Summary of changes:
src/bin/Makefile.am | 1 +
src/engine/test/test-date.cpp | 6 +-
src/engine/test/utest-gnc-pricedb.c | 7 +
src/gnome-utils/Makefile.am | 1 +
.../csv-imp/assistant-csv-trans-import.cpp | 16 +--
.../csv-imp/gnc-csv-trans-settings.cpp | 2 +-
.../csv-imp/gnc-csv-trans-settings.hpp | 7 +-
src/import-export/csv-imp/gnc-tx-import.cpp | 56 ++++----
src/import-export/csv-imp/gnc-tx-import.hpp | 16 ++-
src/libqof/qof/gnc-date.cpp | 76 +++--------
src/libqof/qof/gnc-datetime.cpp | 122 ++++++++++++++++-
src/libqof/qof/gnc-datetime.hpp | 79 ++++++++++-
src/libqof/qof/test/CMakeLists.txt | 34 ++++-
src/libqof/qof/test/Makefile.am | 7 +-
src/libqof/qof/test/gtest-gnc-datetime.cpp | 148 ++++++++++++++++++++-
src/libqof/qof/test/test-gnc-date.c | 45 +++++--
16 files changed, 492 insertions(+), 131 deletions(-)
More information about the gnucash-changes
mailing list