/* 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) { int lpct = 0; errno = 0; /* For as long as our scanner pointer points to a colon *AND* we've not looped before, then keep looping. (two iterations max) */ while ((*pz == ':') && (lpct++ <= 1)) { unsigned long v = str_const_to_ul (pz+1, &pz, 10); if (errno != 0) return BAD_TIME; start = scale_n_add (v, start, 60); if (errno != 0) return BAD_TIME; } /* allow for trailing spaces */ while (isspace ((unsigned char)*pz)) pz++; if (*pz != NUL) { errno = EINVAL; return BAD_TIME; } return start; }
/* * Parse the year/months/days of a time period */ static time_t parse_period (cch_t * in_pz) { char * pT; char * ps; char * pz = strdup (in_pz); void * fptr = pz; time_t res = 0; if (pz == NULL) { errno = ENOMEM; return BAD_TIME; } pT = strchr (pz, 'T'); if (pT != NULL) { *(pT++) = NUL; pz = trim (pz); pT = trim (pT); } /* * Scan for a hyphen */ ps = strchr (pz, '-'); if (ps != NULL) { res = parse_year_month_day (pz, ps); } /* * Try for a 'Y', 'M' or 'D' suffix */ else if (ps = strpbrk (pz, "YMWD"), ps == NULL) { /* Its a YYYYMMDD format: */ res = parse_yearmonthday (pz); } else res = parse_YMWD (pz); if ((errno == 0) && (pT != NULL)) { time_t val = parse_time (pT); res = scale_n_add (res, val, 1); } free (fptr); return res; }
static time_t parse_scaled_value (time_t base, cch_t ** ppz, cch_t * endp, int scale) { cch_t * pz = *ppz; time_t val; if (base == BAD_TIME) return base; errno = 0; val = str_const_to_ul (pz, &pz, 10); if (errno != 0) return BAD_TIME; while (isspace ((unsigned char)*pz)) pz++; if (pz != endp) { errno = EINVAL; return BAD_TIME; } *ppz = pz; return scale_n_add (base, val, scale); }
static time_t parse_non_iso8601 (cch_t * pz) { whats_done_t whatd_we_do = NOTHING_IS_DONE; time_t res = 0; do { time_t val; errno = 0; val = str_const_to_l (pz, &pz, 10); if (errno != 0) goto bad_time; /* IF we find a colon, then we're going to have a seconds value. We will not loop here any more. We cannot already have parsed a minute value and if we've parsed an hour value, then the result value has to be less than an hour. */ if (*pz == ':') { if (whatd_we_do >= MINUTE_IS_DONE) break; val = parse_hr_min_sec (val, pz); if ((whatd_we_do == HOUR_IS_DONE) && (val >= SEC_PER_HR)) break; return scale_n_add (res, val, 1); } { unsigned int mult; /* Skip over white space following the number we just parsed. */ while (isspace ((unsigned char)*pz)) pz++; switch (*pz) { default: goto bad_time; case NUL: return scale_n_add (res, val, 1); case 'y': case 'Y': if (whatd_we_do >= YEAR_IS_DONE) goto bad_time; mult = SEC_PER_YEAR; whatd_we_do = YEAR_IS_DONE; break; case 'M': if (whatd_we_do >= MONTH_IS_DONE) goto bad_time; mult = SEC_PER_MONTH; whatd_we_do = MONTH_IS_DONE; break; case 'W': if (whatd_we_do >= WEEK_IS_DONE) goto bad_time; mult = SEC_PER_WEEK; whatd_we_do = WEEK_IS_DONE; break; case 'd': case 'D': if (whatd_we_do >= DAY_IS_DONE) goto bad_time; mult = SEC_PER_DAY; whatd_we_do = DAY_IS_DONE; break; case 'h': if (whatd_we_do >= HOUR_IS_DONE) goto bad_time; mult = SEC_PER_HR; whatd_we_do = HOUR_IS_DONE; break; case 'm': if (whatd_we_do >= MINUTE_IS_DONE) goto bad_time; mult = SEC_PER_MIN; whatd_we_do = MINUTE_IS_DONE; break; case 's': mult = 1; whatd_we_do = SECOND_IS_DONE; break; } res = scale_n_add (res, val, mult); pz++; while (isspace ((unsigned char)*pz)) pz++; if (*pz == NUL) return res; if (! isdigit ((unsigned char)*pz)) break; } } while (whatd_we_do < SECOND_IS_DONE); bad_time: errno = EINVAL; return BAD_TIME; }