X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fparse-duration.c;h=0a8c4ada8408e187952e636b4441409cd36f4669;hb=fac94349f25305566277d15b965fa8f4efe66613;hp=4c283495b6cb8683ce5b2091b71b1b909558e6a3;hpb=29544c11e365f6c1dc6455ead660f1799e9d326e;p=gnulib.git diff --git a/lib/parse-duration.c b/lib/parse-duration.c index 4c283495b..0a8c4ada8 100644 --- a/lib/parse-duration.c +++ b/lib/parse-duration.c @@ -1,5 +1,5 @@ /* Parse a time duration and return a seconds count - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008-2011 Free Software Foundation, Inc. Written by Bruce Korb , 2008. This program is free software: you can redistribute it and/or modify @@ -17,19 +17,15 @@ #include +/* Specification. */ +#include "parse-duration.h" + #include #include #include #include #include #include -#include "xalloc.h" - -#include "parse-duration.h" - -#ifndef _ -#define _(_s) _s -#endif #ifndef NUL #define NUL '\0' @@ -57,18 +53,23 @@ typedef enum { #define TIME_MAX 0x7FFFFFFF +/* Wrapper around strtoul that does not require a cast. */ static unsigned long inline str_const_to_ul (cch_t * str, cch_t ** ppz, int base) { return strtoul (str, (char **)ppz, base); } +/* Wrapper around strtol that does not require a cast. */ static long inline str_const_to_l (cch_t * str, cch_t ** ppz, int base) { return strtol (str, (char **)ppz, base); } +/* Returns BASE + VAL * SCALE, interpreting BASE = BAD_TIME + with errno set as an error situation, and returning BAD_TIME + with errno set in an error situation. */ static time_t inline scale_n_add (time_t base, time_t val, int scale) { @@ -95,6 +96,7 @@ scale_n_add (time_t base, time_t val, int scale) return base + val; } +/* After a number HH has been parsed, parse subsequent :MM or :MM:SS. */ static time_t parse_hr_min_sec (time_t start, cch_t * pz) { @@ -118,7 +120,8 @@ parse_hr_min_sec (time_t start, cch_t * pz) } /* allow for trailing spaces */ - while (isspace ((unsigned char)*pz)) pz++; + while (isspace ((unsigned char)*pz)) + pz++; if (*pz != NUL) { errno = EINVAL; @@ -128,6 +131,9 @@ parse_hr_min_sec (time_t start, cch_t * pz) return start; } +/* Parses a value and returns BASE + value * SCALE, interpreting + BASE = BAD_TIME with errno set as an error situation, and returning + BAD_TIME with errno set in an error situation. */ static time_t parse_scaled_value (time_t base, cch_t ** ppz, cch_t * endp, int scale) { @@ -141,17 +147,20 @@ parse_scaled_value (time_t base, cch_t ** ppz, cch_t * endp, int scale) val = str_const_to_ul (pz, &pz, 10); if (errno != 0) return BAD_TIME; - while (isspace ((unsigned char)*pz)) pz++; + while (isspace ((unsigned char)*pz)) + pz++; if (pz != endp) { errno = EINVAL; return BAD_TIME; } - *ppz = pz; + *ppz = pz; return scale_n_add (base, val, scale); } +/* Parses the syntax YEAR-MONTH-DAY. + PS points into the string, after "YEAR", before "-MONTH-DAY". */ static time_t parse_year_month_day (cch_t * pz, cch_t * ps) { @@ -159,7 +168,8 @@ parse_year_month_day (cch_t * pz, cch_t * ps) res = parse_scaled_value (0, &pz, ps, SEC_PER_YEAR); - ps = strchr (++pz, '-'); + pz++; /* over the first '-' */ + ps = strchr (pz, '-'); if (ps == NULL) { errno = EINVAL; @@ -167,11 +177,12 @@ parse_year_month_day (cch_t * pz, cch_t * ps) } res = parse_scaled_value (res, &pz, ps, SEC_PER_MONTH); - pz++; + pz++; /* over the second '-' */ ps = pz + strlen (pz); return parse_scaled_value (res, &pz, ps, SEC_PER_DAY); } +/* Parses the syntax YYYYMMDD. */ static time_t parse_yearmonthday (cch_t * in_pz) { @@ -201,6 +212,7 @@ parse_yearmonthday (cch_t * in_pz) return parse_scaled_value (res, &pz, buf + 2, SEC_PER_DAY); } +/* Parses the syntax yy Y mm M ww W dd D. */ static time_t parse_YMWD (cch_t * pz) { @@ -233,7 +245,8 @@ parse_YMWD (cch_t * pz) pz++; } - while (isspace ((unsigned char)*pz)) pz++; + while (isspace ((unsigned char)*pz)) + pz++; if (*pz != NUL) { errno = EINVAL; @@ -243,6 +256,8 @@ parse_YMWD (cch_t * pz) return res; } +/* Parses the syntax HH:MM:SS. + PS points into the string, after "HH", before ":MM:SS". */ static time_t parse_hour_minute_second (cch_t * pz, cch_t * ps) { @@ -250,7 +265,8 @@ parse_hour_minute_second (cch_t * pz, cch_t * ps) res = parse_scaled_value (0, &pz, ps, SEC_PER_HR); - ps = strchr (++pz, ':'); + pz++; + ps = strchr (pz, ':'); if (ps == NULL) { errno = EINVAL; @@ -264,6 +280,7 @@ parse_hour_minute_second (cch_t * pz, cch_t * ps) return parse_scaled_value (res, &pz, ps, 1); } +/* Parses the syntax HHMMSS. */ static time_t parse_hourminutesecond (cch_t * in_pz) { @@ -293,6 +310,7 @@ parse_hourminutesecond (cch_t * in_pz) return parse_scaled_value (res, &pz, buf + 2, 1); } +/* Parses the syntax hh H mm M ss S. */ static time_t parse_HMS (cch_t * pz) { @@ -318,7 +336,8 @@ parse_HMS (cch_t * pz) pz++; } - while (isspace ((unsigned char)*pz)) pz++; + while (isspace ((unsigned char)*pz)) + pz++; if (*pz != NUL) { errno = EINVAL; @@ -328,6 +347,7 @@ parse_HMS (cch_t * pz) return res; } +/* Parses a time (hours, minutes, seconds) specification in either syntax. */ static time_t parse_time (cch_t * pz) { @@ -359,16 +379,20 @@ parse_time (cch_t * pz) return res; } +/* Returns a substring of the given string, with spaces at the beginning and at + the end destructively removed, per SNOBOL. */ static char * -trim(char * pz) +trim (char * pz) { /* trim leading white space */ - while (isspace ((unsigned char)*pz)) pz++; + while (isspace ((unsigned char)*pz)) + pz++; /* trim trailing white space */ { char * pe = pz + strlen (pz); - while ((pe > pz) && isspace ((unsigned char)pe[-1])) pe--; + while ((pe > pz) && isspace ((unsigned char)pe[-1])) + pe--; *pe = NUL; } @@ -381,13 +405,20 @@ trim(char * pz) static time_t parse_period (cch_t * in_pz) { - char * pz = xstrdup (in_pz); - char * pT = strchr (pz, 'T'); + char * pT; char * ps; + char * pz = strdup (in_pz); void * fptr = pz; time_t res = 0; - if (pT != NUL) + if (pz == NULL) + { + errno = ENOMEM; + return BAD_TIME; + } + + pT = strchr (pz, 'T'); + if (pT != NULL) { *(pT++) = NUL; pz = trim (pz); @@ -427,7 +458,7 @@ parse_period (cch_t * in_pz) } static time_t -parse_non_iso8601(cch_t * pz) +parse_non_iso8601 (cch_t * pz) { whats_done_t whatd_we_do = NOTHING_IS_DONE; @@ -462,7 +493,8 @@ parse_non_iso8601(cch_t * pz) unsigned int mult; /* Skip over white space following the number we just parsed. */ - while (isspace ((unsigned char)*pz)) pz++; + while (isspace ((unsigned char)*pz)) + pz++; switch (*pz) { @@ -520,7 +552,9 @@ parse_non_iso8601(cch_t * pz) res = scale_n_add (res, val, mult); - while (isspace ((unsigned char)*++pz)) ; + pz++; + while (isspace ((unsigned char)*pz)) + pz++; if (*pz == NUL) return res; @@ -538,40 +572,24 @@ parse_non_iso8601(cch_t * pz) time_t parse_duration (char const * pz) { - time_t res = 0; + while (isspace ((unsigned char)*pz)) + pz++; - while (isspace ((unsigned char)*pz)) pz++; - - do { - if (*pz == 'P') - { - res = parse_period (pz + 1); - if ((errno != 0) || (res == BAD_TIME)) - break; - return res; - } - - if (*pz == 'T') - { - res = parse_time (pz + 1); - if ((errno != 0) || (res == BAD_TIME)) - break; - return res; - } - - if (! isdigit ((unsigned char)*pz)) - break; + switch (*pz) + { + case 'P': + return parse_period (pz + 1); - res = parse_non_iso8601 (pz); - if ((errno == 0) && (res != BAD_TIME)) - return res; + case 'T': + return parse_time (pz + 1); - } while (0); + default: + if (isdigit ((unsigned char)*pz)) + return parse_non_iso8601 (pz); - fprintf (stderr, _("Invalid time duration: %s\n"), pz); - if (errno == 0) - errno = EINVAL; - return BAD_TIME; + errno = EINVAL; + return BAD_TIME; + } } /*