gnucash maint: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Mon May 28 12:00:07 EDT 2018
Updated via https://github.com/Gnucash/gnucash/commit/74cbde2d (commit)
via https://github.com/Gnucash/gnucash/commit/174752e2 (commit)
via https://github.com/Gnucash/gnucash/commit/8b1b25ae (commit)
from https://github.com/Gnucash/gnucash/commit/aa086893 (commit)
commit 74cbde2d4f8822c330e0eb75777d3e6c1758a58b
Author: John Ralls <jralls at ceridwen.us>
Date: Mon May 28 08:56:01 2018 -0700
normalize date formats the C++ way.
diff --git a/libgnucash/engine/gnc-date.cpp b/libgnucash/engine/gnc-date.cpp
index d82a2ae..edd6eac 100644
--- a/libgnucash/engine/gnc-date.cpp
+++ b/libgnucash/engine/gnc-date.cpp
@@ -733,24 +733,18 @@ floordiv(int a, int b)
* The 'O' and 'E' format modifiers are for localized input/output
* characters. Remove them as we are always using Arabic numbers.
*/
-static char *
-normalize_format (const char *format)
-{
- gint counter = 0, n_counter = 0;
- gchar *normalized;
-
- normalized = g_strdup(format);
- while (format[counter] != '\0')
- {
- normalized[n_counter] = format[counter];
- if ((format[counter] == '%') && \
- (format[counter+1] == 'E' || format[counter+1] == 'O'))
- counter++; // skip format modifier
-
- counter++;
- n_counter++;
- }
- normalized[n_counter] = '\0';
+static inline std::string
+normalize_format (const std::string& format)
+{
+ bool is_pct = false;
+ std::string normalized;
+ std::remove_copy_if(
+ format.begin(), format.end(), back_inserter(normalized),
+ [&is_pct](char e){
+ bool r = (is_pct && (e == 'E' || e == 'O' || e == '-'));
+ is_pct = e == '%';
+ return r;
+ });
return normalized;
}
@@ -846,12 +840,9 @@ qof_scan_date_internal (const char *buff, int *day, int *month, int *year,
if (buff[0] != '\0')
{
struct tm thetime;
- gchar *normalized_format = normalize_format(GNC_D_FMT);
-
/* Parse time string. */
memset(&thetime, -1, sizeof(struct tm));
- strptime (buff, normalized_format, &thetime);
- g_free (normalized_format);
+ strptime (buff, normalize_format(GNC_D_FMT).c_str(), &thetime);
if (third_field)
{
@@ -1045,13 +1036,12 @@ char dateSeparator (void)
struct tm tm;
time64 secs;
gchar *s;
- gchar *normalized_fmt;
secs = gnc_time (NULL);
gnc_localtime_r(&secs, &tm);
- normalized_fmt = normalize_format(qof_date_format_get_string(dateFormat));
- qof_strftime(string, sizeof(string), normalized_fmt, &tm);
- g_free(normalized_fmt);
+ auto normalized_fmt =
+ normalize_format(qof_date_format_get_string(dateFormat));
+ qof_strftime(string, sizeof(string), normalized_fmt.c_str(), &tm);
for (s = string; *s != '\0'; s++)
if (!isdigit(*s))
diff --git a/libgnucash/engine/gnc-datetime.cpp b/libgnucash/engine/gnc-datetime.cpp
index e1f9f4f..f8b52dd 100644
--- a/libgnucash/engine/gnc-datetime.cpp
+++ b/libgnucash/engine/gnc-datetime.cpp
@@ -293,30 +293,6 @@ tz_from_string(std::string str)
return TZ_Ptr(new PTZ(tzstr));
}
-/* The 'O', 'E', and '-' format modifiers are not supported by
- * boost's output facets. Remove them.
- */
-static char *
-normalize_format (const char *format)
-{
- int counter = 0, n_counter = 0;
- char *normalized;
-
- normalized = strdup(format);
- while (format[counter] != '\0')
- {
- normalized[n_counter] = format[counter];
- if ((format[counter] == '%') && \
- (format[counter+1] == '-' || format[counter+1] == 'E' || format[counter+1] == 'O'))
- counter++; // skip format modifier
-
- counter++;
- n_counter++;
- }
- normalized[n_counter] = '\0';
- return normalized;
-}
-
GncDateTimeImpl::GncDateTimeImpl(std::string str) :
m_time(unix_epoch, utc_zone)
{
@@ -394,16 +370,32 @@ GncDateTimeImpl::date() const
return std::unique_ptr<GncDateImpl>(new GncDateImpl(m_time.local_time().date()));
}
+/* The 'O', 'E', and '-' format modifiers are not supported by
+ * boost's output facets. Remove them.
+ */
+static inline std::string
+normalize_format (const std::string& format)
+{
+ bool is_pct = false;
+ std::string normalized;
+ std::remove_copy_if(
+ format.begin(), format.end(), back_inserter(normalized),
+ [&is_pct](char e){
+ bool r = (is_pct && (e == 'E' || e == 'O' || e == '-'));
+ is_pct = e == '%';
+ return r;
+ });
+ return normalized;
+}
+
std::string
GncDateTimeImpl::format(const char* format) const
{
using Facet = boost::local_time::local_time_facet;
std::stringstream ss;
- char *normalized_format = normalize_format(format);
//The stream destructor frees the facet, so it must be heap-allocated.
- auto output_facet(new Facet(normalized_format));
+ auto output_facet(new Facet(normalize_format(format).c_str()));
ss.imbue(std::locale(std::locale(), output_facet));
- free(normalized_format);
ss << m_time;
return ss.str();
}
@@ -413,11 +405,9 @@ GncDateTimeImpl::format_zulu(const char* format) const
{
using Facet = boost::posix_time::time_facet;
std::stringstream ss;
- char *normalized_format = normalize_format(format);
//The stream destructor frees the facet, so it must be heap-allocated.
- auto output_facet(new Facet(normalized_format));
+ auto output_facet(new Facet(normalize_format(format).c_str()));
ss.imbue(std::locale(std::locale(), output_facet));
- free(normalized_format);
ss << m_time.utc_time();
return ss.str();
}
@@ -474,11 +464,9 @@ GncDateImpl::format(const char* format) const
{
using Facet = boost::gregorian::date_facet;
std::stringstream ss;
- char *normalized_format = normalize_format(format);
//The stream destructor frees the facet, so it must be heap-allocated.
- auto output_facet(new Facet(normalized_format));
+ auto output_facet(new Facet(normalize_format(format).c_str()));
ss.imbue(std::locale(std::locale(), output_facet));
- free(normalized_format);
ss << m_greg;
return ss.str();
}
commit 174752e28c83787eeb15f0ccfc77f60b7a3087f4
Merge: aa08689 8b1b25a
Author: John Ralls <jralls at ceridwen.us>
Date: Sat May 26 18:10:02 2018 -0700
Merge Bill Nottingham's 'bad-dates' into maint
commit 8b1b25aee52d3c844a4cbecba7c80b3cd5d8627b
Author: Bill Nottingham <notting at splat.cc>
Date: Tue May 22 23:37:22 2018 -0400
Modify date formatters to strip out certian specifiers.
strptime/strftime supports various modifiers to their parameters.
'E' and 'O': alternate locale-specific formats
(used in default format for Persian, Oriya, Azerbaijani)
'-': padding
(used in default format for Czech)
GnuCash passes dates as integer y/m/d without using locale-specific
formats, so we need to strip out 'E' and 'O' from the format when
scanning dates or determining separators in gnc-date.
None of '-', 'E', or 'O' are supported by boost (and '-' causes
errors), so strip them out from formatters in gnc-datetime as well.
See https://bugzilla.gnome.org/show_bug.cgi?id=795247.
diff --git a/libgnucash/engine/gnc-date.cpp b/libgnucash/engine/gnc-date.cpp
index 881c090..d82a2ae 100644
--- a/libgnucash/engine/gnc-date.cpp
+++ b/libgnucash/engine/gnc-date.cpp
@@ -728,6 +728,32 @@ floordiv(int a, int b)
}
}
+/* Normalize the localized date format to avoid date scanning issues.
+ *
+ * The 'O' and 'E' format modifiers are for localized input/output
+ * characters. Remove them as we are always using Arabic numbers.
+ */
+static char *
+normalize_format (const char *format)
+{
+ gint counter = 0, n_counter = 0;
+ gchar *normalized;
+
+ normalized = g_strdup(format);
+ while (format[counter] != '\0')
+ {
+ normalized[n_counter] = format[counter];
+ if ((format[counter] == '%') && \
+ (format[counter+1] == 'E' || format[counter+1] == 'O'))
+ counter++; // skip format modifier
+
+ counter++;
+ n_counter++;
+ }
+ normalized[n_counter] = '\0';
+ return normalized;
+}
+
/* Convert a string into day, month and year integers
Convert a string into day / month / year integers according to
@@ -820,30 +846,12 @@ qof_scan_date_internal (const char *buff, int *day, int *month, int *year,
if (buff[0] != '\0')
{
struct tm thetime;
- gchar *format = g_strdup (GNC_D_FMT);
- gchar *stripped_format = g_strdup (GNC_D_FMT);
- gint counter = 0, stripped_counter = 0;
-
- /* strptime can't handle the - format modifier
- * let's strip it out of the format before using it
- */
- while (format[counter] != '\0')
- {
- stripped_format[stripped_counter] = format[counter];
- if ((format[counter] == '%') && (format[counter+1] == '-'))
- counter++; // skip - format modifier
-
- counter++;
- stripped_counter++;
- }
- stripped_format[stripped_counter] = '\0';
- g_free (format);
-
+ gchar *normalized_format = normalize_format(GNC_D_FMT);
/* Parse time string. */
memset(&thetime, -1, sizeof(struct tm));
- strptime (buff, stripped_format, &thetime);
- g_free (stripped_format);
+ strptime (buff, normalized_format, &thetime);
+ g_free (normalized_format);
if (third_field)
{
@@ -1037,10 +1045,13 @@ char dateSeparator (void)
struct tm tm;
time64 secs;
gchar *s;
+ gchar *normalized_fmt;
secs = gnc_time (NULL);
gnc_localtime_r(&secs, &tm);
- qof_strftime(string, sizeof(string), GNC_D_FMT, &tm);
+ normalized_fmt = normalize_format(qof_date_format_get_string(dateFormat));
+ qof_strftime(string, sizeof(string), normalized_fmt, &tm);
+ g_free(normalized_fmt);
for (s = string; *s != '\0'; s++)
if (!isdigit(*s))
diff --git a/libgnucash/engine/gnc-datetime.cpp b/libgnucash/engine/gnc-datetime.cpp
index d0958de..344fe5c 100644
--- a/libgnucash/engine/gnc-datetime.cpp
+++ b/libgnucash/engine/gnc-datetime.cpp
@@ -289,6 +289,30 @@ tz_from_string(std::string str)
return TZ_Ptr(new PTZ(tzstr));
}
+/* The 'O', 'E', and '-' format modifiers are not supported by
+ * boost's output facets. Remove them.
+ */
+static char *
+normalize_format (const char *format)
+{
+ int counter = 0, n_counter = 0;
+ char *normalized;
+
+ normalized = strdup(format);
+ while (format[counter] != '\0')
+ {
+ normalized[n_counter] = format[counter];
+ if ((format[counter] == '%') && \
+ (format[counter+1] == '-' || format[counter+1] == 'E' || format[counter+1] == 'O'))
+ counter++; // skip format modifier
+
+ counter++;
+ n_counter++;
+ }
+ normalized[n_counter] = '\0';
+ return normalized;
+}
+
GncDateTimeImpl::GncDateTimeImpl(std::string str) :
m_time(unix_epoch, utc_zone)
{
@@ -371,9 +395,11 @@ GncDateTimeImpl::format(const char* format) const
{
using Facet = boost::local_time::local_time_facet;
std::stringstream ss;
+ char *normalized_format = normalize_format(format);
//The stream destructor frees the facet, so it must be heap-allocated.
- auto output_facet(new Facet(format));
+ auto output_facet(new Facet(normalized_format));
ss.imbue(std::locale(std::locale(), output_facet));
+ free(normalized_format);
ss << m_time;
return ss.str();
}
@@ -383,9 +409,11 @@ GncDateTimeImpl::format_zulu(const char* format) const
{
using Facet = boost::posix_time::time_facet;
std::stringstream ss;
+ char *normalized_format = normalize_format(format);
//The stream destructor frees the facet, so it must be heap-allocated.
- auto output_facet(new Facet(format));
+ auto output_facet(new Facet(normalized_format));
ss.imbue(std::locale(std::locale(), output_facet));
+ free(normalized_format);
ss << m_time.utc_time();
return ss.str();
}
@@ -442,9 +470,11 @@ GncDateImpl::format(const char* format) const
{
using Facet = boost::gregorian::date_facet;
std::stringstream ss;
+ char *normalized_format = normalize_format(format);
//The stream destructor frees the facet, so it must be heap-allocated.
- auto output_facet(new Facet(format));
+ auto output_facet(new Facet(normalized_format));
ss.imbue(std::locale(std::locale(), output_facet));
+ free(normalized_format);
ss << m_greg;
return ss.str();
}
Summary of changes:
libgnucash/engine/gnc-date.cpp | 47 +++++++++++++++++++-------------------
libgnucash/engine/gnc-datetime.cpp | 24 ++++++++++++++++---
2 files changed, 45 insertions(+), 26 deletions(-)
More information about the gnucash-changes
mailing list