blob: 47f9564d526c161b2204eb12accb2d0a23500799 [file] [log] [blame]
Jan Kundráta5a7e292021-12-10 17:37:46 +01001/*
2 * This comes from the musl C library which has been licensed under the permissive MIT license.
3 *
4 * Downloaded from https://git.musl-libc.org/cgit/musl/plain/src/time/strptime.c,
5 * commit 98e688a9da5e7b2925dda17a2d6820dddf1fb287.
Jan Kundrát3b30ba12021-12-11 00:46:58 +01006 *
7 * Lobotomized to remove references to nl_langinfo().
Jan Kundráta5a7e292021-12-10 17:37:46 +01008 * */
9
Jan Kundrát3b30ba12021-12-11 00:46:58 +010010#include <stdio.h>
Jan Kundráta5a7e292021-12-10 17:37:46 +010011#include <stdlib.h>
Jan Kundráta5a7e292021-12-10 17:37:46 +010012#include <time.h>
13#include <ctype.h>
14#include <stddef.h>
15#include <string.h>
Jan Kundráta5a7e292021-12-10 17:37:46 +010016
17char *strptime(const char *restrict s, const char *restrict f, struct tm *restrict tm)
18{
19 int i, w, neg, adj, min, range, *dest, dummy;
Jan Kundráta5a7e292021-12-10 17:37:46 +010020 int want_century = 0, century = 0, relyear = 0;
21 while (*f) {
22 if (*f != '%') {
23 if (isspace(*f)) for (; *s && isspace(*s); s++);
24 else if (*s != *f) return 0;
25 else s++;
26 f++;
27 continue;
28 }
29 f++;
30 if (*f == '+') f++;
31 if (isdigit(*f)) {
32 char *new_f;
33 w=strtoul(f, &new_f, 10);
34 f = new_f;
35 } else {
36 w=-1;
37 }
38 adj=0;
39 switch (*f++) {
40 case 'a': case 'A':
Jan Kundráta5a7e292021-12-10 17:37:46 +010041 case 'b': case 'B': case 'h':
Jan Kundráta5a7e292021-12-10 17:37:46 +010042 case 'c':
Jan Kundrát3b30ba12021-12-11 00:46:58 +010043 goto fail_nl_langinfo;
Jan Kundráta5a7e292021-12-10 17:37:46 +010044 case 'C':
45 dest = &century;
46 if (w<0) w=2;
47 want_century |= 2;
48 goto numeric_digits;
49 case 'd': case 'e':
50 dest = &tm->tm_mday;
51 min = 1;
52 range = 31;
53 goto numeric_range;
54 case 'D':
55 s = strptime(s, "%m/%d/%y", tm);
56 if (!s) return 0;
57 break;
58 case 'H':
59 dest = &tm->tm_hour;
60 min = 0;
61 range = 24;
62 goto numeric_range;
63 case 'I':
64 dest = &tm->tm_hour;
65 min = 1;
66 range = 12;
67 goto numeric_range;
68 case 'j':
69 dest = &tm->tm_yday;
70 min = 1;
71 range = 366;
72 adj = 1;
73 goto numeric_range;
74 case 'm':
75 dest = &tm->tm_mon;
76 min = 1;
77 range = 12;
78 adj = 1;
79 goto numeric_range;
80 case 'M':
81 dest = &tm->tm_min;
82 min = 0;
83 range = 60;
84 goto numeric_range;
85 case 'n': case 't':
86 for (; *s && isspace(*s); s++);
87 break;
88 case 'p':
Jan Kundráta5a7e292021-12-10 17:37:46 +010089 case 'r':
Jan Kundrát3b30ba12021-12-11 00:46:58 +010090 goto fail_nl_langinfo;
Jan Kundráta5a7e292021-12-10 17:37:46 +010091 case 'R':
92 s = strptime(s, "%H:%M", tm);
93 if (!s) return 0;
94 break;
95 case 'S':
96 dest = &tm->tm_sec;
97 min = 0;
98 range = 61;
99 goto numeric_range;
100 case 'T':
101 s = strptime(s, "%H:%M:%S", tm);
102 if (!s) return 0;
103 break;
104 case 'U':
105 case 'W':
106 /* Throw away result, for now. (FIXME?) */
107 dest = &dummy;
108 min = 0;
109 range = 54;
110 goto numeric_range;
111 case 'w':
112 dest = &tm->tm_wday;
113 min = 0;
114 range = 7;
115 goto numeric_range;
116 case 'x':
Jan Kundráta5a7e292021-12-10 17:37:46 +0100117 case 'X':
Jan Kundrát3b30ba12021-12-11 00:46:58 +0100118 goto fail_nl_langinfo;
Jan Kundráta5a7e292021-12-10 17:37:46 +0100119 case 'y':
120 dest = &relyear;
121 w = 2;
122 want_century |= 1;
123 goto numeric_digits;
124 case 'Y':
125 dest = &tm->tm_year;
126 if (w<0) w=4;
127 adj = 1900;
128 want_century = 0;
129 goto numeric_digits;
130 case '%':
131 if (*s++ != '%') return 0;
132 break;
133 default:
134 return 0;
135 numeric_range:
136 if (!isdigit(*s)) return 0;
137 *dest = 0;
138 for (i=1; i<=min+range && isdigit(*s); i*=10)
139 *dest = *dest * 10 + *s++ - '0';
140 if (*dest - min >= (unsigned)range) return 0;
141 *dest -= adj;
142 switch((char *)dest - (char *)tm) {
143 case offsetof(struct tm, tm_yday):
144 ;
145 }
146 goto update;
147 numeric_digits:
148 neg = 0;
149 if (*s == '+') s++;
150 else if (*s == '-') neg=1, s++;
151 if (!isdigit(*s)) return 0;
152 for (*dest=i=0; i<w && isdigit(*s); i++)
153 *dest = *dest * 10 + *s++ - '0';
154 if (neg) *dest = -*dest;
155 *dest -= adj;
156 goto update;
Jan Kundráta5a7e292021-12-10 17:37:46 +0100157 update:
158 //FIXME
159 ;
160 }
161 }
162 if (want_century) {
163 tm->tm_year = relyear;
164 if (want_century & 2) tm->tm_year += century * 100 - 1900;
165 else if (tm->tm_year <= 68) tm->tm_year += 100;
166 }
167 return (char *)s;
Jan Kundrát3b30ba12021-12-11 00:46:58 +0100168fail_nl_langinfo:
169 fprintf(stderr, "strptime: nl_langinfo not available");
170 return NULL;
Jan Kundráta5a7e292021-12-10 17:37:46 +0100171}