136 lines
4.2 KiB
Diff
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);
|