File Coverage

tstr_parse.c
Criterion Covered Total %
statement 40 44 90.9
branch 50 60 83.3
condition n/a
subroutine n/a
pod n/a
total 90 104 86.5


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5              
6             #include "tstr_parsed.h"
7             #include "tstr_format.h"
8             #include "tstr_calendar.h"
9             #include "tstr_sv.h"
10             #include "tstr_regexp.h"
11             #include "tstr_cparse.h"
12             #include "tstr_parse_result.h"
13             #include "tstr_carp.h"
14              
15             #define DEFAULT_PIVOT_YEAR 1950
16              
17 825           static inline bool valid_hms(int h, int m, int s) {
18 825 100         return h >= 0 && h <= 23
19 823 50         && m >= 0 && m <= 59
    100          
20 1650 50         && s >= 0 && (s <= 59 || (s == 60 && h == 23 && m == 59));
    50          
    100          
    100          
    50          
    50          
21             }
22              
23 949           static tstr_parse_result_t validate_parsed(const tstr_parsed_t *p) {
24 949 100         int m = (p->flags & TSTR_PARSED_HAS_MONTH) ? p->month : 1;
25 949 100         int d = (p->flags & TSTR_PARSED_HAS_DAY) ? p->day : 1;
26              
27 949 100         if (!tstr_calendar_valid_ymd(p->year, m, d))
28 2           return TSTR_PARSE_ERR_DATE_RANGE;
29              
30 947 100         if ((p->flags & TSTR_PARSED_HAS_DAY_NAME) &&
31 157 50         tstr_calendar_ymd_to_dow(p->year, p->month, p->day) != p->day_name)
32 0           return TSTR_PARSE_ERR_DAY_NAME_MISMATCH;
33              
34 947 100         if (p->flags & TSTR_PARSED_HAS_MERIDIEM) {
35 22 50         if (p->hour < 1 || p->hour > 12)
    50          
36 0           return TSTR_PARSE_ERR_HOUR_RANGE;
37             }
38              
39 947 100         if (p->flags & TSTR_PARSED_HAS_TIME) {
40 825           int h = p->hour;
41 825 100         if (p->flags & TSTR_PARSED_HAS_MERIDIEM)
42 22           h = p->hour % 12 + p->meridiem;
43 825 100         if (!valid_hms(h, p->minute, p->second))
44 6           return TSTR_PARSE_ERR_TIME_RANGE;
45             }
46              
47 941           return TSTR_PARSE_OK;
48             }
49              
50 956           void tstr_parse(pTHX_ SV *input, tstr_format_t fmt, int pivot_year,
51             REGEXP **regexps, tstr_sv_keys_t *keys, tstr_parsed_t *p) {
52             char *s;
53             STRLEN slen;
54             tstr_parse_result_t rc;
55              
56 956           s = SvPV(input, slen);
57              
58 956           rc = tstr_cparse_dispatch(s, slen, fmt, p);
59              
60 956 100         if (rc == TSTR_PARSE_NOMATCH)
61 2           tstr_croakf("Unable to parse: string does not match the %s format",
62             tstr_format_name(fmt));
63              
64 954 100         if (rc == TSTR_PARSE_NOPARSER) {
65 699           REGEXP *rx = regexps[fmt];
66              
67 699 50         if (!rx)
68 0           croak("panic: no regexp for format '%s'", tstr_format_name(fmt));
69              
70 699 50         if (!pregexec(rx, s, s + slen, s, 0, input, 1))
71 0           tstr_croakf("Unable to parse: string does not match the %s format",
72             tstr_format_name(fmt));
73              
74 699           rc = tstr_regexp_extract(aTHX_ rx, p, keys);
75             }
76              
77 954 100         if (rc != TSTR_PARSE_OK)
78 5           tstr_croakf("Unable to parse: %s", tstr_parse_error_message(rc));
79              
80 949 100         if (p->flags & TSTR_PARSED_HAS_YEAR2)
81 41 100         p->year = tstr_calendar_resolve_century(
82             p->year, pivot_year >= 0 ? pivot_year : DEFAULT_PIVOT_YEAR);
83              
84 949 100         if (fmt == TSTR_FORMAT_RFC2616 && !(p->flags & TSTR_PARSED_HAS_TZ_UTC))
    100          
85 2           tstr_parsed_set_tz_utc(p, "GMT", 3);
86              
87 949           rc = validate_parsed(p);
88 949 100         if (rc != TSTR_PARSE_OK)
89 8           tstr_croakf("Unable to parse: %s", tstr_parse_error_message(rc));
90 941           }