libsoup r1117 - in trunk: . libsoup tests
- From: danw svn gnome org
- To: svn-commits-list gnome org
- Subject: libsoup r1117 - in trunk: . libsoup tests
- Date: Sat, 29 Mar 2008 19:43:18 +0000 (GMT)
Author: danw
Date: Sat Mar 29 19:43:18 2008
New Revision: 1117
URL: http://svn.gnome.org/viewvc/libsoup?rev=1117&view=rev
Log:
* libsoup/soup-date.c (parse_day): fix the test for no-day-parsed
(parse_year): likewise fix the test for no-year-parsed
(parse_time): don't accept empty components here
(parse_textual_date): don't accept a comma if it wasn't preceded
by a weekday
(soup_date_weekday): Fix leap year handling here; the code this
was originally based on only had to work between 1970 and 2038, so
it didn't worry about the mod 100 and mod 400 rules...
* tests/date.c: Add date/string conversion tests (in particular,
to make sure soup_date_weekday is working). Also add test cases
with missing components and make sure they *don't* parse.
Modified:
trunk/ChangeLog
trunk/libsoup/soup-date.c
trunk/tests/date.c
Modified: trunk/libsoup/soup-date.c
==============================================================================
--- trunk/libsoup/soup-date.c (original)
+++ trunk/libsoup/soup-date.c Sat Mar 29 19:43:18 2008
@@ -47,10 +47,47 @@
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
-static const int days_before[] = {
+static const int nonleap_days_in_month[] = {
+ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+static const int nonleap_days_before[] = {
0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
};
+static inline gboolean
+is_leap_year (int year)
+{
+ return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
+}
+
+/* Computes the number of days since proleptic Gregorian 0000-12-31.
+ * (That is, 0001-01-01 is "1", and 1970-01-01 is 719163.
+ */
+static int
+rata_die_day (SoupDate *date)
+{
+ int day;
+
+ day = (date->year - 1) * 365 + ((date->year - 1) / 4) -
+ ((date->year - 1) / 100) + ((date->year - 1) / 400);
+ day += nonleap_days_before[date->month] + date->day;
+ if (is_leap_year (date->year) && date->month > 2)
+ day++;
+ return day;
+}
+
+#define TIME_T_EPOCH_RATA_DIE_DAY 719163
+
+static inline int
+days_in_month (int month, int year)
+{
+ if (month == 2 && is_leap_year (year))
+ return 29;
+ else
+ return nonleap_days_in_month[month];
+}
+
GType
soup_date_get_type (void)
{
@@ -181,7 +218,7 @@
char *end;
date->day = strtoul (*date_string, &end, 10);
- if (end == (char *)date_string)
+ if (end == (char *)*date_string)
return FALSE;
while (*end == ' ' || *end == '-')
@@ -213,7 +250,7 @@
char *end;
date->year = strtoul (*date_string, &end, 10);
- if (end == (char *)date_string)
+ if (end == (char *)*date_string)
return FALSE;
if (end == (char *)*date_string + 2) {
@@ -233,15 +270,20 @@
static inline gboolean
parse_time (SoupDate *date, const char **date_string)
{
- char *p;
+ char *p, *end;
- date->hour = strtoul (*date_string, &p, 10);
- if (*p++ != ':')
+ date->hour = strtoul (*date_string, &end, 10);
+ if (end == (char *)*date_string || *end++ != ':')
+ return FALSE;
+ p = end;
+ date->minute = strtoul (p, &end, 10);
+ if (end == p || *end++ != ':')
return FALSE;
- date->minute = strtoul (p, &p, 10);
- if (*p++ != ':')
+ p = end;
+ date->second = strtoul (p, &end, 10);
+ if (end == p)
return FALSE;
- date->second = strtoul (p, &p, 10);
+ p = end;
while (*p == ' ')
p++;
@@ -289,12 +331,14 @@
parse_textual_date (SoupDate *date, const char *date_string)
{
/* If it starts with a word, it must be a weekday, which we skip */
- while (g_ascii_isalpha (*date_string))
- date_string++;
- if (*date_string == ',')
- date_string++;
- while (g_ascii_isspace (*date_string))
- date_string++;
+ if (g_ascii_isalpha (*date_string)) {
+ while (g_ascii_isalpha (*date_string))
+ date_string++;
+ if (*date_string == ',')
+ date_string++;
+ while (g_ascii_isspace (*date_string))
+ date_string++;
+ }
/* If there's now another word, this must be an asctime-date */
if (g_ascii_isalpha (*date_string)) {
@@ -325,13 +369,6 @@
return TRUE;
}
-static int
-days_in_month (int month, int year)
-{
- return days_before[month + 1] - days_before[month] +
- (((year % 4 == 0) && month == 2) ? 1 : 0);
-}
-
/**
* SoupDateFormat:
* @SOUP_DATE_HTTP: RFC 1123 format, used by the HTTP "Date" header. Eg
@@ -434,18 +471,10 @@
static const char *
soup_date_weekday (SoupDate *date)
{
- int day;
-
/* Proleptic Gregorian 0001-01-01 was a Monday, which
- * corresponds to 1 in the days[] array. So we take the
- * number of days since 0000-12-31, modulo 7.
+ * corresponds to 1 in the days[] array.
*/
- day = (date->year - 1) * 365 + ((date->year - 1) / 4);
- day += days_before[date->month] + date->day;
- if (date->year % 4 == 0 && date->month > 2)
- day++;
-
- return days[day % 7];
+ return days[rata_die_day (date) % 7];
}
/**
@@ -528,11 +557,7 @@
if (sizeof (time_t) == 4 && date->year > 2038)
return (time_t)0x7fffffff;
- tt = (date->year - 1970) * 365;
- tt += (date->year - 1968) / 4;
- tt += days_before[date->month] + date->day - 1;
- if (date->year % 4 == 0 && date->month <= 2)
- tt--;
+ tt = rata_die_day (date) - TIME_T_EPOCH_RATA_DIE_DAY;
tt = ((((tt * 24) + date->hour) * 60) + date->minute) * 60 + date->second;
if (sizeof (time_t) == 4 && tt < 0)
Modified: trunk/tests/date.c
==============================================================================
--- trunk/tests/date.c (original)
+++ trunk/tests/date.c Sat Mar 29 19:43:18 2008
@@ -11,23 +11,41 @@
#include "test-utils.h"
-const char *date_tests[] = {
+static const struct {
+ SoupDateFormat format;
+ const char *date;
+} good_dates[] = {
+ { SOUP_DATE_HTTP, "Sat, 06 Nov 2004 08:09:07 GMT" },
+ { SOUP_DATE_COOKIE, "Sat, 06-Nov-2004 08:09:07 GMT" },
+#ifdef NOT_YET
+ { SOUP_DATE_RFC2822, "Sat, 06 Nov 2004 08:09:07 +0000" },
+#endif
+ { SOUP_DATE_ISO8601_COMPACT, "20041106T080907" },
+ { SOUP_DATE_ISO8601_FULL, "2004-11-06T08:09:07" },
+ { SOUP_DATE_ISO8601_XMLRPC, "20041106T08:09:07" }
+};
+
+static const char *ok_dates[] = {
/* rfc1123-date, and broken variants */
- "Sun, 06 Nov 2004 08:09:07 GMT",
- "Sun, 6 Nov 2004 08:09:07 GMT",
- "Sun, 6 Nov 2004 08:09:07 GMT",
+ "Sat, 06 Nov 2004 08:09:07 GMT",
+ "Sat, 6 Nov 2004 08:09:07 GMT",
+ "Sat, 6 Nov 2004 08:09:07 GMT",
+ "Sat, 06 Nov 2004 08:09:07",
+ "06 Nov 2004 08:09:07 GMT",
/* rfc850-date, and broken variants */
- "Sunday, 06-Nov-04 08:09:07 GMT",
- "Sunday, 6-Nov-04 08:09:07 GMT",
- "Sunday, 6-Nov-04 08:09:07 GMT",
- "Sunday, 06-Nov-104 08:09:07 GMT",
+ "Saturday, 06-Nov-04 08:09:07 GMT",
+ "Saturday, 6-Nov-04 08:09:07 GMT",
+ "Saturday, 6-Nov-04 08:09:07 GMT",
+ "Saturday, 06-Nov-104 08:09:07 GMT",
+ "Saturday, 06-Nov-04 08:09:07",
+ "06-Nov-04 08:09:07 GMT",
/* asctime-date, and broken variants */
- "Sun Nov 6 08:09:07 2004",
- "Sun Nov 06 08:09:07 2004",
- "Sun Nov 6 08:09:07 2004",
- "Sun Nov 6 08:09:07 2004 GMT",
+ "Sat Nov 6 08:09:07 2004",
+ "Sat Nov 06 08:09:07 2004",
+ "Sat Nov 6 08:09:07 2004",
+ "Sat Nov 6 08:09:07 2004 GMT",
/* ISO 8601 */
"2004-11-06T08:09:07Z",
@@ -36,53 +54,130 @@
"20041106T080907+00:00",
/* Netscape cookie spec date, and broken variants */
- "Sun, 06-Nov-2004 08:09:07 GMT",
- "Sun, 6-Nov-2004 08:09:07 GMT",
- "Sun, 6-Nov-2004 08:09:07 GMT",
+ "Sat, 06-Nov-2004 08:09:07 GMT",
+ "Sat, 6-Nov-2004 08:09:07 GMT",
+ "Sat, 6-Nov-2004 08:09:07 GMT",
+ "Sat, 06-Nov-2004 08:09:07",
/* Original version of Netscape cookie spec, and broken variants */
- "Sun, 06-Nov-04 08:09:07 GMT",
- "Sun, 6-Nov-04 08:09:07 GMT",
- "Sun, 6-Nov-04 08:09:07 GMT",
- "Sun, 06-Nov-104 08:09:07 GMT",
+ "Sat, 06-Nov-04 08:09:07 GMT",
+ "Sat, 6-Nov-04 08:09:07 GMT",
+ "Sat, 6-Nov-04 08:09:07 GMT",
+ "Sat, 06-Nov-104 08:09:07 GMT",
+ "Sat, 06-Nov-04 08:09:07",
/* Netscape cookie spec example syntax, and broken variants */
- "Sunday, 06-Nov-04 08:09:07 GMT",
- "Sunday, 6-Nov-04 08:09:07 GMT",
- "Sunday, 6-Nov-04 08:09:07 GMT",
- "Sunday, 06-Nov-104 08:09:07 GMT",
- "Sunday, 06-Nov-2004 08:09:07 GMT",
- "Sunday, 6-Nov-2004 08:09:07 GMT",
- "Sunday, 6-Nov-2004 08:09:07 GMT",
+ "Saturday, 06-Nov-04 08:09:07 GMT",
+ "Saturday, 6-Nov-04 08:09:07 GMT",
+ "Saturday, 6-Nov-04 08:09:07 GMT",
+ "Saturday, 06-Nov-104 08:09:07 GMT",
+ "Saturday, 06-Nov-2004 08:09:07 GMT",
+ "Saturday, 6-Nov-2004 08:09:07 GMT",
+ "Saturday, 6-Nov-2004 08:09:07 GMT",
+ "Saturday, 06-Nov-04 08:09:07",
/* Miscellaneous broken formats seen on the web */
- "Sun 06-Nov-2004 08:9:07",
- "Sunday, 06-Nov-04 8:9:07 GMT",
- "Sun, 06 Nov 2004 08:09:7 GMT",
- "Sun, 06-Nov-2004 08:09:07"
+ "Sat 06-Nov-2004 08:9:07",
+ "Saturday, 06-Nov-04 8:9:07 GMT",
+ "Sat, 06 Nov 2004 08:09:7 GMT"
+};
+
+static const char *bad_dates[] = {
+ /* broken rfc1123-date */
+ ", 06 Nov 2004 08:09:07 GMT",
+ "Sat, Nov 2004 08:09:07 GMT",
+ "Sat, 06 2004 08:09:07 GMT",
+ "Sat, 06 Nov 08:09:07 GMT",
+ "Sat, 06 Nov 2004 :09:07 GMT",
+ "Sat, 06 Nov 2004 09:07 GMT",
+ "Sat, 06 Nov 2004 08::07 GMT",
+ "Sat, 06 Nov 2004 08:09: GMT",
+
+ /* broken rfc850-date */
+ ", 06-Nov-04 08:09:07 GMT",
+ "Saturday, -Nov-04 08:09:07 GMT",
+ "Saturday, Nov-04 08:09:07 GMT",
+ "Saturday, 06-04 08:09:07 GMT",
+ "Saturday, 06--04 08:09:07 GMT",
+ "Saturday, 06-Nov- 08:09:07 GMT",
+ "Saturday, 06-Nov 08:09:07 GMT",
+ "Saturday, 06-Nov-04 :09:07 GMT",
+ "Saturday, 06-Nov-04 09:07 GMT",
+ "Saturday, 06-Nov-04 08::07 GMT",
+ "Saturday, 06-Nov-04 08:09: GMT",
+
+ /* broken asctime-date */
+ "Nov 6 08:09:07 2004",
+ "Sat 6 08:09:07 2004",
+ "Sat Nov 08:09:07 2004",
+ "Sat Nov 6 :09:07 2004",
+ "Sat Nov 6 09:07 2004",
+ "Sat Nov 6 08::07 2004",
+ "Sat Nov 6 08:09: 2004",
+ "Sat Nov 6 08:09:07",
+ "Sat Nov 6 08:09:07 GMT 2004"
};
#define TIME_T 1099728547L
#define TIME_T_STRING "1099728547"
-static void
-check (const char *strdate, SoupDate *date)
+static gboolean
+check_ok (const char *strdate, SoupDate *date)
{
+ debug_printf (2, "%s\n", strdate);
+
if (date &&
date->year == 2004 && date->month == 11 && date->day == 6 &&
date->hour == 8 && date->minute == 9 && date->second == 7) {
soup_date_free (date);
- return;
+ return TRUE;
}
- fprintf (stderr, "date parsing failed for '%s'.\n", strdate);
+ debug_printf (1, " date parsing failed for '%s'.\n", strdate);
if (date) {
- fprintf (stderr, " got: %d %d %d - %d %d %d\n\n",
- date->year, date->month, date->day,
- date->hour, date->minute, date->second);
+ debug_printf (1, " got: %d %d %d - %d %d %d\n\n",
+ date->year, date->month, date->day,
+ date->hour, date->minute, date->second);
soup_date_free (date);
}
errors++;
+ return FALSE;
+}
+
+static void
+check_good (SoupDateFormat format, const char *strdate)
+{
+ SoupDate *date;
+ char *strdate2;
+
+ date = soup_date_new_from_string (strdate);
+ if (date)
+ strdate2 = soup_date_to_string (date, format);
+ if (!check_ok (strdate, date))
+ return;
+
+ if (strcmp (strdate, strdate2) != 0) {
+ debug_printf (1, " restringification failed: '%s' -> '%s'\n",
+ strdate, strdate2);
+ errors++;
+ }
+ g_free (strdate2);
+}
+
+static void
+check_bad (const char *strdate, SoupDate *date)
+{
+ debug_printf (2, "%s\n", strdate);
+
+ if (!date)
+ return;
+ errors++;
+
+ debug_printf (1, " date parsing succeeded for '%s'!\n", strdate);
+ debug_printf (1, " got: %d %d %d - %d %d %d\n\n",
+ date->year, date->month, date->day,
+ date->hour, date->minute, date->second);
+ soup_date_free (date);
}
int
@@ -92,10 +187,18 @@
test_init (argc, argv, NULL);
- for (i = 0; i < G_N_ELEMENTS (date_tests); i++) {
- check (date_tests[i], soup_date_new_from_string (date_tests[i]));
- }
- check (TIME_T_STRING, soup_date_new_from_time_t (TIME_T));
+ debug_printf (1, "Good dates:\n");
+ for (i = 0; i < G_N_ELEMENTS (good_dates); i++)
+ check_good (good_dates[i].format, good_dates[i].date);
+
+ debug_printf (1, "\nOK dates:\n");
+ for (i = 0; i < G_N_ELEMENTS (ok_dates); i++)
+ check_ok (ok_dates[i], soup_date_new_from_string (ok_dates[i]));
+ check_ok (TIME_T_STRING, soup_date_new_from_time_t (TIME_T));
+
+ debug_printf (1, "\nBad dates:\n");
+ for (i = 0; i < G_N_ELEMENTS (bad_dates); i++)
+ check_bad (bad_dates[i], soup_date_new_from_string (bad_dates[i]));
test_cleanup ();
return errors != 0;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]