Updating built in Io code to use += instead of x = x + y
[io/quag.git] / libs / basekit / source / PortableStrptime.c
blobd04cb19c297abe94e9786b0a6b726269437baa83
1 /*
2 * code found at: http://www.uni-paderborn.de/info/solaris_porting_faq
3 */
4 /*
5 * Copyright (c) 1994 Powerdog Industries. All rights reserved.
7 * Redistribution and use in source and binary forms, without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * 3. All advertising materials mentioning features or use of this
17 * software must display the following acknowledgement:
18 * This product includes software developed by Powerdog Industries.
19 * 4. The name of Powerdog Industries may not be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
23 * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``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 THE POWERDOG INDUSTRIES 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
32 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 /* A few changes by Steve Dekorte:
37 * - renamed function and moved En_US into function
39 #include "Base.h"
40 #include "PortableStrptime.h"
42 /*#ifdef IO_NEEDS_STRPTIME*/
44 #include <time.h>
45 #include <ctype.h>
46 #include <locale.h>
47 #include <string.h>
49 #define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
51 /*#ifndef sun*/
52 struct dtconv {
53 char *abbrev_month_names[12];
54 char *month_names[12];
55 char *abbrev_weekday_names[7];
56 char *weekday_names[7];
57 char *time_format;
58 char *sdate_format;
59 char *dtime_format;
60 char *am_string;
61 char *pm_string;
62 char *ldate_format;
64 /*#endif*/
66 #ifdef SUNOS4
67 extern int strncasecmp();
68 #endif
70 #if defined(_MSC_VER) && !defined(__SYMBIAN32__)
71 #define strcasecmp _stricmp
72 #define strncasecmp _strnicmp
73 #endif
75 int readndigits(char **const buf, const size_t count)
77 int result = 0;
78 int i;
80 for (i = 0; i < count; i++, (*buf)++) {
81 const char digit = **buf;
82 if (digit == 0 || !isdigit(digit)) {
83 break;
85 result *= 10;
86 result += digit - '0';
89 return result;
92 // TODO rename function when I understand what this function does.
93 void somethingToDoWithSpaces(const char *const buf, char **const ptr)
95 if (*buf != 0 && isspace((int)*buf)) {
96 while (**ptr != 0 && !isspace((int)**ptr)) {
97 (*ptr)++;
102 char *io_strptime(char *buf, char *fmt, struct tm *tm)
104 struct dtconv En_US = {
105 { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
106 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" },
107 { "January", "February", "March", "April",
108 "May", "June", "July", "August",
109 "September", "October", "November", "December" },
110 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
111 { "Sunday", "Monday", "Tuesday", "Wednesday",
112 "Thursday", "Friday", "Saturday" },
113 "%H:%M:%S",
114 "%m/%d/%y",
115 "%a %b %e %T %Z %Y",
116 "AM",
117 "PM",
118 "%A, %B, %e, %Y"
121 char c,
122 *ptr;
123 int i,
124 len;
126 len = 0;
127 ptr = fmt;
128 while (*ptr != 0) {
129 if (*buf == 0)
130 break;
132 c = *ptr++;
134 if (c != '%') {
135 if (isspace((int)c))
136 while (*buf != 0 && isspace((int)*buf))
137 buf++;
138 else if (c != *buf++)
139 return NULL;
140 continue;
143 c = *ptr++;
144 switch (c) {
145 case 0:
146 return NULL;
148 case '%':
149 if (*buf++ != '%')
150 return NULL;
151 break;
153 case 'C':
154 buf = io_strptime(buf, En_US.ldate_format, tm);
155 if (buf == 0)
156 return NULL;
157 break;
159 case 'c':
160 buf = io_strptime(buf, "%x %X", tm);
161 if (buf == 0)
162 return NULL;
163 break;
165 case 'D':
166 buf = io_strptime(buf, "%m/%d/%y", tm);
167 if (buf == 0)
168 return NULL;
169 break;
171 case 'R':
172 buf = io_strptime(buf, "%H:%M", tm);
173 if (buf == 0)
174 return NULL;
175 break;
177 case 'r':
178 buf = io_strptime(buf, "%I:%M:%S %p", tm);
179 if (buf == 0)
180 return NULL;
181 break;
183 case 'T':
184 buf = io_strptime(buf, "%H:%M:%S", tm);
185 if (buf == 0)
186 return NULL;
187 break;
189 case 'X':
190 buf = io_strptime(buf, En_US.time_format, tm);
191 if (buf == 0)
192 return NULL;
193 break;
195 case 'x':
196 buf = io_strptime(buf, En_US.sdate_format, tm);
197 if (buf == 0)
198 return NULL;
199 break;
201 case 'j':
202 if (*buf == 0 || isspace((int)*buf))
203 break;
205 i = readndigits(&buf, 3);
206 if (i < 0 || i > 366)
207 return NULL;
209 tm->tm_yday = i;
210 break;
212 case 'M':
213 if (*buf == 0 || isspace((int)*buf))
214 break;
216 i = readndigits(&buf, 2);
217 if (i < 0 || i > 59)
218 return NULL;
220 tm->tm_min = i;
222 somethingToDoWithSpaces(buf, &ptr);
223 break;
225 case 'S':
226 if (*buf == 0 || isspace((int)*buf))
227 break;
229 i = readndigits(&buf, 2);
230 if (i < 0 || i > 60) // Earlier 61 was also allowed.
231 return NULL;
233 tm->tm_sec = i;
235 somethingToDoWithSpaces(buf, &ptr);
236 break;
238 case 'H':
239 case 'k':
240 if (!isdigit((int)*buf))
241 return NULL;
243 i = readndigits(&buf, 2);
244 if (i < 0 || i > 23)
245 return NULL;
247 tm->tm_hour = i;
249 somethingToDoWithSpaces(buf, &ptr);
250 break;
252 case 'I':
253 case 'l':
254 if (!isdigit((int)*buf))
255 return NULL;
257 i = readndigits(&buf, 2);
258 if (i < 1 || i > 12)
259 return NULL;
261 tm->tm_hour = i;
263 somethingToDoWithSpaces(buf, &ptr);
264 break;
266 case 'd':
267 case 'e':
268 if (!isdigit((int)*buf))
269 return NULL;
271 i = readndigits(&buf, 2);
272 if (i < 1 || i > 31)
273 return NULL;
275 tm->tm_mday = i;
277 somethingToDoWithSpaces(buf, &ptr);
278 break;
280 case 'm':
281 if (!isdigit((int)*buf))
282 return NULL;
284 i = readndigits(&buf, 2);
285 if (i < 1 || i > 12)
286 return NULL;
288 tm->tm_mon = i - 1;
290 somethingToDoWithSpaces(buf, &ptr);
291 break;
293 case 'Y':
294 if (*buf == 0 || isspace((int)*buf))
295 break;
297 if (!isdigit((int)*buf))
298 return NULL;
300 i = readndigits(&buf, 4);
301 if (i < 0 || i > 9999)
302 return NULL;
304 tm->tm_year = i - 1900;
306 somethingToDoWithSpaces(buf, &ptr);
307 break;
309 case 'y':
310 if (*buf == 0 || isspace((int)*buf))
311 break;
313 if (!isdigit((int)*buf))
314 return NULL;
316 i = readndigits(&buf, 2);
317 if (i < 0 || i > 99)
318 return NULL;
320 tm->tm_year = i;
322 somethingToDoWithSpaces(buf, &ptr);
323 break;
325 case 'P':
326 case 'p':
327 len = strlen(En_US.am_string);
328 if (strncasecmp(buf, En_US.am_string, len) == 0) {
329 if (tm->tm_hour > 12)
330 return NULL;
331 if (tm->tm_hour == 12)
332 tm->tm_hour = 0;
333 buf += len;
334 break;
337 len = strlen(En_US.pm_string);
338 if (strncasecmp(buf, En_US.pm_string, len) == 0) {
339 if (tm->tm_hour > 12)
340 return NULL;
341 if (tm->tm_hour != 12)
342 tm->tm_hour += 12;
343 buf += len;
344 break;
347 return NULL;
349 case 'A':
350 case 'a':
351 for (i = 0; i < (int)asizeof(En_US.weekday_names); i ++) {
352 len = strlen(En_US.weekday_names[i]);
353 if (strncasecmp(buf,
354 En_US.weekday_names[i],
355 len) == 0)
356 break;
358 len = strlen(En_US.abbrev_weekday_names[i]);
359 if (strncasecmp(buf,
360 En_US.abbrev_weekday_names[i],
361 len) == 0)
362 break;
364 if (i == asizeof(En_US.weekday_names))
365 return NULL;
367 tm->tm_wday = i;
368 buf += len;
369 break;
371 case 'B':
372 case 'b':
373 case 'h':
374 for (i = 0; i < (int)asizeof(En_US.month_names); i ++) {
375 len = strlen(En_US.month_names[i]);
376 if (strncasecmp(buf,
377 En_US.month_names[i],
378 len) == 0)
379 break;
381 len = strlen(En_US.abbrev_month_names[i]);
382 if (strncasecmp(buf,
383 En_US.abbrev_month_names[i],
384 len) == 0)
385 break;
387 if (i == asizeof(En_US.month_names))
388 return NULL;
390 tm->tm_mon = i;
391 buf += len;
392 break;
396 return buf;
399 /*#endif*/