~ubuntu-branches/ubuntu/trusty/mapcache/trusty

« back to all changes in this revision

Viewing changes to lib/strptime.c

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2013-09-11 19:16:06 UTC
  • Revision ID: package-import@ubuntu.com-20130911191606-9aydo919w4dgjx9v
Tags: upstream-1.2.0
Import upstream version 1.2.0

Show diffs side-by-side

added added

removed removed

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