1 /* Missing time implementations for Windows
2 Code taken largely from rtmpserver (www.rtmpd.com)
3
4 Copyright (C) 2011-2018 Ruven Pillay
5 2010 Gavriloaie Eugen-Andrei
6 1997, 1998 Kungliga Tekniska Hogskolan
7 (Royal Institute of Technology, Stockholm, Sweden)
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23
24 #ifdef WIN32
25
26 #include <ctype.h>
27 #include <cmath>
28 #include <ctime>
29 #include <cstdlib>
30 #include <cstring>
31 #include <Windows.h>
32
33
34 int
strncasecmp(const char * s1,const char * s2,size_t n)35 strncasecmp(const char *s1, const char *s2, size_t n)
36 {
37 while(n > 0
38 && toupper((unsigned char)*s1) == toupper((unsigned char)*s2))
39 {
40 if(*s1 == '\0')
41 return 0;
42 s1++;
43 s2++;
44 n--;
45 }
46 if(n == 0)
47 return 0;
48 return toupper((unsigned char)*s1) - toupper((unsigned char)*s2);
49 }
50
51 int
gettimeofday(struct timeval * tv,struct timezone * tz)52 gettimeofday(struct timeval *tv, struct timezone* tz) {
53 FILETIME ft;
54 GetSystemTimeAsFileTime(&ft);
55 __int64 value = ((__int64) ft.dwHighDateTime << 32) | ft.dwLowDateTime;
56 tv->tv_usec = (long) ((value / 10LL) % 1000000LL);
57 tv->tv_sec = (long) ((value - 116444736000000000LL) / 10000000LL);
58 return (0);
59 }
60
61 static int
is_leap(unsigned y)62 is_leap(unsigned y)
63 {
64 y += 1900;
65 return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
66 }
67
68 time_t
timegm(struct tm * tm)69 timegm (struct tm *tm)
70 {
71 static const unsigned ndays[2][12] ={
72 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
73 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
74 time_t res = 0;
75 int i;
76
77 for (i = 70; i < tm->tm_year; ++i)
78 res += is_leap(i) ? 366 : 365;
79
80 for (i = 0; i < tm->tm_mon; ++i)
81 res += ndays[is_leap(tm->tm_year)][i];
82 res += tm->tm_mday - 1;
83 res *= 24;
84 res += tm->tm_hour;
85 res *= 60;
86 res += tm->tm_min;
87 res *= 60;
88 res += tm->tm_sec;
89 return res;
90 }
91
92 static const char *abb_weekdays[] = {
93 "Sun",
94 "Mon",
95 "Tue",
96 "Wed",
97 "Thu",
98 "Fri",
99 "Sat",
100 NULL
101 };
102
103 static const char *full_weekdays[] = {
104 "Sunday",
105 "Monday",
106 "Tuesday",
107 "Wednesday",
108 "Thursday",
109 "Friday",
110 "Saturday",
111 NULL
112 };
113
114 static const char *abb_month[] = {
115 "Jan",
116 "Feb",
117 "Mar",
118 "Apr",
119 "May",
120 "Jun",
121 "Jul",
122 "Aug",
123 "Sep",
124 "Oct",
125 "Nov",
126 "Dec",
127 NULL
128 };
129
130 static const char *full_month[] = {
131 "January",
132 "February",
133 "Mars",
134 "April",
135 "May",
136 "June",
137 "July",
138 "August",
139 "September",
140 "October",
141 "November",
142 "December",
143 NULL,
144 };
145
146 static const char *ampm[] = {
147 "am",
148 "pm",
149 NULL
150 };
151
152 /*
153 * Try to match `*buf' to one of the strings in `strs'. Return the
154 * index of the matching string (or -1 if none). Also advance buf.
155 */
156
157 static int
match_string(const char ** buf,const char ** strs)158 match_string (const char **buf, const char **strs)
159 {
160 int i = 0;
161
162 for (i = 0; strs[i] != NULL; ++i) {
163 int len = strlen (strs[i]);
164
165 if (strncasecmp (*buf, strs[i], len) == 0) {
166 *buf += len;
167 return i;
168 }
169 }
170 return -1;
171 }
172
173 /*
174 * tm_year is relative this year */
175
176 const int tm_year_base = 1900;
177
178 /*
179 * Return TRUE iff `year' was a leap year.
180 */
181
182 static int
is_leap_year(int year)183 is_leap_year (int year)
184 {
185 return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
186 }
187
188 /*
189 * Return the weekday [0,6] (0 = Sunday) of the first day of `year'
190 */
191
192 static int
first_day(int year)193 first_day (int year)
194 {
195 int ret = 4;
196
197 for (; year > 1970; --year)
198 ret = (ret + 365 + is_leap_year (year) ? 1 : 0) % 7;
199 return ret;
200 }
201
202 /*
203 * Set `timeptr' given `wnum' (week number [0, 53])
204 */
205
206 static void
set_week_number_sun(struct tm * timeptr,int wnum)207 set_week_number_sun (struct tm *timeptr, int wnum)
208 {
209 int fday = first_day (timeptr->tm_year + tm_year_base);
210
211 timeptr->tm_yday = wnum * 7 + timeptr->tm_wday - fday;
212 if (timeptr->tm_yday < 0) {
213 timeptr->tm_wday = fday;
214 timeptr->tm_yday = 0;
215 }
216 }
217
218 /*
219 * Set `timeptr' given `wnum' (week number [0, 53])
220 */
221
222 static void
set_week_number_mon(struct tm * timeptr,int wnum)223 set_week_number_mon (struct tm *timeptr, int wnum)
224 {
225 int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7;
226
227 timeptr->tm_yday = wnum * 7 + (timeptr->tm_wday + 6) % 7 - fday;
228 if (timeptr->tm_yday < 0) {
229 timeptr->tm_wday = (fday + 1) % 7;
230 timeptr->tm_yday = 0;
231 }
232 }
233
234 /*
235 * Set `timeptr' given `wnum' (week number [0, 53])
236 */
237
238 static void
set_week_number_mon4(struct tm * timeptr,int wnum)239 set_week_number_mon4 (struct tm *timeptr, int wnum)
240 {
241 int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7;
242 int offset = 0;
243
244 if (fday < 4)
245 offset += 7;
246
247 timeptr->tm_yday = offset + (wnum - 1) * 7 + timeptr->tm_wday - fday;
248 if (timeptr->tm_yday < 0) {
249 timeptr->tm_wday = fday;
250 timeptr->tm_yday = 0;
251 }
252 }
253
254 /*
255 *
256 */
257
258 char *
strptime(const char * buf,const char * fmt,struct tm * timeptr)259 strptime (const char *buf, const char *fmt, struct tm *timeptr)
260 {
261 char c;
262
263 for (; (c = *fmt) != '\0'; ++fmt) {
264 char *s;
265 int ret;
266
267 if (isspace (c)) {
268 while (isspace (*buf))
269 ++buf;
270 } else if (c == '%' && fmt[1] != '\0') {
271 c = *++fmt;
272 if (c == 'E' || c == 'O')
273 c = *++fmt;
274 switch (c) {
275 case 'A' :
276 ret = match_string (&buf, full_weekdays);
277 if (ret < 0)
278 return NULL;
279 timeptr->tm_wday = ret;
280 break;
281 case 'a' :
282 ret = match_string (&buf, abb_weekdays);
283 if (ret < 0)
284 return NULL;
285 timeptr->tm_wday = ret;
286 break;
287 case 'B' :
288 ret = match_string (&buf, full_month);
289 if (ret < 0)
290 return NULL;
291 timeptr->tm_mon = ret;
292 break;
293 case 'b' :
294 case 'h' :
295 ret = match_string (&buf, abb_month);
296 if (ret < 0)
297 return NULL;
298 timeptr->tm_mon = ret;
299 break;
300 case 'C' :
301 ret = strtol (buf, &s, 10);
302 if (s == buf)
303 return NULL;
304 timeptr->tm_year = (ret * 100) - tm_year_base;
305 buf = s;
306 break;
307 case 'c' :
308 abort ();
309 case 'D' : /* %m/%d/%y */
310 s = strptime (buf, "%m/%d/%y", timeptr);
311 if (s == NULL)
312 return NULL;
313 buf = s;
314 break;
315 case 'd' :
316 case 'e' :
317 ret = strtol (buf, &s, 10);
318 if (s == buf)
319 return NULL;
320 timeptr->tm_mday = ret;
321 buf = s;
322 break;
323 case 'H' :
324 case 'k' :
325 ret = strtol (buf, &s, 10);
326 if (s == buf)
327 return NULL;
328 timeptr->tm_hour = ret;
329 buf = s;
330 break;
331 case 'I' :
332 case 'l' :
333 ret = strtol (buf, &s, 10);
334 if (s == buf)
335 return NULL;
336 if (ret == 12)
337 timeptr->tm_hour = 0;
338 else
339 timeptr->tm_hour = ret;
340 buf = s;
341 break;
342 case 'j' :
343 ret = strtol (buf, &s, 10);
344 if (s == buf)
345 return NULL;
346 timeptr->tm_yday = ret - 1;
347 buf = s;
348 break;
349 case 'm' :
350 ret = strtol (buf, &s, 10);
351 if (s == buf)
352 return NULL;
353 timeptr->tm_mon = ret - 1;
354 buf = s;
355 break;
356 case 'M' :
357 ret = strtol (buf, &s, 10);
358 if (s == buf)
359 return NULL;
360 timeptr->tm_min = ret;
361 buf = s;
362 break;
363 case 'n' :
364 if (*buf == '\n')
365 ++buf;
366 else
367 return NULL;
368 break;
369 case 'p' :
370 ret = match_string (&buf, ampm);
371 if (ret < 0)
372 return NULL;
373 if (timeptr->tm_hour == 0) {
374 if (ret == 1)
375 timeptr->tm_hour = 12;
376 } else
377 timeptr->tm_hour += 12;
378 break;
379 case 'r' : /* %I:%M:%S %p */
380 s = strptime (buf, "%I:%M:%S %p", timeptr);
381 if (s == NULL)
382 return NULL;
383 buf = s;
384 break;
385 case 'R' : /* %H:%M */
386 s = strptime (buf, "%H:%M", timeptr);
387 if (s == NULL)
388 return NULL;
389 buf = s;
390 break;
391 case 'S' :
392 ret = strtol (buf, &s, 10);
393 if (s == buf)
394 return NULL;
395 timeptr->tm_sec = ret;
396 buf = s;
397 break;
398 case 't' :
399 if (*buf == '\t')
400 ++buf;
401 else
402 return NULL;
403 break;
404 case 'T' : /* %H:%M:%S */
405 case 'X' :
406 s = strptime (buf, "%H:%M:%S", timeptr);
407 if (s == NULL)
408 return NULL;
409 buf = s;
410 break;
411 case 'u' :
412 ret = strtol (buf, &s, 10);
413 if (s == buf)
414 return NULL;
415 timeptr->tm_wday = ret - 1;
416 buf = s;
417 break;
418 case 'w' :
419 ret = strtol (buf, &s, 10);
420 if (s == buf)
421 return NULL;
422 timeptr->tm_wday = ret;
423 buf = s;
424 break;
425 case 'U' :
426 ret = strtol (buf, &s, 10);
427 if (s == buf)
428 return NULL;
429 set_week_number_sun (timeptr, ret);
430 buf = s;
431 break;
432 case 'V' :
433 ret = strtol (buf, &s, 10);
434 if (s == buf)
435 return NULL;
436 set_week_number_mon4 (timeptr, ret);
437 buf = s;
438 break;
439 case 'W' :
440 ret = strtol (buf, &s, 10);
441 if (s == buf)
442 return NULL;
443 set_week_number_mon (timeptr, ret);
444 buf = s;
445 break;
446 case 'x' :
447 s = strptime (buf, "%Y:%m:%d", timeptr);
448 if (s == NULL)
449 return NULL;
450 buf = s;
451 break;
452 case 'y' :
453 ret = strtol (buf, &s, 10);
454 if (s == buf)
455 return NULL;
456 if (ret < 70)
457 timeptr->tm_year = 100 + ret;
458 else
459 timeptr->tm_year = ret;
460 buf = s;
461 break;
462 case 'Y' :
463 ret = strtol (buf, &s, 10);
464 if (s == buf)
465 return NULL;
466 timeptr->tm_year = ret - tm_year_base;
467 buf = s;
468 break;
469 case 'Z' :
470 abort ();
471 case '\0' :
472 --fmt;
473 /* FALLTHROUGH */
474 case '%' :
475 if (*buf == '%')
476 ++buf;
477 else
478 return NULL;
479 break;
480 default :
481 if (*buf == '%' || *++buf == c)
482 ++buf;
483 else
484 return NULL;
485 break;
486 }
487 } else {
488 if (*buf == c)
489 ++buf;
490 else
491 return NULL;
492 }
493 }
494 return (char *)buf;
495 }
496
497
498 #endif /* WIN32 */
499