#include "../src/journal.h" #include "../src/text.h" #include /* C99 */ #include #include #include /** 1. reverse ordering, 2. uint32_t is a valid union type, 3. C11 or GNU anonymous unions. */ union date32 { struct { uint32_t day : 5, month : 4, year : 23; }; uint32_t u32; }; static void date32_to_string(const union date32 d, char (*const z)[12]) { assert(d.year < 10000 && d.month && d.month <= 31 && d.day && d.day <= 31); sprintf(*z, "%u-%2.2u-%2.2u", d.year % 10000, d.month, d.day); } static int page_compare(const union date32 a, const union date32 b) { return a.u32 > b.u32; } static void page_to_string(const union date32 d, char (*const z)[12]) { date32_to_string(d, z); } static void page_to_string(const struct page_tree_entry entry, char (*const z)[12]) { date32_to_string(*entry.key, z); } #define TREE_NAME page #define TREE_KEY union date32 #define TREE_VALUE char * #define TREE_COMPARE #define TREE_TO_STRING #include "../src/tree.h" /*!re2c re2c:yyfill:enable = 0; re2c:define:YYCTYPE = char; */ /** "-"? [1-9][0-9]*$, within the range of `INT_MAX`. */ static int looks_like_year(const char *const a, int *const year) { const char *YYCURSOR = a, *YYMARKER = a, *s0; /*!stags:re2c format = 'const char *@@;\n'; */ assert(a && year); /*!re2c /**/ @s0 ("-"? [1-9][0-9]* | "0") "\x00" { int sign = 1, mag; if(*s0 == '-') { sign = -1; s0++; } for(mag = 0; *s0 != '\0'; s0++) { int d = *s0 - '0'; if((INT_MAX - d) / 10 < mag) return 0; mag = mag * 10 + d; } *year = sign * mag; return 1; } * { return 0; } */ } /** 1 <= [0-1][0-9]$ <= 12 */ static unsigned looks_like_month(const char *const a) { const char *YYCURSOR = a, *YYMARKER = a, *s0; /*!stags:re2c format = 'const char *@@;\n'; */ (void)yyt1; assert(a); /*!re2c /**/ @s0 [0-1][0-9] "\x00" { unsigned val = 10u * (unsigned)(s0[0] - '0') + (unsigned)(s0[1] - '0'); return val < 1 || val > 12 ? 0 : val; } * { return 0; } */ } /** 1 <= [0-3][0-9].txt$ <= 31 */ static unsigned looks_like_day(const char *const a) { const char *YYCURSOR = a, *YYMARKER = a, *s0; /*!stags:re2c format = 'const char *@@;\n'; */ (void)yyt1; assert(a); /*!re2c /**/ @s0 [0-3][0-9] ".txt\x00" { unsigned val = 10u * (unsigned)(s0[0] - '0') + (unsigned)(s0[1] - '0'); return val < 1 || val > 31 ? 0 : val; } * { return 0; } */ }