glib2/gdate-Use-longest-matching-month-name-in-g_date_set_.patch
2019-09-30 10:40:42 -04:00

136 lines
4.2 KiB
Diff

From ba18822f358c49f15435197dba7c11f6753396f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com>
Date: Tue, 30 Oct 2018 00:00:00 +0000
Subject: [PATCH 258/682] gdate: Use longest matching month name in
g_date_set_parse
There are languages where a name of one month is a substring of another.
Instead of stopping search on the first match use the month that
constitutes the longest match.
Fixes #1343.
---
glib/gdate.c | 75 ++++++++++++++++++++---------------------------
glib/tests/date.c | 34 +++++++++++++++++++++
2 files changed, 65 insertions(+), 44 deletions(-)
diff --git a/glib/gdate.c b/glib/gdate.c
index 4925818b3..5457a3b8c 100644
--- a/glib/gdate.c
+++ b/glib/gdate.c
@@ -931,6 +931,27 @@ struct _GDateParseTokens {
typedef struct _GDateParseTokens GDateParseTokens;
+static inline gboolean
+update_month_match (gsize *longest,
+ const gchar *haystack,
+ const gchar *needle)
+{
+ gsize length;
+
+ if (needle == NULL)
+ return FALSE;
+
+ length = strlen (needle);
+ if (*longest >= length)
+ return FALSE;
+
+ if (strstr (haystack, needle) == NULL)
+ return FALSE;
+
+ *longest = length;
+ return TRUE;
+}
+
#define NUM_LEN 10
/* HOLDS: g_date_global_lock */
@@ -978,6 +999,7 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
if (pt->num_ints < 3)
{
+ gsize longest = 0;
gchar *casefold;
gchar *normalized;
@@ -985,8 +1007,7 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
normalized = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL);
g_free (casefold);
- i = 1;
- while (i < 13)
+ for (i = 1; i < 13; ++i)
{
/* Here month names may be in a genitive case if the language
* grammatical rules require it.
@@ -997,60 +1018,26 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
* genitive case here so they use nominative everywhere.
* For example, English always uses "January".
*/
- if (long_month_names[i] != NULL)
- {
- const gchar *found = strstr (normalized, long_month_names[i]);
-
- if (found != NULL)
- {
- pt->month = i;
- break;
- }
- }
+ if (update_month_match (&longest, normalized, long_month_names[i]))
+ pt->month = i;
/* Here month names will be in a nominative case.
* Examples of how January may look in some languages:
* Catalan: "gener", Croatian: "Siječanj", Polish: "styczeń",
* Upper Sorbian: "Januar".
*/
- if (long_month_names_alternative[i] != NULL)
- {
- const gchar *found = strstr (normalized, long_month_names_alternative[i]);
-
- if (found != NULL)
- {
- pt->month = i;
- break;
- }
- }
+ if (update_month_match (&longest, normalized, long_month_names_alternative[i]))
+ pt->month = i;
/* Differences between abbreviated nominative and abbreviated
* genitive month names are visible in very few languages but
* let's handle them.
*/
- if (short_month_names[i] != NULL)
- {
- const gchar *found = strstr (normalized, short_month_names[i]);
-
- if (found != NULL)
- {
- pt->month = i;
- break;
- }
- }
+ if (update_month_match (&longest, normalized, short_month_names[i]))
+ pt->month = i;
- if (short_month_names_alternative[i] != NULL)
- {
- const gchar *found = strstr (normalized, short_month_names_alternative[i]);
-
- if (found != NULL)
- {
- pt->month = i;
- break;
- }
- }
-
- ++i;
+ if (update_month_match (&longest, normalized, short_month_names_alternative[i]))
+ pt->month = i;
}
g_free (normalized);