ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
strptime.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file strptime.cc
1 #ifndef __STRPTIME_C__
2 #define __STRPTIME_C__
3 /*
4  * Copyright (c) 1999 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of KTH nor the names of its contributors may be
20  * used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
24  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
34 
35 extern "C"
36 {
37 
38 #ifndef HAVE_STRPTIME_PROTOTYPE
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42 #include <ctype.h>
43 //#include "roken.h"
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <stdarg.h>
47 #include <string.h>
48 #include <signal.h>
49 #include <time.h>
50 
51 
52 static const char *abb_weekdays[] = {
53  "Sun",
54  "Mon",
55  "Tue",
56  "Wed",
57  "Thu",
58  "Fri",
59  "Sat",
60  NULL
61 };
62 
63 static const char *full_weekdays[] = {
64  "Sunday",
65  "Monday",
66  "Tuesday",
67  "Wednesday",
68  "Thursday",
69  "Friday",
70  "Saturday",
71  NULL
72 };
73 
74 static const char *abb_month[] = {
75  "Jan",
76  "Feb",
77  "Mar",
78  "Apr",
79  "May",
80  "Jun",
81  "Jul",
82  "Aug",
83  "Sep",
84  "Oct",
85  "Nov",
86  "Dec",
87  NULL
88 };
89 
90 static const char *full_month[] = {
91  "January",
92  "February",
93  "Mars",
94  "April",
95  "May",
96  "June",
97  "July",
98  "August",
99  "September",
100  "October",
101  "November",
102  "December",
103  NULL,
104 };
105 
106 static const char *ampm[] = {
107  "am",
108  "pm",
109  NULL
110 };
111 
112 /*
113  * Try to match `*buf' to one of the strings in `strs'. Return the
114  * index of the matching string (or -1 if none). Also advance buf.
115  */
116 
117 static int
118 match_string (const char **buf, const char **strs)
119 {
120  int i = 0;
121 
122  for (i = 0; strs[i] != NULL; ++i) {
123  int len = strlen (strs[i]);
124 
125  if (strncasecmp (*buf, strs[i], len) == 0) {
126  *buf += len;
127  return i;
128  }
129  }
130  return -1;
131 }
132 
133 /*
134  * tm_year is relative this year */
135 
136 const int tm_year_base = 1900;
137 
138 /*
139  * Return TRUE iff `year' was a leap year.
140  */
141 
142 static int
143 is_leap_year (int year)
144 {
145  return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
146 }
147 
148 /*
149  * Return the weekday [0,6] (0 = Sunday) of the first day of `year'
150  */
151 
152 static int
153 first_day (int year)
154 {
155  int ret = 4;
156 
157  for (; year > 1970; --year)
158  ret = (ret + 365 + is_leap_year (year) ? 1 : 0) % 7;
159  return ret;
160 }
161 
162 /*
163  * Set `timeptr' given `wnum' (week number [0, 53])
164  */
165 
166 static void
167 set_week_number_sun (struct tm *timeptr, int wnum)
168 {
169  int fday = first_day (timeptr->tm_year + tm_year_base);
170 
171  timeptr->tm_yday = wnum * 7 + timeptr->tm_wday - fday;
172  if (timeptr->tm_yday < 0) {
173  timeptr->tm_wday = fday;
174  timeptr->tm_yday = 0;
175  }
176 }
177 
178 /*
179  * Set `timeptr' given `wnum' (week number [0, 53])
180  */
181 
182 static void
183 set_week_number_mon (struct tm *timeptr, int wnum)
184 {
185  int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7;
186 
187  timeptr->tm_yday = wnum * 7 + (timeptr->tm_wday + 6) % 7 - fday;
188  if (timeptr->tm_yday < 0) {
189  timeptr->tm_wday = (fday + 1) % 7;
190  timeptr->tm_yday = 0;
191  }
192 }
193 
194 /*
195  * Set `timeptr' given `wnum' (week number [0, 53])
196  */
197 
198 static void
199 set_week_number_mon4 (struct tm *timeptr, int wnum)
200 {
201  int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7;
202  int offset = 0;
203 
204  if (fday < 4)
205  offset += 7;
206 
207  timeptr->tm_yday = offset + (wnum - 1) * 7 + timeptr->tm_wday - fday;
208  if (timeptr->tm_yday < 0) {
209  timeptr->tm_wday = fday;
210  timeptr->tm_yday = 0;
211  }
212 }
213 
214 /*
215  *
216  */
217 
218 char *
219 strptime (const char *buf, const char *format, struct tm *timeptr)
220 {
221  char c;
222 
223  for (; (c = *format) != '\0'; ++format) {
224  char *s;
225  int ret;
226 
227  if (isspace (c)) {
228  while (isspace (*buf))
229  ++buf;
230  } else if (c == '%' && format[1] != '\0') {
231  c = *++format;
232  if (c == 'E' || c == 'O')
233  c = *++format;
234  switch (c) {
235  case 'A' :
236  ret = match_string (&buf, full_weekdays);
237  if (ret < 0)
238  return NULL;
239  timeptr->tm_wday = ret;
240  break;
241  case 'a' :
242  ret = match_string (&buf, abb_weekdays);
243  if (ret < 0)
244  return NULL;
245  timeptr->tm_wday = ret;
246  break;
247  case 'B' :
248  ret = match_string (&buf, full_month);
249  if (ret < 0)
250  return NULL;
251  timeptr->tm_mon = ret;
252  break;
253  case 'b' :
254  case 'h' :
255  ret = match_string (&buf, abb_month);
256  if (ret < 0)
257  return NULL;
258  timeptr->tm_mon = ret;
259  break;
260  case 'C' :
261  ret = strtol (buf, &s, 10);
262  if (s == buf)
263  return NULL;
264  timeptr->tm_year = (ret * 100) - tm_year_base;
265  buf = s;
266  break;
267  case 'c' :
268  abort ();
269  case 'D' : /* %m/%d/%y */
270  s = strptime (buf, "%m/%d/%y", timeptr);
271  if (s == NULL)
272  return NULL;
273  buf = s;
274  break;
275  case 'd' :
276  case 'e' :
277  ret = strtol (buf, &s, 10);
278  if (s == buf)
279  return NULL;
280  timeptr->tm_mday = ret;
281  buf = s;
282  break;
283  case 'H' :
284  case 'k' :
285  ret = strtol (buf, &s, 10);
286  if (s == buf)
287  return NULL;
288  timeptr->tm_hour = ret;
289  buf = s;
290  break;
291  case 'I' :
292  case 'l' :
293  ret = strtol (buf, &s, 10);
294  if (s == buf)
295  return NULL;
296  if (ret == 12)
297  timeptr->tm_hour = 0;
298  else
299  timeptr->tm_hour = ret;
300  buf = s;
301  break;
302  case 'j' :
303  ret = strtol (buf, &s, 10);
304  if (s == buf)
305  return NULL;
306  timeptr->tm_yday = ret - 1;
307  buf = s;
308  break;
309  case 'm' :
310  ret = strtol (buf, &s, 10);
311  if (s == buf)
312  return NULL;
313  timeptr->tm_mon = ret - 1;
314  buf = s;
315  break;
316  case 'M' :
317  ret = strtol (buf, &s, 10);
318  if (s == buf)
319  return NULL;
320  timeptr->tm_min = ret;
321  buf = s;
322  break;
323  case 'n' :
324  if (*buf == '\n')
325  ++buf;
326  else
327  return NULL;
328  break;
329  case 'p' :
330  ret = match_string (&buf, ampm);
331  if (ret < 0)
332  return NULL;
333  if (timeptr->tm_hour == 0) {
334  if (ret == 1)
335  timeptr->tm_hour = 12;
336  } else
337  timeptr->tm_hour += 12;
338  break;
339  case 'r' : /* %I:%M:%S %p */
340  s = strptime (buf, "%I:%M:%S %p", timeptr);
341  if (s == NULL)
342  return NULL;
343  buf = s;
344  break;
345  case 'R' : /* %H:%M */
346  s = strptime (buf, "%H:%M", timeptr);
347  if (s == NULL)
348  return NULL;
349  buf = s;
350  break;
351  case 'S' :
352  ret = strtol (buf, &s, 10);
353  if (s == buf)
354  return NULL;
355  timeptr->tm_sec = ret;
356  buf = s;
357  break;
358  case 't' :
359  if (*buf == '\t')
360  ++buf;
361  else
362  return NULL;
363  break;
364  case 'T' : /* %H:%M:%S */
365  case 'X' :
366  s = strptime (buf, "%H:%M:%S", timeptr);
367  if (s == NULL)
368  return NULL;
369  buf = s;
370  break;
371  case 'u' :
372  ret = strtol (buf, &s, 10);
373  if (s == buf)
374  return NULL;
375  timeptr->tm_wday = ret - 1;
376  buf = s;
377  break;
378  case 'w' :
379  ret = strtol (buf, &s, 10);
380  if (s == buf)
381  return NULL;
382  timeptr->tm_wday = ret;
383  buf = s;
384  break;
385  case 'U' :
386  ret = strtol (buf, &s, 10);
387  if (s == buf)
388  return NULL;
389  set_week_number_sun (timeptr, ret);
390  buf = s;
391  break;
392  case 'V' :
393  ret = strtol (buf, &s, 10);
394  if (s == buf)
395  return NULL;
396  set_week_number_mon4 (timeptr, ret);
397  buf = s;
398  break;
399  case 'W' :
400  ret = strtol (buf, &s, 10);
401  if (s == buf)
402  return NULL;
403  set_week_number_mon (timeptr, ret);
404  buf = s;
405  break;
406  case 'x' :
407  s = strptime (buf, "%Y:%m:%d", timeptr);
408  if (s == NULL)
409  return NULL;
410  buf = s;
411  break;
412  case 'y' :
413  ret = strtol (buf, &s, 10);
414  if (s == buf)
415  return NULL;
416  if (ret < 70)
417  timeptr->tm_year = 100 + ret;
418  else
419  timeptr->tm_year = ret;
420  buf = s;
421  break;
422  case 'Y' :
423  ret = strtol (buf, &s, 10);
424  if (s == buf)
425  return NULL;
426  timeptr->tm_year = ret - tm_year_base;
427  buf = s;
428  break;
429  case 'Z' :
430  abort ();
431  case '\0' :
432  --format;
433  /* FALLTHROUGH */
434  case '%' :
435  if (*buf == '%')
436  ++buf;
437  else
438  return NULL;
439  break;
440  default :
441  if (*buf == '%' || *++buf == c)
442  ++buf;
443  else
444  return NULL;
445  break;
446  }
447  } else {
448  if (*buf == c)
449  ++buf;
450  else
451  return NULL;
452  }
453  }
454  return (char *)buf;
455 }
456 
457 #endif
458 }
459 
460 #endif /* __STRPTIME_C__ */