Annotation of embedaddon/php/ext/date/lib/parse_tz.c, revision 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>