Annotation of embedaddon/php/ext/date/lib/parse_tz.c, revision 1.1.1.1
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1997-2010 The PHP Group |
6: +----------------------------------------------------------------------+
7: | This source file is subject to version 3.01 of the PHP license, |
8: | that is bundled with this package in the file LICENSE, and is |
9: | available through the world-wide-web at the following url: |
10: | http://www.php.net/license/3_01.txt |
11: | If you did not receive a copy of the PHP license and are unable to |
12: | obtain it through the world-wide-web, please send a note to |
13: | license@php.net so we can mail you a copy immediately. |
14: +----------------------------------------------------------------------+
15: | Authors: Derick Rethans <derick@derickrethans.nl> |
16: +----------------------------------------------------------------------+
17: */
18:
19: /* $Id: parse_tz.c 311110 2011-05-16 21:29:45Z johannes $ */
20:
21: #include "timelib.h"
22:
23: #include <stdio.h>
24:
25: #ifdef HAVE_LOCALE_H
26: #include <locale.h>
27: #endif
28:
29: #ifdef HAVE_STRING_H
30: #include <string.h>
31: #else
32: #include <strings.h>
33: #endif
34: #include "timezonedb.h"
35:
36: #if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
37: # if defined(__LITTLE_ENDIAN__)
38: # undef WORDS_BIGENDIAN
39: # else
40: # if defined(__BIG_ENDIAN__)
41: # define WORDS_BIGENDIAN
42: # endif
43: # endif
44: #endif
45:
46: #ifdef WORDS_BIGENDIAN
47: #define timelib_conv_int(l) (l)
48: #else
49: #define timelib_conv_int(l) ((l & 0x000000ff) << 24) + ((l & 0x0000ff00) << 8) + ((l & 0x00ff0000) >> 8) + ((l & 0xff000000) >> 24)
50: #endif
51:
52: static void read_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
53: {
54: /* skip ID */
55: *tzf += 4;
56:
57: /* read BC flag */
58: tz->bc = (**tzf == '\1');
59: *tzf += 1;
60:
61: /* read country code */
62: memcpy(tz->location.country_code, *tzf, 2);
63: tz->location.country_code[2] = '\0';
64: *tzf += 2;
65:
66: /* skip read of preamble */
67: *tzf += 13;
68: }
69:
70: static void read_header(const unsigned char **tzf, timelib_tzinfo *tz)
71: {
72: uint32_t buffer[6];
73:
74: memcpy(&buffer, *tzf, sizeof(buffer));
75: tz->ttisgmtcnt = timelib_conv_int(buffer[0]);
76: tz->ttisstdcnt = timelib_conv_int(buffer[1]);
77: tz->leapcnt = timelib_conv_int(buffer[2]);
78: tz->timecnt = timelib_conv_int(buffer[3]);
79: tz->typecnt = timelib_conv_int(buffer[4]);
80: tz->charcnt = timelib_conv_int(buffer[5]);
81: *tzf += sizeof(buffer);
82: }
83:
84: static void read_transistions(const unsigned char **tzf, timelib_tzinfo *tz)
85: {
86: int32_t *buffer = NULL;
87: uint32_t i;
88: unsigned char *cbuffer = NULL;
89:
90: if (tz->timecnt) {
91: buffer = (int32_t*) malloc(tz->timecnt * sizeof(int32_t));
92: if (!buffer) {
93: return;
94: }
95: memcpy(buffer, *tzf, sizeof(int32_t) * tz->timecnt);
96: *tzf += (sizeof(int32_t) * tz->timecnt);
97: for (i = 0; i < tz->timecnt; i++) {
98: buffer[i] = timelib_conv_int(buffer[i]);
99: }
100:
101: cbuffer = (unsigned char*) malloc(tz->timecnt * sizeof(unsigned char));
102: if (!cbuffer) {
103: free(buffer);
104: return;
105: }
106: memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->timecnt);
107: *tzf += sizeof(unsigned char) * tz->timecnt;
108: }
109:
110: tz->trans = buffer;
111: tz->trans_idx = cbuffer;
112: }
113:
114: static void read_types(const unsigned char **tzf, timelib_tzinfo *tz)
115: {
116: unsigned char *buffer;
117: int32_t *leap_buffer;
118: unsigned int i, j;
119:
120: buffer = (unsigned char*) malloc(tz->typecnt * sizeof(unsigned char) * 6);
121: if (!buffer) {
122: return;
123: }
124: memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->typecnt);
125: *tzf += sizeof(unsigned char) * 6 * tz->typecnt;
126:
127: tz->type = (ttinfo*) malloc(tz->typecnt * sizeof(struct ttinfo));
128: if (!tz->type) {
129: free(buffer);
130: return;
131: }
132:
133: for (i = 0; i < tz->typecnt; i++) {
134: j = i * 6;
135: tz->type[i].offset = (buffer[j] * 16777216) + (buffer[j + 1] * 65536) + (buffer[j + 2] * 256) + buffer[j + 3];
136: tz->type[i].isdst = buffer[j + 4];
137: tz->type[i].abbr_idx = buffer[j + 5];
138: }
139: free(buffer);
140:
141: tz->timezone_abbr = (char*) malloc(tz->charcnt);
142: if (!tz->timezone_abbr) {
143: return;
144: }
145: memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->charcnt);
146: *tzf += sizeof(char) * tz->charcnt;
147:
148: if (tz->leapcnt) {
149: leap_buffer = (int32_t *) malloc(tz->leapcnt * 2 * sizeof(int32_t));
150: if (!leap_buffer) {
151: return;
152: }
153: memcpy(leap_buffer, *tzf, sizeof(int32_t) * tz->leapcnt * 2);
154: *tzf += sizeof(int32_t) * tz->leapcnt * 2;
155:
156: tz->leap_times = (tlinfo*) malloc(tz->leapcnt * sizeof(tlinfo));
157: if (!tz->leap_times) {
158: free(leap_buffer);
159: return;
160: }
161: for (i = 0; i < tz->leapcnt; i++) {
162: tz->leap_times[i].trans = timelib_conv_int(leap_buffer[i * 2]);
163: tz->leap_times[i].offset = timelib_conv_int(leap_buffer[i * 2 + 1]);
164: }
165: free(leap_buffer);
166: }
167:
168: if (tz->ttisstdcnt) {
169: buffer = (unsigned char*) malloc(tz->ttisstdcnt * sizeof(unsigned char));
170: if (!buffer) {
171: return;
172: }
173: memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisstdcnt);
174: *tzf += sizeof(unsigned char) * tz->ttisstdcnt;
175:
176: for (i = 0; i < tz->ttisstdcnt; i++) {
177: tz->type[i].isstdcnt = buffer[i];
178: }
179: free(buffer);
180: }
181:
182: if (tz->ttisgmtcnt) {
183: buffer = (unsigned char*) malloc(tz->ttisgmtcnt * sizeof(unsigned char));
184: if (!buffer) {
185: return;
186: }
187: memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisgmtcnt);
188: *tzf += sizeof(unsigned char) * tz->ttisgmtcnt;
189:
190: for (i = 0; i < tz->ttisgmtcnt; i++) {
191: tz->type[i].isgmtcnt = buffer[i];
192: }
193: free(buffer);
194: }
195: }
196:
197: static void read_location(const unsigned char **tzf, timelib_tzinfo *tz)
198: {
199: uint32_t buffer[3];
200: uint32_t comments_len;
201:
202: memcpy(&buffer, *tzf, sizeof(buffer));
203: tz->location.latitude = timelib_conv_int(buffer[0]);
204: tz->location.latitude = (tz->location.latitude / 100000) - 90;
205: tz->location.longitude = timelib_conv_int(buffer[1]);
206: tz->location.longitude = (tz->location.longitude / 100000) - 180;
207: comments_len = timelib_conv_int(buffer[2]);
208: *tzf += sizeof(buffer);
209:
210: tz->location.comments = malloc(comments_len + 1);
211: memcpy(tz->location.comments, *tzf, comments_len);
212: tz->location.comments[comments_len] = '\0';
213: *tzf += comments_len;
214: }
215:
216: void timelib_dump_tzinfo(timelib_tzinfo *tz)
217: {
218: uint32_t i;
219:
220: printf("Country Code: %s\n", tz->location.country_code);
221: printf("Geo Location: %f,%f\n", tz->location.latitude, tz->location.longitude);
222: printf("Comments:\n%s\n", tz->location.comments);
223: printf("BC: %s\n", tz->bc ? "" : "yes");
224: printf("UTC/Local count: %lu\n", (unsigned long) tz->ttisgmtcnt);
225: printf("Std/Wall count: %lu\n", (unsigned long) tz->ttisstdcnt);
226: printf("Leap.sec. count: %lu\n", (unsigned long) tz->leapcnt);
227: printf("Trans. count: %lu\n", (unsigned long) tz->timecnt);
228: printf("Local types count: %lu\n", (unsigned long) tz->typecnt);
229: printf("Zone Abbr. count: %lu\n", (unsigned long) tz->charcnt);
230:
231: printf ("%8s (%12s) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
232: "", "", 0,
233: (long int) tz->type[0].offset,
234: tz->type[0].isdst,
235: tz->type[0].abbr_idx,
236: &tz->timezone_abbr[tz->type[0].abbr_idx],
237: tz->type[0].isstdcnt,
238: tz->type[0].isgmtcnt
239: );
240: for (i = 0; i < tz->timecnt; i++) {
241: printf ("%08X (%12d) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
242: tz->trans[i], tz->trans[i], tz->trans_idx[i],
243: (long int) tz->type[tz->trans_idx[i]].offset,
244: tz->type[tz->trans_idx[i]].isdst,
245: tz->type[tz->trans_idx[i]].abbr_idx,
246: &tz->timezone_abbr[tz->type[tz->trans_idx[i]].abbr_idx],
247: tz->type[tz->trans_idx[i]].isstdcnt,
248: tz->type[tz->trans_idx[i]].isgmtcnt
249: );
250: }
251: for (i = 0; i < tz->leapcnt; i++) {
252: printf ("%08X (%12ld) = %d\n",
253: tz->leap_times[i].trans,
254: (long) tz->leap_times[i].trans,
255: tz->leap_times[i].offset);
256: }
257: }
258:
259: static int seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb)
260: {
261: int left = 0, right = tzdb->index_size - 1;
262: #ifdef HAVE_SETLOCALE
263: char *cur_locale = NULL, *tmp;
264:
265: tmp = setlocale(LC_CTYPE, NULL);
266: if (tmp) {
267: cur_locale = strdup(tmp);
268: }
269: setlocale(LC_CTYPE, "C");
270: #endif
271:
272: do {
273: int mid = ((unsigned)left + right) >> 1;
274: int cmp = strcasecmp(timezone, tzdb->index[mid].id);
275:
276: if (cmp < 0) {
277: right = mid - 1;
278: } else if (cmp > 0) {
279: left = mid + 1;
280: } else { /* (cmp == 0) */
281: (*tzf) = &(tzdb->data[tzdb->index[mid].pos]);
282: #ifdef HAVE_SETLOCALE
283: setlocale(LC_CTYPE, cur_locale);
284: if (cur_locale) free(cur_locale);
285: #endif
286: return 1;
287: }
288:
289: } while (left <= right);
290:
291: #ifdef HAVE_SETLOCALE
292: setlocale(LC_CTYPE, cur_locale);
293: if (cur_locale) free(cur_locale);
294: #endif
295: return 0;
296: }
297:
298: const timelib_tzdb *timelib_builtin_db(void)
299: {
300: return &timezonedb_builtin;
301: }
302:
303: const timelib_tzdb_index_entry *timelib_timezone_builtin_identifiers_list(int *count)
304: {
305: *count = sizeof(timezonedb_idx_builtin) / sizeof(*timezonedb_idx_builtin);
306: return timezonedb_idx_builtin;
307: }
308:
309: int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb)
310: {
311: const unsigned char *tzf;
312: return (seek_to_tz_position(&tzf, timezone, tzdb));
313: }
314:
315: timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb)
316: {
317: const unsigned char *tzf;
318: timelib_tzinfo *tmp;
319:
320: if (seek_to_tz_position(&tzf, timezone, tzdb)) {
321: tmp = timelib_tzinfo_ctor(timezone);
322:
323: read_preamble(&tzf, tmp);
324: read_header(&tzf, tmp);
325: read_transistions(&tzf, tmp);
326: read_types(&tzf, tmp);
327: read_location(&tzf, tmp);
328: } else {
329: tmp = NULL;
330: }
331:
332: return tmp;
333: }
334:
335: static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib_sll *transition_time)
336: {
337: uint32_t i;
338:
339: /* If there is no transistion time, we pick the first one, if that doesn't
340: * exist we return NULL */
341: if (!tz->timecnt || !tz->trans) {
342: *transition_time = 0;
343: if (tz->typecnt == 1) {
344: return &(tz->type[0]);
345: }
346: return NULL;
347: }
348:
349: /* If the TS is lower than the first transistion time, then we scan over
350: * all the transistion times to find the first non-DST one, or the first
351: * one in case there are only DST entries. Not sure which smartass came up
352: * with this idea in the first though :) */
353: if (ts < tz->trans[0]) {
354: uint32_t j;
355:
356: *transition_time = 0;
357: j = 0;
358: while (j < tz->timecnt && tz->type[j].isdst) {
359: ++j;
360: }
361: if (j == tz->timecnt) {
362: j = 0;
363: }
364: return &(tz->type[j]);
365: }
366:
367: /* In all other cases we loop through the available transtion times to find
368: * the correct entry */
369: for (i = 0; i < tz->timecnt; i++) {
370: if (ts < tz->trans[i]) {
371: *transition_time = tz->trans[i - 1];
372: return &(tz->type[tz->trans_idx[i - 1]]);
373: }
374: }
375: *transition_time = tz->trans[tz->timecnt - 1];
376: return &(tz->type[tz->trans_idx[tz->timecnt - 1]]);
377: }
378:
379: static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
380: {
381: int i;
382:
383: if (!tz->leapcnt || !tz->leap_times) {
384: return NULL;
385: }
386:
387: for (i = tz->leapcnt - 1; i > 0; i--) {
388: if (ts > tz->leap_times[i].trans) {
389: return &(tz->leap_times[i]);
390: }
391: }
392: return NULL;
393: }
394:
395: int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz)
396: {
397: ttinfo *to;
398: timelib_sll dummy;
399:
400: if ((to = fetch_timezone_offset(tz, ts, &dummy))) {
401: return to->isdst;
402: }
403: return -1;
404: }
405:
406: timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz)
407: {
408: ttinfo *to;
409: tlinfo *tl;
410: int32_t offset = 0, leap_secs = 0;
411: char *abbr;
412: timelib_time_offset *tmp = timelib_time_offset_ctor();
413: timelib_sll transistion_time;
414:
415: if ((to = fetch_timezone_offset(tz, ts, &transistion_time))) {
416: offset = to->offset;
417: abbr = &(tz->timezone_abbr[to->abbr_idx]);
418: tmp->is_dst = to->isdst;
419: tmp->transistion_time = transistion_time;
420: } else {
421: offset = 0;
422: abbr = tz->timezone_abbr;
423: tmp->is_dst = 0;
424: tmp->transistion_time = 0;
425: }
426:
427: if ((tl = fetch_leaptime_offset(tz, ts))) {
428: leap_secs = -tl->offset;
429: }
430:
431: tmp->offset = offset;
432: tmp->leap_secs = leap_secs;
433: tmp->abbr = abbr ? strdup(abbr) : strdup("GMT");
434:
435: return tmp;
436: }
437:
438: timelib_sll timelib_get_current_offset(timelib_time *t)
439: {
440: timelib_time_offset *gmt_offset;
441: timelib_sll retval;
442:
443: switch (t->zone_type) {
444: case TIMELIB_ZONETYPE_ABBR:
445: case TIMELIB_ZONETYPE_OFFSET:
446: return (t->z + t->dst) * -60;
447:
448: case TIMELIB_ZONETYPE_ID:
449: gmt_offset = timelib_get_time_zone_info(t->sse, t->tz_info);
450: retval = gmt_offset->offset;
451: timelib_time_offset_dtor(gmt_offset);
452: return retval;
453:
454: default:
455: return 0;
456: }
457: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>