File Coverage

tstr_token_parse.c
Criterion Covered Total %
statement 224 239 93.7
branch 72 96 75.0
condition n/a
subroutine n/a
pod n/a
total 296 335 88.3


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include
4             #include
5              
6             #include "tstr_packed_alpha.h"
7             #include "tstr_packed_alnum.h"
8              
9             const int kNotFound = INT_MAX;
10              
11 1025           static inline int lookup_day_from_packed_alnum(uint64_t packed) {
12 1025           switch (packed) {
13 130           case TSTR_PACKED_ALNUM1('1'):
14             case TSTR_PACKED_ALNUM2('0','1'):
15             case TSTR_PACKED_ALNUM3('1','s','t'):
16 130           return 1;
17 5           case TSTR_PACKED_ALNUM1('2'):
18             case TSTR_PACKED_ALNUM2('0','2'):
19             case TSTR_PACKED_ALNUM3('2','n','d'):
20 5           return 2;
21 5           case TSTR_PACKED_ALNUM1('3'):
22             case TSTR_PACKED_ALNUM2('0','3'):
23             case TSTR_PACKED_ALNUM3('3','r','d'):
24 5           return 3;
25 3           case TSTR_PACKED_ALNUM1('4'):
26             case TSTR_PACKED_ALNUM2('0','4'):
27             case TSTR_PACKED_ALNUM3('4','t','h'):
28 3           return 4;
29 3           case TSTR_PACKED_ALNUM1('5'):
30             case TSTR_PACKED_ALNUM2('0','5'):
31             case TSTR_PACKED_ALNUM3('5','t','h'):
32 3           return 5;
33 16           case TSTR_PACKED_ALNUM1('6'):
34             case TSTR_PACKED_ALNUM2('0','6'):
35             case TSTR_PACKED_ALNUM3('6','t','h'):
36 16           return 6;
37 3           case TSTR_PACKED_ALNUM1('7'):
38             case TSTR_PACKED_ALNUM2('0','7'):
39             case TSTR_PACKED_ALNUM3('7','t','h'):
40 3           return 7;
41 3           case TSTR_PACKED_ALNUM1('8'):
42             case TSTR_PACKED_ALNUM2('0','8'):
43             case TSTR_PACKED_ALNUM3('8','t','h'):
44 3           return 8;
45 3           case TSTR_PACKED_ALNUM1('9'):
46             case TSTR_PACKED_ALNUM2('0','9'):
47             case TSTR_PACKED_ALNUM3('9','t','h'):
48 3           return 9;
49 2           case TSTR_PACKED_ALNUM2('1','0'):
50             case TSTR_PACKED_ALNUM4('1','0','t','h'):
51 2           return 10;
52 2           case TSTR_PACKED_ALNUM2('1','1'):
53             case TSTR_PACKED_ALNUM4('1','1','t','h'):
54 2           return 11;
55 2           case TSTR_PACKED_ALNUM2('1','2'):
56             case TSTR_PACKED_ALNUM4('1','2','t','h'):
57 2           return 12;
58 2           case TSTR_PACKED_ALNUM2('1','3'):
59             case TSTR_PACKED_ALNUM4('1','3','t','h'):
60 2           return 13;
61 2           case TSTR_PACKED_ALNUM2('1','4'):
62             case TSTR_PACKED_ALNUM4('1','4','t','h'):
63 2           return 14;
64 2           case TSTR_PACKED_ALNUM2('1','5'):
65             case TSTR_PACKED_ALNUM4('1','5','t','h'):
66 2           return 15;
67 2           case TSTR_PACKED_ALNUM2('1','6'):
68             case TSTR_PACKED_ALNUM4('1','6','t','h'):
69 2           return 16;
70 2           case TSTR_PACKED_ALNUM2('1','7'):
71             case TSTR_PACKED_ALNUM4('1','7','t','h'):
72 2           return 17;
73 2           case TSTR_PACKED_ALNUM2('1','8'):
74             case TSTR_PACKED_ALNUM4('1','8','t','h'):
75 2           return 18;
76 2           case TSTR_PACKED_ALNUM2('1','9'):
77             case TSTR_PACKED_ALNUM4('1','9','t','h'):
78 2           return 19;
79 2           case TSTR_PACKED_ALNUM2('2','0'):
80             case TSTR_PACKED_ALNUM4('2','0','t','h'):
81 2           return 20;
82 3           case TSTR_PACKED_ALNUM2('2','1'):
83             case TSTR_PACKED_ALNUM4('2','1','s','t'):
84 3           return 21;
85 2           case TSTR_PACKED_ALNUM2('2','2'):
86             case TSTR_PACKED_ALNUM4('2','2','n','d'):
87 2           return 22;
88 2           case TSTR_PACKED_ALNUM2('2','3'):
89             case TSTR_PACKED_ALNUM4('2','3','r','d'):
90 2           return 23;
91 747           case TSTR_PACKED_ALNUM2('2','4'):
92             case TSTR_PACKED_ALNUM4('2','4','t','h'):
93 747           return 24;
94 3           case TSTR_PACKED_ALNUM2('2','5'):
95             case TSTR_PACKED_ALNUM4('2','5','t','h'):
96 3           return 25;
97 2           case TSTR_PACKED_ALNUM2('2','6'):
98             case TSTR_PACKED_ALNUM4('2','6','t','h'):
99 2           return 26;
100 3           case TSTR_PACKED_ALNUM2('2','7'):
101             case TSTR_PACKED_ALNUM4('2','7','t','h'):
102 3           return 27;
103 2           case TSTR_PACKED_ALNUM2('2','8'):
104             case TSTR_PACKED_ALNUM4('2','8','t','h'):
105 2           return 28;
106 8           case TSTR_PACKED_ALNUM2('2','9'):
107             case TSTR_PACKED_ALNUM4('2','9','t','h'):
108 8           return 29;
109 4           case TSTR_PACKED_ALNUM2('3','0'):
110             case TSTR_PACKED_ALNUM4('3','0','t','h'):
111 4           return 30;
112 51           case TSTR_PACKED_ALNUM2('3','1'):
113             case TSTR_PACKED_ALNUM4('3','1','s','t'):
114 51           return 31;
115 5           default:
116 5           return kNotFound;
117             }
118             }
119              
120 181           static inline int lookup_day_name_from_packed_alpha(uint64_t packed) {
121 181           switch (packed) {
122 123           case TSTR_PACKED_ALPHA3('M','o','n'):
123             case TSTR_PACKED_ALPHA6('M','o','n','d','a','y'):
124 123           return 1;
125 7           case TSTR_PACKED_ALPHA3('T','u','e'):
126             case TSTR_PACKED_ALPHA4('T','u','e','s'):
127             case TSTR_PACKED_ALPHA7('T','u','e','s','d','a','y'):
128 7           return 2;
129 4           case TSTR_PACKED_ALPHA3('W','e','d'):
130             case TSTR_PACKED_ALPHA9('W','e','d','n','e','s','d','a','y'):
131 4           return 3;
132 20           case TSTR_PACKED_ALPHA3('T','h','u'):
133             case TSTR_PACKED_ALPHA5('T','h','u','r','s'):
134             case TSTR_PACKED_ALPHA8('T','h','u','r','s','d','a','y'):
135 20           return 4;
136 8           case TSTR_PACKED_ALPHA3('F','r','i'):
137             case TSTR_PACKED_ALPHA6('F','r','i','d','a','y'):
138 8           return 5;
139 3           case TSTR_PACKED_ALPHA3('S','a','t'):
140             case TSTR_PACKED_ALPHA8('S','a','t','u','r','d','a','y'):
141 3           return 6;
142 13           case TSTR_PACKED_ALPHA3('S','u','n'):
143             case TSTR_PACKED_ALPHA6('S','u','n','d','a','y'):
144 13           return 7;
145 3           default:
146 3           return kNotFound;
147             }
148             }
149              
150 1023           static inline int lookup_month_from_packed_alnum(uint64_t packed) {
151 1023           switch (packed) {
152 140           case TSTR_PACKED_ALNUM1('1'):
153             case TSTR_PACKED_ALNUM2('0','1'):
154             case TSTR_PACKED_ALNUM1('I'):
155             case TSTR_PACKED_ALNUM3('J','a','n'):
156             case TSTR_PACKED_ALNUM7('J','a','n','u','a','r','y'):
157 140           return 1;
158 17           case TSTR_PACKED_ALNUM1('2'):
159             case TSTR_PACKED_ALNUM2('0','2'):
160             case TSTR_PACKED_ALNUM2('I','I'):
161             case TSTR_PACKED_ALNUM3('F','e','b'):
162             case TSTR_PACKED_ALNUM8('F','e','b','r','u','a','r','y'):
163 17           return 2;
164 9           case TSTR_PACKED_ALNUM1('3'):
165             case TSTR_PACKED_ALNUM2('0','3'):
166             case TSTR_PACKED_ALNUM3('I','I','I'):
167             case TSTR_PACKED_ALNUM3('M','a','r'):
168             case TSTR_PACKED_ALNUM5('M','a','r','c','h'):
169 9           return 3;
170 11           case TSTR_PACKED_ALNUM1('4'):
171             case TSTR_PACKED_ALNUM2('0','4'):
172             case TSTR_PACKED_ALNUM2('I','V'):
173             case TSTR_PACKED_ALNUM3('A','p','r'):
174             case TSTR_PACKED_ALNUM5('A','p','r','i','l'):
175 11           return 4;
176 8           case TSTR_PACKED_ALNUM1('5'):
177             case TSTR_PACKED_ALNUM2('0','5'):
178             case TSTR_PACKED_ALNUM1('V'):
179             case TSTR_PACKED_ALNUM3('M','a','y'):
180 8           return 5;
181 8           case TSTR_PACKED_ALNUM1('6'):
182             case TSTR_PACKED_ALNUM2('0','6'):
183             case TSTR_PACKED_ALNUM2('V','I'):
184             case TSTR_PACKED_ALNUM3('J','u','n'):
185             case TSTR_PACKED_ALNUM4('J','u','n','e'):
186 8           return 6;
187 8           case TSTR_PACKED_ALNUM1('7'):
188             case TSTR_PACKED_ALNUM2('0','7'):
189             case TSTR_PACKED_ALNUM3('V','I','I'):
190             case TSTR_PACKED_ALNUM3('J','u','l'):
191             case TSTR_PACKED_ALNUM4('J','u','l','y'):
192 8           return 7;
193 10           case TSTR_PACKED_ALNUM1('8'):
194             case TSTR_PACKED_ALNUM2('0','8'):
195             case TSTR_PACKED_ALNUM4('V','I','I','I'):
196             case TSTR_PACKED_ALNUM3('A','u','g'):
197             case TSTR_PACKED_ALNUM6('A','u','g','u','s','t'):
198 10           return 8;
199 12           case TSTR_PACKED_ALNUM1('9'):
200             case TSTR_PACKED_ALNUM2('0','9'):
201             case TSTR_PACKED_ALNUM2('I','X'):
202             case TSTR_PACKED_ALNUM3('S','e','p'):
203             case TSTR_PACKED_ALNUM4('S','e','p','t'):
204             case TSTR_PACKED_ALNUM9('S','e','p','t','e','m','b','e','r'):
205 12           return 9;
206 7           case TSTR_PACKED_ALNUM2('1','0'):
207             case TSTR_PACKED_ALNUM1('X'):
208             case TSTR_PACKED_ALNUM3('O','c','t'):
209             case TSTR_PACKED_ALNUM7('O','c','t','o','b','e','r'):
210 7           return 10;
211 20           case TSTR_PACKED_ALNUM2('1','1'):
212             case TSTR_PACKED_ALNUM2('X','I'):
213             case TSTR_PACKED_ALNUM3('N','o','v'):
214             case TSTR_PACKED_ALNUM8('N','o','v','e','m','b','e','r'):
215 20           return 11;
216 764           case TSTR_PACKED_ALNUM2('1','2'):
217             case TSTR_PACKED_ALNUM3('X','I','I'):
218             case TSTR_PACKED_ALNUM3('D','e','c'):
219             case TSTR_PACKED_ALNUM8('D','e','c','e','m','b','e','r'):
220 764           return 12;
221 9           default:
222 9           return kNotFound;
223             }
224             }
225              
226 1026           bool tstr_token_parse_day(const char* src, size_t len, int* day) {
227             uint64_t packed;
228             int value;
229 1026 100         if (!len || tstr_packed_alnum_encode(src, len, &packed) != len)
    50          
230 1           return false;
231 1025           value = lookup_day_from_packed_alnum(packed);
232 1025 100         if (value == kNotFound)
233 5           return false;
234 1020           *day = value;
235 1020           return true;
236             }
237              
238 182           bool tstr_token_parse_day_name(const char* src, size_t len, int* day) {
239             uint64_t packed;
240             int value;
241 182 100         if (!len || tstr_packed_alpha_encode(src, len, &packed) != len)
    50          
242 1           return false;
243 181           value = lookup_day_name_from_packed_alpha(packed);
244 181 100         if (value == kNotFound)
245 3           return false;
246 178           *day = value;
247 178           return true;
248             }
249              
250 1024           bool tstr_token_parse_month(const char* src, size_t len, int* month) {
251             uint64_t packed;
252             int value;
253 1024 100         if (!len || tstr_packed_alnum_encode(src, len, &packed) != len)
    50          
254 1           return false;
255 1023           value = lookup_month_from_packed_alnum(packed);
256 1023 100         if (value == kNotFound)
257 9           return false;
258 1014           *month = value;
259 1014           return true;
260             }
261              
262 36           bool tstr_token_parse_meridiem(const char* src, size_t len, int* merdiem) {
263             unsigned char a, m;
264              
265 36 100         if (len == 2) {
266 24           a = src[0];
267 24           m = src[1];
268 12 100         } else if (len == 4) {
269 9 100         if (src[1] != '.' || src[3] != '.')
    50          
270 1           return false;
271 8           a = src[0];
272 8           m = src[2];
273             } else {
274 3           return false;
275             }
276              
277 32 50         if ((m | 0x20) != 'm')
278 0           return false;
279              
280 32 100         if ((a | 0x20) == 'a') {
281 12           *merdiem = 0;
282 12           return true;
283             }
284 20 50         if ((a | 0x20) == 'p') {
285 20           *merdiem = 12;
286 20           return true;
287             }
288 0           return false;
289             }
290              
291 11600           static inline bool is_digit(char c) {
292 11600           return (unsigned)c - '0' < 10;
293             }
294              
295 417           bool tstr_token_parse_tz_offset(const char* src, size_t len, int* offset) {
296 417 100         if (!len)
297 1           return false;
298              
299 416           const char *end = src + len;
300             int sign;
301 416           switch (*src++) {
302 278           case '+':
303 278           sign = 1;
304 278           break;
305 135           case '-':
306 135           sign = -1;
307 135           break;
308 3           default:
309 3           return false;
310             }
311              
312             // Parse hour (1-2 digits)
313 413           int h = 0;
314 413           size_t nd = 0;
315 1220 100         while (nd < 2 && src < end && is_digit(*src)) {
    100          
    100          
316 807           h = h * 10 + (*src++ - '0');
317 807           nd++;
318             }
319              
320 413 100         if (nd == 0)
321 2           return false;
322              
323             // Parse optional minutes
324 411           int m = 0;
325 411 100         if (src < end) {
326 374 100         if (*src == ':')
327 131           src++;
328 374 50         if (end - src != 2)
329 0           return false;
330 374 50         if (!is_digit(src[0]) || !is_digit(src[1]))
    50          
331 0           return false;
332 374           m = (src[0] - '0') * 10 + (src[1] - '0');
333 374           src += 2;
334             }
335              
336 411 50         if (src != end)
337 0           return false;
338              
339 411 100         if (h > 23 || m > 59)
    100          
340 7           return false;
341              
342 404           *offset = sign * (h * 60 + m);
343 404           return true;
344             }
345              
346 954           bool tstr_token_parse_year(const char* src, size_t len, int* year) {
347 954 100         if (len != 2 && len != 4)
    50          
348 0           return false;
349              
350 954           int v = 0;
351 4688 100         for (size_t i = 0; i < len; i++) {
352 3734 50         if (!is_digit(src[i]))
353 0           return false;
354 3734           v = v * 10 + (src[i] - '0');
355             }
356              
357 954           *year = v;
358 954           return true;
359             }
360              
361 827           bool tstr_token_parse_hour(const char* src, size_t len, int* hour) {
362 827 50         if (len < 1 || len > 2)
    50          
363 0           return false;
364              
365 827           int v = 0;
366 2476 100         for (size_t i = 0; i < len; i++) {
367 1649 50         if (!is_digit(src[i]))
368 0           return false;
369 1649           v = v * 10 + (src[i] - '0');
370             }
371              
372 827           *hour = v;
373 827           return true;
374             }
375              
376 803           bool tstr_token_parse_minute(const char* src, size_t len, int* minute) {
377 803 50         if (len != 2)
378 0           return false;
379 803 50         if (!is_digit(src[0]) || !is_digit(src[1]))
    50          
380 0           return false;
381              
382 803           *minute = (src[0] - '0') * 10 + (src[1] - '0');
383 803           return true;
384             }
385              
386 761           bool tstr_token_parse_second(const char* src, size_t len, int* second) {
387 761 50         if (len != 2)
388 0           return false;
389 761 50         if (!is_digit(src[0]) || !is_digit(src[1]))
    50          
390 0           return false;
391              
392 761           *second = (src[0] - '0') * 10 + (src[1] - '0');
393 761           return true;
394             }
395              
396 298           bool tstr_token_parse_fraction(const char* src, size_t len, int* nanosecond) {
397 298 50         if (len < 1 || len > 9)
    50          
398 0           return false;
399              
400 298           int v = 0;
401 1827 100         for (size_t i = 0; i < len; i++) {
402 1529 50         if (!is_digit(src[i]))
403 0           return false;
404 1529           v = v * 10 + (src[i] - '0');
405             }
406              
407 1451 100         for (size_t i = len; i < 9; i++)
408 1153           v *= 10;
409              
410 298           *nanosecond = v;
411 298           return true;
412             }