Gitweb links:

...log 
http://git.netsurf-browser.org/netsurf.git/shortlog/389220195f6e31768d48901a5e7ae019f112212c
...commit 
http://git.netsurf-browser.org/netsurf.git/commit/389220195f6e31768d48901a5e7ae019f112212c
...tree 
http://git.netsurf-browser.org/netsurf.git/tree/389220195f6e31768d48901a5e7ae019f112212c

The branch, tlsa/date has been created
        at  389220195f6e31768d48901a5e7ae019f112212c (commit)

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=389220195f6e31768d48901a5e7ae019f112212c
commit 389220195f6e31768d48901a5e7ae019f112212c
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Time: Add date string to time_t parser.

diff --git a/utils/time.c b/utils/time.c
index dd67d8a..fbd5ec8 100644
--- a/utils/time.c
+++ b/utils/time.c
@@ -25,17 +25,19 @@
  * \brief Implementation of time operations.
  */
 
+#include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
-#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
 
 #include <curl/curl.h>
 
+#include "utils/str-parse.h"
 #include "utils/errors.h"
 #include "utils/time.h"
 
 
-
 /**
  * Weekdays
  *
@@ -181,6 +183,829 @@ nserror nsc_snptimet(const char *str, size_t size, time_t 
*timep)
 }
 
 
+#ifndef USE_CURL
+
+
+/**
+ * Array of long weekday names.
+ */
+const char * const weekdays_long[NSC_TIME_WEEKDAY__COUNT] = {
+       [NSC_TIME_WEEKDAY_SUN] = "Sunday",
+       [NSC_TIME_WEEKDAY_MON] = "Monday",
+       [NSC_TIME_WEEKDAY_TUE] = "Tuesday",
+       [NSC_TIME_WEEKDAY_WED] = "Wednesday",
+       [NSC_TIME_WEEKDAY_THU] = "Thursday",
+       [NSC_TIME_WEEKDAY_FRI] = "Friday",
+       [NSC_TIME_WEEKDAY_SAT] = "Saturday"
+};
+
+/**
+ * Timezone offsets in mins
+ *
+ * Order doesn't matter.
+ */
+enum nsc_time_zone_offsets {
+       /* Timezones */
+       NSC_TIME_ZONE_OFFSET_IDLE = -12 * 60,
+       NSC_TIME_ZONE_OFFSET_NZST = -12 * 60,
+       NSC_TIME_ZONE_OFFSET_NZT  = -12 * 60,
+       NSC_TIME_ZONE_OFFSET_EAST = -10 * 60,
+       NSC_TIME_ZONE_OFFSET_GST  = -10 * 60,
+       NSC_TIME_ZONE_OFFSET_JST  = - 9 * 60,
+       NSC_TIME_ZONE_OFFSET_CCT  = - 8 * 60,
+       NSC_TIME_ZONE_OFFSET_WAST = - 7 * 60,
+       NSC_TIME_ZONE_OFFSET_EET  = - 2 * 60,
+       NSC_TIME_ZONE_OFFSET_CET  = - 1 * 60,
+       NSC_TIME_ZONE_OFFSET_FWT  = - 1 * 60,
+       NSC_TIME_ZONE_OFFSET_MET  = - 1 * 60,
+       NSC_TIME_ZONE_OFFSET_MEWT = - 1 * 60,
+       NSC_TIME_ZONE_OFFSET_GMT  =   0,
+       NSC_TIME_ZONE_OFFSET_UTC  =   0,
+       NSC_TIME_ZONE_OFFSET_WET  =   0,
+       NSC_TIME_ZONE_OFFSET_WAT  =   1 * 60,
+       NSC_TIME_ZONE_OFFSET_AST  =   4 * 60,
+       NSC_TIME_ZONE_OFFSET_EST  =   5 * 60,
+       NSC_TIME_ZONE_OFFSET_CST  =   6 * 60,
+       NSC_TIME_ZONE_OFFSET_MST  =   7 * 60,
+       NSC_TIME_ZONE_OFFSET_PST  =   8 * 60,
+       NSC_TIME_ZONE_OFFSET_YST  =   9 * 60,
+       NSC_TIME_ZONE_OFFSET_AHST =  10 * 60,
+       NSC_TIME_ZONE_OFFSET_CAT  =  10 * 60,
+       NSC_TIME_ZONE_OFFSET_HST  =  10 * 60,
+       NSC_TIME_ZONE_OFFSET_IDLW =  12 * 60,
+
+       /* Daylight saving modified timezones */
+       NSC_TIME_ZONE_OFFSET_NZDT = NSC_TIME_ZONE_OFFSET_NZT  - 60,
+       NSC_TIME_ZONE_OFFSET_EADT = NSC_TIME_ZONE_OFFSET_EAST - 60,
+       NSC_TIME_ZONE_OFFSET_WADT = NSC_TIME_ZONE_OFFSET_WAST - 60,
+       NSC_TIME_ZONE_OFFSET_CEST = NSC_TIME_ZONE_OFFSET_CET  - 60,
+       NSC_TIME_ZONE_OFFSET_FST  = NSC_TIME_ZONE_OFFSET_FWT  - 60,
+       NSC_TIME_ZONE_OFFSET_MEST = NSC_TIME_ZONE_OFFSET_MET  - 60,
+       NSC_TIME_ZONE_OFFSET_MESZ = NSC_TIME_ZONE_OFFSET_MET  - 60,
+       NSC_TIME_ZONE_OFFSET_BST  = NSC_TIME_ZONE_OFFSET_GMT  - 60,
+       NSC_TIME_ZONE_OFFSET_ADT  = NSC_TIME_ZONE_OFFSET_AST  - 60,
+       NSC_TIME_ZONE_OFFSET_EDT  = NSC_TIME_ZONE_OFFSET_EST  - 60,
+       NSC_TIME_ZONE_OFFSET_CDT  = NSC_TIME_ZONE_OFFSET_CST  - 60,
+       NSC_TIME_ZONE_OFFSET_MDT  = NSC_TIME_ZONE_OFFSET_MST  - 60,
+       NSC_TIME_ZONE_OFFSET_PDT  = NSC_TIME_ZONE_OFFSET_PST  - 60,
+       NSC_TIME_ZONE_OFFSET_YDT  = NSC_TIME_ZONE_OFFSET_YST  - 60,
+       NSC_TIME_ZONE_OFFSET_HDT  = NSC_TIME_ZONE_OFFSET_HST  - 60,
+
+       /* Military timezones */
+       NSC_TIME_ZONE_OFFSET_Y    = -12 * 60,
+       NSC_TIME_ZONE_OFFSET_X    = -11 * 60,
+       NSC_TIME_ZONE_OFFSET_W    = -10 * 60,
+       NSC_TIME_ZONE_OFFSET_V    = - 9 * 60,
+       NSC_TIME_ZONE_OFFSET_U    = - 8 * 60,
+       NSC_TIME_ZONE_OFFSET_T    = - 7 * 60,
+       NSC_TIME_ZONE_OFFSET_S    = - 6 * 60,
+       NSC_TIME_ZONE_OFFSET_R    = - 5 * 60,
+       NSC_TIME_ZONE_OFFSET_Q    = - 4 * 60,
+       NSC_TIME_ZONE_OFFSET_P    = - 3 * 60,
+       NSC_TIME_ZONE_OFFSET_O    = - 2 * 60,
+       NSC_TIME_ZONE_OFFSET_N    = - 1 * 60,
+       NSC_TIME_ZONE_OFFSET_Z    =   0 * 60,
+       NSC_TIME_ZONE_OFFSET_A    =   1 * 60,
+       NSC_TIME_ZONE_OFFSET_B    =   2 * 60,
+       NSC_TIME_ZONE_OFFSET_C    =   3 * 60,
+       NSC_TIME_ZONE_OFFSET_D    =   4 * 60,
+       NSC_TIME_ZONE_OFFSET_E    =   5 * 60,
+       NSC_TIME_ZONE_OFFSET_F    =   6 * 60,
+       NSC_TIME_ZONE_OFFSET_G    =   7 * 60,
+       NSC_TIME_ZONE_OFFSET_H    =   8 * 60,
+       NSC_TIME_ZONE_OFFSET_I    =   9 * 60,
+       NSC_TIME_ZONE_OFFSET_K    =  10 * 60,
+       NSC_TIME_ZONE_OFFSET_L    =  11 * 60,
+       NSC_TIME_ZONE_OFFSET_M    =  12 * 60,
+};
+
+/**
+ * List of timezones.
+ *
+ * The order here is the order they appear in the `timezone_mins` array.
+ * So there is value in putting the most common timezones first.
+ */
+enum nsc_time_zones {
+       NSC_TIME_ZONE_IDLE,
+       NSC_TIME_ZONE_NZST,
+       NSC_TIME_ZONE_NZT,
+       NSC_TIME_ZONE_EAST,
+       NSC_TIME_ZONE_GST,
+       NSC_TIME_ZONE_JST,
+       NSC_TIME_ZONE_CCT,
+       NSC_TIME_ZONE_WAST,
+       NSC_TIME_ZONE_EET,
+       NSC_TIME_ZONE_CET,
+       NSC_TIME_ZONE_FWT,
+       NSC_TIME_ZONE_MET,
+       NSC_TIME_ZONE_MEWT,
+       NSC_TIME_ZONE_GMT,
+       NSC_TIME_ZONE_UTC,
+       NSC_TIME_ZONE_WET,
+       NSC_TIME_ZONE_WAT,
+       NSC_TIME_ZONE_AST,
+       NSC_TIME_ZONE_EST,
+       NSC_TIME_ZONE_CST,
+       NSC_TIME_ZONE_MST,
+       NSC_TIME_ZONE_PST,
+       NSC_TIME_ZONE_YST,
+       NSC_TIME_ZONE_AHST,
+       NSC_TIME_ZONE_CAT,
+       NSC_TIME_ZONE_HST,
+       NSC_TIME_ZONE_IDLW,
+       NSC_TIME_ZONE_NZDT,
+       NSC_TIME_ZONE_EADT,
+       NSC_TIME_ZONE_WADT,
+       NSC_TIME_ZONE_CEST,
+       NSC_TIME_ZONE_FST,
+       NSC_TIME_ZONE_MEST,
+       NSC_TIME_ZONE_MESZ,
+       NSC_TIME_ZONE_BST,
+       NSC_TIME_ZONE_ADT,
+       NSC_TIME_ZONE_EDT,
+       NSC_TIME_ZONE_CDT,
+       NSC_TIME_ZONE_MDT,
+       NSC_TIME_ZONE_PDT,
+       NSC_TIME_ZONE_YDT,
+       NSC_TIME_ZONE_HDT,
+       NSC_TIME_ZONE_Y,
+       NSC_TIME_ZONE_X,
+       NSC_TIME_ZONE_W,
+       NSC_TIME_ZONE_V,
+       NSC_TIME_ZONE_U,
+       NSC_TIME_ZONE_T,
+       NSC_TIME_ZONE_S,
+       NSC_TIME_ZONE_R,
+       NSC_TIME_ZONE_Q,
+       NSC_TIME_ZONE_P,
+       NSC_TIME_ZONE_O,
+       NSC_TIME_ZONE_N,
+       NSC_TIME_ZONE_Z,
+       NSC_TIME_ZONE_A,
+       NSC_TIME_ZONE_B,
+       NSC_TIME_ZONE_C,
+       NSC_TIME_ZONE_D,
+       NSC_TIME_ZONE_E,
+       NSC_TIME_ZONE_F,
+       NSC_TIME_ZONE_G,
+       NSC_TIME_ZONE_H,
+       NSC_TIME_ZONE_I,
+       NSC_TIME_ZONE_K,
+       NSC_TIME_ZONE_L,
+       NSC_TIME_ZONE_M,
+       NSC_TIME_ZONE__COUNT
+};
+
+/**
+ * Array of minute offsets for timezones.
+ */
+const int16_t timezone_mins[NSC_TIME_ZONE__COUNT] = {
+       [NSC_TIME_ZONE_IDLE] = NSC_TIME_ZONE_OFFSET_IDLE,
+       [NSC_TIME_ZONE_NZST] = NSC_TIME_ZONE_OFFSET_NZST,
+       [NSC_TIME_ZONE_NZT]  = NSC_TIME_ZONE_OFFSET_NZT,
+       [NSC_TIME_ZONE_EAST] = NSC_TIME_ZONE_OFFSET_EAST,
+       [NSC_TIME_ZONE_GST]  = NSC_TIME_ZONE_OFFSET_GST,
+       [NSC_TIME_ZONE_JST]  = NSC_TIME_ZONE_OFFSET_JST,
+       [NSC_TIME_ZONE_CCT]  = NSC_TIME_ZONE_OFFSET_CCT,
+       [NSC_TIME_ZONE_WAST] = NSC_TIME_ZONE_OFFSET_WAST,
+       [NSC_TIME_ZONE_EET]  = NSC_TIME_ZONE_OFFSET_EET,
+       [NSC_TIME_ZONE_CET]  = NSC_TIME_ZONE_OFFSET_CET,
+       [NSC_TIME_ZONE_FWT]  = NSC_TIME_ZONE_OFFSET_FWT,
+       [NSC_TIME_ZONE_MET]  = NSC_TIME_ZONE_OFFSET_MET,
+       [NSC_TIME_ZONE_MEWT] = NSC_TIME_ZONE_OFFSET_MEWT,
+       [NSC_TIME_ZONE_GMT]  = NSC_TIME_ZONE_OFFSET_GMT,
+       [NSC_TIME_ZONE_UTC]  = NSC_TIME_ZONE_OFFSET_UTC,
+       [NSC_TIME_ZONE_WET]  = NSC_TIME_ZONE_OFFSET_WET,
+       [NSC_TIME_ZONE_WAT]  = NSC_TIME_ZONE_OFFSET_WAT,
+       [NSC_TIME_ZONE_AST]  = NSC_TIME_ZONE_OFFSET_AST,
+       [NSC_TIME_ZONE_EST]  = NSC_TIME_ZONE_OFFSET_EST,
+       [NSC_TIME_ZONE_CST]  = NSC_TIME_ZONE_OFFSET_CST,
+       [NSC_TIME_ZONE_MST]  = NSC_TIME_ZONE_OFFSET_MST,
+       [NSC_TIME_ZONE_PST]  = NSC_TIME_ZONE_OFFSET_PST,
+       [NSC_TIME_ZONE_YST]  = NSC_TIME_ZONE_OFFSET_YST,
+       [NSC_TIME_ZONE_AHST] = NSC_TIME_ZONE_OFFSET_AHST,
+       [NSC_TIME_ZONE_CAT]  = NSC_TIME_ZONE_OFFSET_CAT,
+       [NSC_TIME_ZONE_HST]  = NSC_TIME_ZONE_OFFSET_HST,
+       [NSC_TIME_ZONE_IDLW] = NSC_TIME_ZONE_OFFSET_IDLW,
+       [NSC_TIME_ZONE_NZDT] = NSC_TIME_ZONE_OFFSET_NZDT,
+       [NSC_TIME_ZONE_EADT] = NSC_TIME_ZONE_OFFSET_EADT,
+       [NSC_TIME_ZONE_WADT] = NSC_TIME_ZONE_OFFSET_WADT,
+       [NSC_TIME_ZONE_CEST] = NSC_TIME_ZONE_OFFSET_CEST,
+       [NSC_TIME_ZONE_FST]  = NSC_TIME_ZONE_OFFSET_FST,
+       [NSC_TIME_ZONE_MEST] = NSC_TIME_ZONE_OFFSET_MEST,
+       [NSC_TIME_ZONE_MESZ] = NSC_TIME_ZONE_OFFSET_MESZ,
+       [NSC_TIME_ZONE_BST]  = NSC_TIME_ZONE_OFFSET_BST,
+       [NSC_TIME_ZONE_ADT]  = NSC_TIME_ZONE_OFFSET_ADT,
+       [NSC_TIME_ZONE_EDT]  = NSC_TIME_ZONE_OFFSET_EDT,
+       [NSC_TIME_ZONE_CDT]  = NSC_TIME_ZONE_OFFSET_CDT,
+       [NSC_TIME_ZONE_MDT]  = NSC_TIME_ZONE_OFFSET_MDT,
+       [NSC_TIME_ZONE_PDT]  = NSC_TIME_ZONE_OFFSET_PDT,
+       [NSC_TIME_ZONE_YDT]  = NSC_TIME_ZONE_OFFSET_YDT,
+       [NSC_TIME_ZONE_HDT]  = NSC_TIME_ZONE_OFFSET_HDT,
+       [NSC_TIME_ZONE_Y]    = NSC_TIME_ZONE_OFFSET_Y,
+       [NSC_TIME_ZONE_X]    = NSC_TIME_ZONE_OFFSET_X,
+       [NSC_TIME_ZONE_W]    = NSC_TIME_ZONE_OFFSET_W,
+       [NSC_TIME_ZONE_V]    = NSC_TIME_ZONE_OFFSET_V,
+       [NSC_TIME_ZONE_U]    = NSC_TIME_ZONE_OFFSET_U,
+       [NSC_TIME_ZONE_T]    = NSC_TIME_ZONE_OFFSET_T,
+       [NSC_TIME_ZONE_S]    = NSC_TIME_ZONE_OFFSET_S,
+       [NSC_TIME_ZONE_R]    = NSC_TIME_ZONE_OFFSET_R,
+       [NSC_TIME_ZONE_Q]    = NSC_TIME_ZONE_OFFSET_Q,
+       [NSC_TIME_ZONE_P]    = NSC_TIME_ZONE_OFFSET_P,
+       [NSC_TIME_ZONE_O]    = NSC_TIME_ZONE_OFFSET_O,
+       [NSC_TIME_ZONE_N]    = NSC_TIME_ZONE_OFFSET_N,
+       [NSC_TIME_ZONE_Z]    = NSC_TIME_ZONE_OFFSET_Z,
+       [NSC_TIME_ZONE_A]    = NSC_TIME_ZONE_OFFSET_A,
+       [NSC_TIME_ZONE_B]    = NSC_TIME_ZONE_OFFSET_B,
+       [NSC_TIME_ZONE_C]    = NSC_TIME_ZONE_OFFSET_C,
+       [NSC_TIME_ZONE_D]    = NSC_TIME_ZONE_OFFSET_D,
+       [NSC_TIME_ZONE_E]    = NSC_TIME_ZONE_OFFSET_E,
+       [NSC_TIME_ZONE_F]    = NSC_TIME_ZONE_OFFSET_F,
+       [NSC_TIME_ZONE_G]    = NSC_TIME_ZONE_OFFSET_G,
+       [NSC_TIME_ZONE_H]    = NSC_TIME_ZONE_OFFSET_H,
+       [NSC_TIME_ZONE_I]    = NSC_TIME_ZONE_OFFSET_I,
+       [NSC_TIME_ZONE_K]    = NSC_TIME_ZONE_OFFSET_K,
+       [NSC_TIME_ZONE_L]    = NSC_TIME_ZONE_OFFSET_L,
+       [NSC_TIME_ZONE_M]    = NSC_TIME_ZONE_OFFSET_M
+};
+
+/**
+ * Array of timezone names.  Order does not matter.
+ */
+const char * const timezones[NSC_TIME_ZONE__COUNT] = {
+       [NSC_TIME_ZONE_IDLE] = "IDLE",
+       [NSC_TIME_ZONE_NZST] = "NZST",
+       [NSC_TIME_ZONE_NZT]  = "NZT",
+       [NSC_TIME_ZONE_EAST] = "EAST",
+       [NSC_TIME_ZONE_GST]  = "GST",
+       [NSC_TIME_ZONE_JST]  = "JST",
+       [NSC_TIME_ZONE_CCT]  = "CCT",
+       [NSC_TIME_ZONE_WAST] = "WAST",
+       [NSC_TIME_ZONE_EET]  = "EET",
+       [NSC_TIME_ZONE_CET]  = "CET",
+       [NSC_TIME_ZONE_FWT]  = "FWT",
+       [NSC_TIME_ZONE_MET]  = "MET",
+       [NSC_TIME_ZONE_MEWT] = "MEWT",
+       [NSC_TIME_ZONE_GMT]  = "GMT",
+       [NSC_TIME_ZONE_UTC]  = "UTC",
+       [NSC_TIME_ZONE_WET]  = "WET",
+       [NSC_TIME_ZONE_WAT]  = "WAT",
+       [NSC_TIME_ZONE_AST]  = "AST",
+       [NSC_TIME_ZONE_EST]  = "EST",
+       [NSC_TIME_ZONE_CST]  = "CST",
+       [NSC_TIME_ZONE_MST]  = "MST",
+       [NSC_TIME_ZONE_PST]  = "PST",
+       [NSC_TIME_ZONE_YST]  = "YST",
+       [NSC_TIME_ZONE_AHST] = "AHST",
+       [NSC_TIME_ZONE_CAT]  = "CAT",
+       [NSC_TIME_ZONE_HST]  = "HST",
+       [NSC_TIME_ZONE_IDLW] = "IDLW",
+       [NSC_TIME_ZONE_NZDT] = "NZDT",
+       [NSC_TIME_ZONE_EADT] = "EADT",
+       [NSC_TIME_ZONE_WADT] = "WADT",
+       [NSC_TIME_ZONE_CEST] = "CEST",
+       [NSC_TIME_ZONE_FST]  = "FST",
+       [NSC_TIME_ZONE_MEST] = "MEST",
+       [NSC_TIME_ZONE_MESZ] = "MESZ",
+       [NSC_TIME_ZONE_BST]  = "BST",
+       [NSC_TIME_ZONE_ADT]  = "ADT",
+       [NSC_TIME_ZONE_EDT]  = "EDT",
+       [NSC_TIME_ZONE_CDT]  = "CDT",
+       [NSC_TIME_ZONE_MDT]  = "MDT",
+       [NSC_TIME_ZONE_PDT]  = "PDT",
+       [NSC_TIME_ZONE_YDT]  = "YDT",
+       [NSC_TIME_ZONE_HDT]  = "HDT",
+       [NSC_TIME_ZONE_Y]    = "Y",
+       [NSC_TIME_ZONE_X]    = "X",
+       [NSC_TIME_ZONE_W]    = "W",
+       [NSC_TIME_ZONE_V]    = "V",
+       [NSC_TIME_ZONE_U]    = "U",
+       [NSC_TIME_ZONE_T]    = "T",
+       [NSC_TIME_ZONE_S]    = "S",
+       [NSC_TIME_ZONE_R]    = "R",
+       [NSC_TIME_ZONE_Q]    = "Q",
+       [NSC_TIME_ZONE_P]    = "P",
+       [NSC_TIME_ZONE_O]    = "O",
+       [NSC_TIME_ZONE_N]    = "N",
+       [NSC_TIME_ZONE_Z]    = "Z",
+       [NSC_TIME_ZONE_A]    = "A",
+       [NSC_TIME_ZONE_B]    = "B",
+       [NSC_TIME_ZONE_C]    = "C",
+       [NSC_TIME_ZONE_D]    = "D",
+       [NSC_TIME_ZONE_E]    = "E",
+       [NSC_TIME_ZONE_F]    = "F",
+       [NSC_TIME_ZONE_G]    = "G",
+       [NSC_TIME_ZONE_H]    = "H",
+       [NSC_TIME_ZONE_I]    = "I",
+       [NSC_TIME_ZONE_K]    = "K",
+       [NSC_TIME_ZONE_L]    = "L",
+       [NSC_TIME_ZONE_M]    = "M"
+};
+
+/**
+ * Flags for tracking the components of a date that have been parsed.
+ */
+enum nsc_date_component_flags {
+       NSC_COMPONENT_FLAGS_NONE            = 0,
+       NSC_COMPONENT_FLAGS_HAVE_YEARS      = (1 << 0),
+       NSC_COMPONENT_FLAGS_HAVE_MONTHS     = (1 << 1),
+       NSC_COMPONENT_FLAGS_HAVE_DAYS       = (1 << 2),
+       NSC_COMPONENT_FLAGS_HAVE_HOURS      = (1 << 3),
+       NSC_COMPONENT_FLAGS_HAVE_MINS       = (1 << 4),
+       NSC_COMPONENT_FLAGS_HAVE_SECS       = (1 << 5),
+       NSC_COMPONENT_FLAGS_HAVE_TIMEZONE   = (1 << 6),
+       NSC_COMPONENT_FLAGS_HAVE_WEEKDAY    = (1 << 7),
+       NSC_COMPONENT_FLAGS__HAVE_YYYYMMDD  =
+                       NSC_COMPONENT_FLAGS_HAVE_YEARS   |
+                       NSC_COMPONENT_FLAGS_HAVE_MONTHS  |
+                       NSC_COMPONENT_FLAGS_HAVE_DAYS,
+       NSC_COMPONENT_FLAGS__HAVE_HHMMSS    =
+                       NSC_COMPONENT_FLAGS_HAVE_HOURS   |
+                       NSC_COMPONENT_FLAGS_HAVE_MINS    |
+                       NSC_COMPONENT_FLAGS_HAVE_SECS,
+       NSC_COMPONENT_FLAGS__HAVE_ALL       =
+                       NSC_COMPONENT_FLAGS_HAVE_YEARS   |
+                       NSC_COMPONENT_FLAGS_HAVE_MONTHS  |
+                       NSC_COMPONENT_FLAGS_HAVE_DAYS    |
+                       NSC_COMPONENT_FLAGS_HAVE_HOURS   |
+                       NSC_COMPONENT_FLAGS_HAVE_MINS    |
+                       NSC_COMPONENT_FLAGS_HAVE_SECS    |
+                       NSC_COMPONENT_FLAGS_HAVE_TIMEZONE
+};
+
+/**
+ * Context for date parsing.
+ */
+struct nsc_date_parse_ctx {
+       enum {
+               PARSE_STATE_NONE,
+               PARSE_STATE_HAD_PLUS,
+               PARSE_STATE_HAD_MINUS
+       } state; /**< Used for handling neumenrical timezone */
+       uint8_t secs;
+       uint8_t mins;
+       uint8_t hours;
+       uint8_t days;
+       uint8_t months;
+       uint16_t years;
+       int16_t timezone_offset_mins;
+};
+
+
+/**
+ * Helper for testing whether any of the flags in mask are set.
+ *
+ * \param[in] flags  Flags to to check.
+ * \param[in] mask   The set of flags to check for in `flags`.
+ * \return true iff any flags in `mask` are set in `flags`, else false.
+ */
+static bool flags_chk(
+               enum nsc_date_component_flags flags,
+               enum nsc_date_component_flags mask)
+{
+       return flags & mask;
+}
+
+/**
+ * Helper for testing whether all of the flags in mask are set.
+ *
+ * \param[in] flags  Flags to to check.
+ * \param[in] mask   The set of flags to check for in `flags`.
+ * \return true iff all flags in `mask` are set in `flags`, else false.
+ */
+static bool flags_chk_all(
+               enum nsc_date_component_flags flags,
+               enum nsc_date_component_flags mask)
+{
+       return (flags & mask) == mask;
+}
+
+
+/**
+ * Test for a weekday name in a string (case insensitive).
+ *
+ * \param[in]     str    String to parse a weekday name in.
+ * \param[in,out] flags  Flags indicating which date components have been
+ *                       found in `str` already.  If a weekday component
+ *                       is found, the weekday flag is set.
+ * \param[in]     len    Number of consecutive alphabetical characters.
+ * \return true iff weekday component is found, else false.
+ */
+static inline bool time__parse_weekday(
+               const char *str,
+               enum nsc_date_component_flags *flags,
+               size_t len)
+{
+       const char * const *names = (len == 3) ?
+                       weekdays_short : weekdays_long;
+
+       if (flags_chk(*flags, NSC_COMPONENT_FLAGS_HAVE_WEEKDAY)) {
+               return false;
+       }
+
+       for (uint32_t i = 0; i < NSC_TIME_WEEKDAY__COUNT; i++) {
+               if (strings_equal_caseless(names[i], str)) {
+                       *flags |= NSC_COMPONENT_FLAGS_HAVE_WEEKDAY;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
+/**
+ * Attempt to parse a month name in a string (case insensitive).
+ *
+ * \param[in]     str    String to parse a month name in.
+ * \param[in,out] flags  Flags indicating which date components have been
+ *                       found in `str` already.  If a month component
+ *                       is found, the month flag is set.
+ * \param[in,out] ctx    Current date parsing context.  If month component
+ *                       is found, the context's month value is set.
+ * \return true iff month name component is found, else false.
+ */
+static inline bool time__parse_month(
+               const char *str,
+               enum nsc_date_component_flags *flags,
+               struct nsc_date_parse_ctx *ctx)
+{
+       if (flags_chk(*flags, NSC_COMPONENT_FLAGS_HAVE_MONTHS)) {
+               return false;
+       }
+
+       for (uint32_t i = 0; i < NSC_TIME_MONTH__COUNT; i++) {
+               if (strings_equal_caseless(months[i], str)) {
+                       *flags |= NSC_COMPONENT_FLAGS_HAVE_MONTHS;
+                       ctx->months = i;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
+/**
+ * Attempt to parse a timezone name in a string (case insensitive).
+ *
+ * \param[in]     str    String to parse a timezone name in.
+ * \param[in,out] flags  Flags indicating which date components have been
+ *                       found in `str` already.  If a timezone component
+ *                       is found, the timezone flag is set.
+ * \param[in,out] ctx    Current date parsing context.  If timezone component
+ *                       is found, the context's timezone value is set.
+ * \return true iff timezone name component is found, else false.
+ */
+static inline bool time__parse_timezone(
+               const char *str,
+               enum nsc_date_component_flags *flags,
+               struct nsc_date_parse_ctx *ctx)
+{
+       if (flags_chk(*flags, NSC_COMPONENT_FLAGS_HAVE_TIMEZONE)) {
+               return false;
+       }
+
+       for (uint32_t i = 0; i < NSC_TIME_ZONE__COUNT; i++) {
+               if (strings_equal_caseless(timezones[i], str)) {
+                       *flags |= NSC_COMPONENT_FLAGS_HAVE_TIMEZONE;
+                       ctx->timezone_offset_mins = timezone_mins[i];
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
+/**
+ * Attempt to parse an "hh:mm:ss" time from a string.
+ *
+ * \param[in]     str    String to parse a time in.
+ * \param[in,out] flags  Flags indicating which date components have been
+ *                       found in `str` already.  If a time component
+ *                       is found, the hours, mins and secs flags are set.
+ * \param[in,out] ctx    Current date parsing context.  If time component
+ *                       is found, the context's time values are set.
+ * \param[in,out] len    The number of characters until the first non-digit.
+ *                       Iff a time component is found, updated to the number
+ *                       of comsumend characters.
+ * \return true iff time component is found, else false.
+ */
+static inline bool time__parse_hh_mm_ss(
+               const char *str,
+               enum nsc_date_component_flags *flags,
+               struct nsc_date_parse_ctx *ctx,
+               size_t *len)
+{
+       size_t l;
+
+       if (*len != 2 || flags_chk(*flags, NSC_COMPONENT_FLAGS__HAVE_HHMMSS)) {
+               return false;
+       }
+
+       l = *len + count_digit_or_colon(str + *len);
+       if (l == 8) {
+               int h, m, s, count;
+               count = sscanf(str, "%02d:%02d:%02d", &h, &m, &s);
+               if (count == 3) {
+                       ctx->hours = h;
+                       ctx->mins  = m;
+                       ctx->secs  = s;
+                       *flags |= NSC_COMPONENT_FLAGS__HAVE_HHMMSS;
+                       *len = l;
+                       return true;
+               }
+       } else if (l == 5) {
+               int h, m, count;
+               count = sscanf(str, "%02d:%02d", &h, &m);
+               if (count == 2) {
+                       ctx->hours = h;
+                       ctx->mins  = m;
+                       ctx->secs  = 0;
+                       *flags |= NSC_COMPONENT_FLAGS__HAVE_HHMMSS;
+                       *len = l;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
+/**
+ * Attempt to parse a number from a date string.
+ *
+ * How the number is treated depends on various things:
+ *
+ * - its character length,
+ * - its value,
+ * - which date components have already been parsed
+ *
+ * \param[in]     str    String to parse a time in.
+ * \param[in,out] flags  Flags indicating which date components have been
+ *                       found in `str` already.  If any component is found,
+ *                       their flags are set.
+ * \param[in,out] ctx    Current date parsing context.  If any component
+ *                       is found, the appropriate context values are set.
+ * \param[in]     len    The number of characters until the first non-digit.
+ * \return true iff a component is found, else false.
+ */
+static inline bool time__parse_number(
+               const char *str,
+               enum nsc_date_component_flags *flags,
+               struct nsc_date_parse_ctx *ctx,
+               size_t len)
+{
+       int value;
+
+       if (len != string_to_int(str, &value)) {
+               return false;
+       }
+
+       switch (len) {
+       case 8:
+               if (!flags_chk(*flags, NSC_COMPONENT_FLAGS__HAVE_YYYYMMDD)) {
+                       ctx->years  =  value / 10000;
+                       ctx->months = (value % 10000) / 100 - 1;
+                       ctx->days   =  value % 100;
+                       *flags |= NSC_COMPONENT_FLAGS__HAVE_YYYYMMDD;
+                       return true;
+               }
+               break;
+
+       case 4:
+               if (!flags_chk(*flags, NSC_COMPONENT_FLAGS_HAVE_TIMEZONE)) {
+                       if (ctx->state != PARSE_STATE_NONE &&
+                                       value <= 1400) {
+                               ctx->timezone_offset_mins =
+                                               value / 100 * 60 +
+                                               value % 100;
+                               if (ctx->state == PARSE_STATE_HAD_MINUS) {
+                                       ctx->timezone_offset_mins *= -1;
+                               }
+                               *flags |= NSC_COMPONENT_FLAGS_HAVE_TIMEZONE;
+                               return true;
+                       }
+               }
+               if (!flags_chk(*flags, NSC_COMPONENT_FLAGS_HAVE_YEARS)) {
+                       ctx->years = value;
+                       *flags |= NSC_COMPONENT_FLAGS_HAVE_YEARS;
+                       return true;
+               }
+               break;
+
+       case 2:
+               if (!flags_chk(*flags, NSC_COMPONENT_FLAGS_HAVE_DAYS) &&
+                               value <= 31) {
+                       ctx->days = value;
+                       *flags |= NSC_COMPONENT_FLAGS_HAVE_DAYS;
+                       return true;
+               }
+               if (!flags_chk(*flags, NSC_COMPONENT_FLAGS_HAVE_YEARS)) {
+                       ctx->years = (value > 70) ?
+                                       value + 1900 :
+                                       value + 2000;
+                       *flags |= NSC_COMPONENT_FLAGS_HAVE_YEARS;
+                       return true;
+               }
+               break;
+
+       case 1:
+               if (!flags_chk(*flags, NSC_COMPONENT_FLAGS_HAVE_DAYS)) {
+                       ctx->days = value;
+                       *flags |= NSC_COMPONENT_FLAGS_HAVE_DAYS;
+                       return true;
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return false;
+}
+
+/**
+ * Get number of leap days up until end of given year.
+ *
+ * \param[in] year  Year to count leap years up to.
+ * \return Number of leap days up to end of `year`.
+ */
+static inline int time__get_leap_days(int year)
+{
+       return (year / 4) - (year / 100) + (year / 400);
+}
+
+
+/**
+ * Helper to convert a date string context to a time_t.
+ *
+ * \param[in]  ctx    Current date parsing context.
+ * \param[in]  flags  Flags indicating which date components have been set.
+ * \param[out] time   Returns the number of seconds since 1 Jan 1970 00:00 UTC.
+ * \return NSERROR_OK on success, appropriate error otherwise.
+ */
+static nserror time__ctx_to_time_t(
+               const struct nsc_date_parse_ctx *ctx,
+               enum nsc_date_component_flags flags,
+               time_t *time)
+{
+       enum {
+               NSC_MONTH_DAYS_JAN = 31,
+               NSC_MONTH_DAYS_FEB = 28, /**< Leap years handled separatly */
+               NSC_MONTH_DAYS_MAR = 31,
+               NSC_MONTH_DAYS_APR = 30,
+               NSC_MONTH_DAYS_MAY = 31,
+               NSC_MONTH_DAYS_JUN = 30,
+               NSC_MONTH_DAYS_JUL = 31,
+               NSC_MONTH_DAYS_AUG = 31,
+               NSC_MONTH_DAYS_SEP = 30,
+               NSC_MONTH_DAYS_OCT = 31,
+               NSC_MONTH_DAYS_NOV = 30,
+               NSC_MONTH_DAYS_DEC = 31
+       };
+       enum {
+               NSC_MONTH_OFF_JAN = 0,
+               NSC_MONTH_OFF_FEB = NSC_MONTH_OFF_JAN + NSC_MONTH_DAYS_JAN,
+               NSC_MONTH_OFF_MAR = NSC_MONTH_OFF_FEB + NSC_MONTH_DAYS_FEB,
+               NSC_MONTH_OFF_APR = NSC_MONTH_OFF_MAR + NSC_MONTH_DAYS_MAR,
+               NSC_MONTH_OFF_MAY = NSC_MONTH_OFF_APR + NSC_MONTH_DAYS_APR,
+               NSC_MONTH_OFF_JUN = NSC_MONTH_OFF_MAY + NSC_MONTH_DAYS_MAY,
+               NSC_MONTH_OFF_JUL = NSC_MONTH_OFF_JUN + NSC_MONTH_DAYS_JUN,
+               NSC_MONTH_OFF_AUG = NSC_MONTH_OFF_JUL + NSC_MONTH_DAYS_JUL,
+               NSC_MONTH_OFF_SEP = NSC_MONTH_OFF_AUG + NSC_MONTH_DAYS_AUG,
+               NSC_MONTH_OFF_OCT = NSC_MONTH_OFF_SEP + NSC_MONTH_DAYS_SEP,
+               NSC_MONTH_OFF_NOV = NSC_MONTH_OFF_OCT + NSC_MONTH_DAYS_OCT,
+               NSC_MONTH_OFF_DEC = NSC_MONTH_OFF_NOV + NSC_MONTH_DAYS_NOV
+       };
+       static const uint16_t month_offsets[NSC_TIME_MONTH__COUNT] = {
+               [NSC_TIME_MONTH_JAN] = NSC_MONTH_OFF_JAN,
+               [NSC_TIME_MONTH_FEB] = NSC_MONTH_OFF_FEB,
+               [NSC_TIME_MONTH_MAR] = NSC_MONTH_OFF_MAR,
+               [NSC_TIME_MONTH_APR] = NSC_MONTH_OFF_APR,
+               [NSC_TIME_MONTH_MAY] = NSC_MONTH_OFF_MAY,
+               [NSC_TIME_MONTH_JUN] = NSC_MONTH_OFF_JUN,
+               [NSC_TIME_MONTH_JUL] = NSC_MONTH_OFF_JUL,
+               [NSC_TIME_MONTH_AUG] = NSC_MONTH_OFF_AUG,
+               [NSC_TIME_MONTH_SEP] = NSC_MONTH_OFF_SEP,
+               [NSC_TIME_MONTH_OCT] = NSC_MONTH_OFF_OCT,
+               [NSC_TIME_MONTH_NOV] = NSC_MONTH_OFF_NOV,
+               [NSC_TIME_MONTH_DEC] = NSC_MONTH_OFF_DEC
+       };
+       int year_days = (ctx->years - 1970) * 365;
+       int month_days = month_offsets[ctx->months];
+       int year = (ctx->months < NSC_TIME_MONTH_FEB) ?
+                       ctx->years - 1 : ctx->years;
+       int leap_days = time__get_leap_days(year) - time__get_leap_days(1969);
+       int total_days = year_days + month_days + ctx->days + leap_days;
+
+       int mins = (int)ctx->mins + (int)ctx->timezone_offset_mins;
+
+       *time = (((((time_t)(total_days)) * 24) +
+                       ctx->hours) * 60 +
+                       mins) * 60 +
+                       ctx->secs;
+       return NSERROR_OK;
+}
+
+
+/**
+ * Parse a date string to a `time_t`.
+ *
+ * \param[in]  str   String to parse.
+ * \param[out] time  Returns the number of seconds since 1 Jan 1970 00:00 UTC.
+ * \return `NSERROR_OK` on success, else
+ *         `NSERROR_INVALID` if the string parsing failed,
+ *         appropriate error otherwise.
+ */
+static nserror time__get_date(const char *str, time_t *time)
+{
+       enum nsc_date_component_flags flags = NSC_COMPONENT_FLAGS_NONE;
+       struct nsc_date_parse_ctx ctx = {
+               .state  = PARSE_STATE_NONE,
+               .secs   = 0,
+               .mins   = 0,
+               .hours  = 0,
+               .days   = 0,
+               .months = 0,
+               .years  = 0,
+               .timezone_offset_mins = 0
+       };
+
+       if (str == NULL || *str == '\0' || time == NULL) {
+               return NSERROR_BAD_PARAMETER;
+       }
+
+       /* Parse */
+       while (*str != '\0' &&
+                       !flags_chk_all(flags, NSC_COMPONENT_FLAGS__HAVE_ALL)) {
+
+               if (isspace(*str)) {
+                       str++;
+
+               } else if (is_alpha(*str)) {
+                       size_t len = count_alpha(str + 1) + 1;
+
+                       if (!time__parse_weekday(str, &flags, len) &&
+                           !time__parse_month(str, &flags, &ctx) &&
+                           !time__parse_timezone(str, &flags, &ctx)) {
+                               return NSERROR_INVALID;
+                       }
+
+                       str += len;
+
+               } else if (is_digit(*str)) {
+                       size_t len = count_digit(str + 1) + 1;
+
+                       if (!time__parse_hh_mm_ss(str, &flags, &ctx, &len) &&
+                           !time__parse_number(str, &flags, &ctx, len)) {
+                               return NSERROR_INVALID;
+                       }
+
+                       str += len;
+
+               } else if (*str == '+') {
+                       ctx.state = PARSE_STATE_HAD_PLUS;
+                       str++;
+                       continue;
+
+               } else if (*str == '-') {
+                       ctx.state = PARSE_STATE_HAD_MINUS;
+                       str++;
+                       continue;
+
+               } else {
+                       str++;
+               }
+
+               ctx.state = PARSE_STATE_NONE;
+       }
+
+       /* The initial values of 0 are used if hours, mins, secs not found */
+       flags |= NSC_COMPONENT_FLAGS__HAVE_HHMMSS;
+
+       /* Validate */
+       if (!flags_chk_all(flags, NSC_COMPONENT_FLAGS__HAVE_ALL)) {
+               return NSERROR_INVALID;
+       }
+       if (ctx.secs > 60 || ctx.mins > 59 || ctx.hours > 23 ||
+                       ctx.days > 31 || ctx.months > 11) {
+               return NSERROR_INVALID;
+       }
+
+       /* Convert */
+       return time__ctx_to_time_t(&ctx, flags, time);
+}
+
+/* exported function documented in utils/time.h */
+nserror nsc_strntimet(const char *str, size_t size, time_t *timep)
+{
+       return time__get_date(str, timep);
+}
+
+# else
+
 /* exported function documented in utils/time.h */
 nserror nsc_strntimet(const char *str, size_t size, time_t *timep)
 {
@@ -196,3 +1021,5 @@ nserror nsc_strntimet(const char *str, size_t size, time_t 
*timep)
 
        return NSERROR_OK;
 }
+
+#endif


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=624c7ae0aa14eba8e36f3d1bf2edf0d691115de9
commit 624c7ae0aa14eba8e36f3d1bf2edf0d691115de9
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Utils: Add a set of string parsing helpers.
    
    These are not affected by the current locale.

diff --git a/utils/str-parse.h b/utils/str-parse.h
new file mode 100644
index 0000000..f4efa12
--- /dev/null
+++ b/utils/str-parse.h
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2014 Vincent Sanders <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file utils/str-parse.h
+ * \brief Helpers for string parsing.
+ *
+ * These helpers for string pasrsing will have the correct effect for parsing
+ * English language text (as used by most web specs), regradless of system
+ * locale.
+ */
+
+#ifndef _NETSURF_UTILS_STR_PARSE_H_
+#define _NETSURF_UTILS_STR_PARSE_H_
+
+#include <stdlib.h>
+
+/**
+ * Test whether a character is lower-case alphabetical.
+ *
+ * \param[in] c  Character to test.
+ * \return true iff `c` is lower-case alphabetical, else false.
+ */
+static inline bool is_alpha_lower(char c)
+{
+       return (c >= 'a' && c <= 'z');
+}
+
+/**
+ * Test whether a character is upper-case alphabetical.
+ *
+ * \param[in] c  Character to test.
+ * \return true iff `c` is upper-case alphabetical, else false.
+ */
+static inline bool is_alpha_upper(char c)
+{
+       return (c >= 'A' && c <= 'Z');
+}
+
+/**
+ * Test whether a character is alphabetical (upper or lower case).
+ *
+ * \param[in] c  Character to test.
+ * \return true iff `c` is alphabetical, else false.
+ */
+static inline bool is_alpha(char c)
+{
+       return (c >= 'A' && c <= 'Z');
+}
+
+/**
+ * Test whether a character is a decimal digit.
+ *
+ * \param[in] c  Character to test.
+ * \return true iff `c` is a decimal digit, else false.
+ */
+static inline bool is_digit(char c)
+{
+       return (c >= '0' && c <= '9');
+}
+
+/**
+ * Convert an upper case character to lower case.
+ *
+ * If the given character is not upper case alphabetical, it is returned
+ * unchanged.
+ *
+ * \param[in] c  Character to convert.
+ * \return lower case conversion of `c` else `c`.
+ */
+static inline char to_lower(char c)
+{
+       return (is_alpha_upper(c)) ? (c + 'a' - 'A') : c;
+}
+
+/**
+ * Convert a lower case character to upper case.
+ *
+ * If the given character is not lower case alphabetical, it is returned
+ * unchanged.
+ *
+ * \param[in] c  Character to convert.
+ * \return upper case conversion of `c` else `c`.
+ */
+static inline char to_upper(char c)
+{
+       return (is_alpha_lower(c)) ? (c + 'A' - 'a') : c;
+}
+
+/**
+ * Count consecutive lower case alphabetical characters in string.
+ *
+ * \param[in] str  String to count characters in.
+ * \return number of consecutive lower case characters at start of `str`.
+ */
+static inline size_t count_alpha_lower(const char *str)
+{
+       size_t count = 0;
+       while (is_alpha_lower(*(str++))) {
+               count++;
+       }
+       return count;
+}
+
+/**
+ * Count consecutive upper case alphabetical characters in string.
+ *
+ * \param[in] str  String to count characters in.
+ * \return number of consecutive upper case characters at start of `str`.
+ */
+static inline size_t count_alpha_upper(const char *str)
+{
+       size_t count = 0;
+       while (is_alpha_upper(*(str++))) {
+               count++;
+       }
+       return count;
+}
+
+/**
+ * Count consecutive alphabetical characters in string (upper or lower case).
+ *
+ * \param[in] str  String to count characters in.
+ * \return number of consecutive alphabetical characters at start of `str`.
+ */
+static inline size_t count_alpha(const char *str)
+{
+       size_t count = 0;
+       while (is_alpha(*(str++))) {
+               count++;
+       }
+       return count;
+}
+
+/**
+ * Count consecutive decial digit characters in string.
+ *
+ * \param[in] str  String to count characters in.
+ * \return number of consecutive decimal digit characters at start of `str`.
+ */
+static inline size_t count_digit(const char *str)
+{
+       size_t count = 0;
+       while (is_digit(*(str++))) {
+               count++;
+       }
+       return count;
+}
+
+/**
+ * Count consecutive characters either decial digit or colon in string.
+ *
+ * \param[in] str  String to count characters in.
+ * \return number of consecutive decimal or ':' characters at start of `str`.
+ */
+static inline size_t count_digit_or_colon(const char *str)
+{
+       size_t count = 0;
+       while (is_digit(*str) || *str == ':') {
+               count++;
+               str++;
+       }
+       return count;
+}
+
+/**
+ * Test for string equality (case insensitive).
+ *
+ * \param[in] s1  First string to compare.
+ * \param[in] s2  Second string to compare.
+ * \return true iff strings are equivelant, else false.
+ */
+static inline bool strings_equal_caseless(
+               const char *s1, const char *s2)
+{
+       while (*s1 != '\0') {
+               if (to_lower(*(s1++)) != to_lower(*(s2++))) {
+                       return false;
+               }
+       }
+       return true;
+}
+
+/**
+ * Test for string equality (case sensitive).
+ *
+ * \param[in] s1  First string to compare.
+ * \param[in] s2  Second string to compare.
+ * \return true iff strings are equal, else false.
+ */
+static inline bool strings_equal(
+               const char *s1, const char *s2)
+{
+       while (*s1 != '\0') {
+               if (*(s1++) != *(s2++)) {
+                       return false;
+               }
+       }
+       return true;
+}
+
+/**
+ * Parse an int out of a string.
+ *
+ * \param[in]  str  String to parse integer out of.
+ * \param[out] res  Returns parsed integer.
+ * \return The number of characters consumed in `str`.
+ *         Returning 0 indicates failure to parse an integer out of the string.
+ */
+static inline size_t string_to_int(const char *str, int *res)
+{
+       char *end = NULL;
+       long long temp = strtoll(str, &end, 10);
+
+       if (end == str || errno == ERANGE ||
+                       temp < INT_MIN || temp > INT_MAX) {
+               return 0;
+       }
+
+       *res = temp;
+       return end - str;
+}
+
+#endif


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=756f9727c67cc9fe26c865e4632ab1247c199d93
commit 756f9727c67cc9fe26c865e4632ab1247c199d93
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Time: Expose arrays of weekday and month names.

diff --git a/utils/time.c b/utils/time.c
index cf8acc0..dd67d8a 100644
--- a/utils/time.c
+++ b/utils/time.c
@@ -35,20 +35,86 @@
 #include "utils/time.h"
 
 
+
+/**
+ * Weekdays
+ *
+ * Must be calender order.
+ */
+enum nsc_time_weekdays {
+       NSC_TIME_WEEKDAY_SUN,
+       NSC_TIME_WEEKDAY_MON,
+       NSC_TIME_WEEKDAY_TUE,
+       NSC_TIME_WEEKDAY_WED,
+       NSC_TIME_WEEKDAY_THU,
+       NSC_TIME_WEEKDAY_FRI,
+       NSC_TIME_WEEKDAY_SAT,
+       NSC_TIME_WEEKDAY__COUNT
+};
+/**
+ * Months
+ *
+ * Must be calender order.
+ */
+enum nsc_time_months {
+       NSC_TIME_MONTH_JAN,
+       NSC_TIME_MONTH_FEB,
+       NSC_TIME_MONTH_MAR,
+       NSC_TIME_MONTH_APR,
+       NSC_TIME_MONTH_MAY,
+       NSC_TIME_MONTH_JUN,
+       NSC_TIME_MONTH_JUL,
+       NSC_TIME_MONTH_AUG,
+       NSC_TIME_MONTH_SEP,
+       NSC_TIME_MONTH_OCT,
+       NSC_TIME_MONTH_NOV,
+       NSC_TIME_MONTH_DEC,
+       NSC_TIME_MONTH__COUNT,
+};
+
+
+/**
+ * Array of short weekday names.
+ */
+const char * const weekdays_short[NSC_TIME_WEEKDAY__COUNT] = {
+       [NSC_TIME_WEEKDAY_SUN] = "Sun",
+       [NSC_TIME_WEEKDAY_MON] = "Mon",
+       [NSC_TIME_WEEKDAY_TUE] = "Tue",
+       [NSC_TIME_WEEKDAY_WED] = "Wed",
+       [NSC_TIME_WEEKDAY_THU] = "Thu",
+       [NSC_TIME_WEEKDAY_FRI] = "Fri",
+       [NSC_TIME_WEEKDAY_SAT] = "Sat"
+};
+/**
+ * Array of month names.
+ */
+const char * const months[NSC_TIME_MONTH__COUNT] = {
+       [NSC_TIME_MONTH_JAN] = "Jan",
+       [NSC_TIME_MONTH_FEB] = "Feb",
+       [NSC_TIME_MONTH_MAR] = "Mar",
+       [NSC_TIME_MONTH_APR] = "Apr",
+       [NSC_TIME_MONTH_MAY] = "May",
+       [NSC_TIME_MONTH_JUN] = "Jun",
+       [NSC_TIME_MONTH_JUL] = "Jul",
+       [NSC_TIME_MONTH_AUG] = "Aug",
+       [NSC_TIME_MONTH_SEP] = "Sep",
+       [NSC_TIME_MONTH_OCT] = "Oct",
+       [NSC_TIME_MONTH_NOV] = "Nov",
+       [NSC_TIME_MONTH_DEC] = "Dec"
+};
+
+
 /* exported interface documented in utils/time.h */
 const char *rfc1123_date(time_t t)
 {
        static char ret[30];
 
        struct tm *tm = gmtime(&t);
-       const char *days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 
},
-               *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 
        snprintf(ret, sizeof ret, "%s, %02d %s %d %02d:%02d:%02d GMT",
-                       days[tm->tm_wday], tm->tm_mday, months[tm->tm_mon],
-                       tm->tm_year + 1900, tm->tm_hour, tm->tm_min,
-                       tm->tm_sec);
+                       weekdays_short[tm->tm_wday], tm->tm_mday,
+                       months[tm->tm_mon], tm->tm_year + 1900,
+                       tm->tm_hour, tm->tm_min, tm->tm_sec);
 
        return ret;
 }


-----------------------------------------------------------------------


-- 
NetSurf Browser

_______________________________________________
netsurf-commits mailing list
[email protected]
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org

Reply via email to