LTP GCOV extension - code coverage report
Current view: directory - ext/date/lib - parse_tz.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 182
Code covered: 65.9 % Executed lines: 120
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2007 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,v 1.20.2.6.2.12 2007/01/25 14:38:45 tony2001 Exp $ */
      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                 : #ifdef WORDS_BIGENDIAN
      37                 : #define timelib_conv_int(l) (l)
      38                 : #else
      39                 : #define timelib_conv_int(l) ((l & 0x000000ff) << 24) + ((l & 0x0000ff00) << 8) + ((l & 0x00ff0000) >> 8) + ((l & 0xff000000) >> 24)
      40                 : #endif
      41                 : 
      42                 : static void read_header(char **tzf, timelib_tzinfo *tz)
      43               2 : {
      44                 :         uint32_t buffer[6];
      45                 : 
      46               2 :         memcpy(&buffer, *tzf, sizeof(buffer));
      47               2 :         tz->ttisgmtcnt = timelib_conv_int(buffer[0]);
      48               2 :         tz->ttisstdcnt = timelib_conv_int(buffer[1]);
      49               2 :         tz->leapcnt    = timelib_conv_int(buffer[2]);
      50               2 :         tz->timecnt    = timelib_conv_int(buffer[3]);
      51               2 :         tz->typecnt    = timelib_conv_int(buffer[4]);
      52               2 :         tz->charcnt    = timelib_conv_int(buffer[5]);
      53               2 :         *tzf += sizeof(buffer);
      54               2 : }
      55                 : 
      56                 : static void read_transistions(char **tzf, timelib_tzinfo *tz)
      57               2 : {
      58               2 :         int32_t *buffer = NULL;
      59                 :         uint32_t i;
      60               2 :         unsigned char *cbuffer = NULL;
      61                 : 
      62               2 :         if (tz->timecnt) {
      63               1 :                 buffer = (int32_t*) malloc(tz->timecnt * sizeof(int32_t));
      64               1 :                 if (!buffer) {
      65               0 :                         return;
      66                 :                 }
      67               1 :                 memcpy(buffer, *tzf, sizeof(int32_t) * tz->timecnt);
      68               1 :                 *tzf += (sizeof(int32_t) * tz->timecnt);
      69             144 :                 for (i = 0; i < tz->timecnt; i++) {
      70             143 :                         buffer[i] = timelib_conv_int(buffer[i]);
      71                 :                 }
      72                 : 
      73               1 :                 cbuffer = (unsigned char*) malloc(tz->timecnt * sizeof(unsigned char));
      74               1 :                 if (!cbuffer) {
      75               0 :                         return;
      76                 :                 }
      77               1 :                 memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->timecnt);
      78               1 :                 *tzf += sizeof(unsigned char) * tz->timecnt;
      79                 :         }
      80                 :         
      81               2 :         tz->trans = buffer;
      82               2 :         tz->trans_idx = cbuffer;
      83                 : }
      84                 : 
      85                 : static void read_types(char **tzf, timelib_tzinfo *tz)
      86               2 : {
      87                 :         unsigned char *buffer;
      88                 :         int32_t *leap_buffer;
      89                 :         unsigned int i, j;
      90                 : 
      91               2 :         buffer = (unsigned char*) malloc(tz->typecnt * sizeof(unsigned char) * 6);
      92               2 :         if (!buffer) {
      93               0 :                 return;
      94                 :         }
      95               2 :         memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->typecnt);
      96               2 :         *tzf += sizeof(unsigned char) * 6 * tz->typecnt;
      97                 : 
      98               2 :         tz->type = (ttinfo*) malloc(tz->typecnt * sizeof(struct ttinfo));
      99               2 :         if (!tz->type) {
     100               0 :                 return;
     101                 :         }
     102                 : 
     103              11 :         for (i = 0; i < tz->typecnt; i++) {
     104               9 :                 j = i * 6;
     105               9 :                 tz->type[i].offset = (buffer[j] * 16777216) + (buffer[j + 1] * 65536) + (buffer[j + 2] * 256) + buffer[j + 3];
     106               9 :                 tz->type[i].isdst = buffer[j + 4];
     107               9 :                 tz->type[i].abbr_idx = buffer[j + 5];
     108                 :         }
     109               2 :         free(buffer);
     110                 : 
     111               2 :         tz->timezone_abbr = (char*) malloc(tz->charcnt);
     112               2 :         if (!tz->timezone_abbr) {
     113               0 :                 return;
     114                 :         }
     115               2 :         memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->charcnt);
     116               2 :         *tzf += sizeof(char) * tz->charcnt;
     117                 : 
     118               2 :         leap_buffer = (int32_t *) malloc(tz->leapcnt * 2 * sizeof(int32_t));
     119               2 :         if (!leap_buffer) {
     120               0 :                 return;
     121                 :         }
     122               2 :         memcpy(leap_buffer, *tzf, sizeof(int32_t) * tz->leapcnt * 2);
     123               2 :         *tzf += sizeof(int32_t) * tz->leapcnt * 2;
     124                 : 
     125               2 :         tz->leap_times = (tlinfo*) malloc(tz->leapcnt * sizeof(tlinfo));
     126               2 :         if (!tz->leap_times) {
     127               0 :                 return;
     128                 :         }
     129               2 :         for (i = 0; i < tz->leapcnt; i++) {
     130               0 :                 tz->leap_times[i].trans = timelib_conv_int(leap_buffer[i * 2]);
     131               0 :                 tz->leap_times[i].offset = timelib_conv_int(leap_buffer[i * 2 + 1]);
     132                 :         }
     133               2 :         free(leap_buffer);
     134                 :         
     135               2 :         buffer = (unsigned char*) malloc(tz->ttisstdcnt * sizeof(unsigned char));
     136               2 :         if (!buffer) {
     137               0 :                 return;
     138                 :         }
     139               2 :         memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisstdcnt);
     140               2 :         *tzf += sizeof(unsigned char) * tz->ttisstdcnt;
     141                 : 
     142              11 :         for (i = 0; i < tz->ttisstdcnt; i++) {
     143               9 :                 tz->type[i].isstdcnt = buffer[i];
     144                 :         }
     145               2 :         free(buffer);
     146                 : 
     147               2 :         buffer = (unsigned char*) malloc(tz->ttisgmtcnt * sizeof(unsigned char));
     148               2 :         if (!buffer) {
     149               0 :                 return;
     150                 :         }
     151               2 :         memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisgmtcnt);
     152               2 :         *tzf += sizeof(unsigned char) * tz->ttisgmtcnt;
     153                 : 
     154              11 :         for (i = 0; i < tz->ttisgmtcnt; i++) {
     155               9 :                 tz->type[i].isgmtcnt = buffer[i];
     156                 :         }
     157               2 :         free(buffer);
     158                 : }
     159                 : 
     160                 : void timelib_dump_tzinfo(timelib_tzinfo *tz)
     161               0 : {
     162                 :         uint32_t i;
     163                 : 
     164               0 :         printf("UTC/Local count:   %lu\n", (unsigned long) tz->ttisgmtcnt);
     165               0 :         printf("Std/Wall count:    %lu\n", (unsigned long) tz->ttisstdcnt);
     166               0 :         printf("Leap.sec. count:   %lu\n", (unsigned long) tz->leapcnt);
     167               0 :         printf("Trans. count:      %lu\n", (unsigned long) tz->timecnt);
     168               0 :         printf("Local types count: %lu\n", (unsigned long) tz->typecnt);
     169               0 :         printf("Zone Abbr. count:  %lu\n", (unsigned long) tz->charcnt);
     170                 : 
     171               0 :         printf ("%8s (%12s) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
     172                 :                 "", "", 0,
     173                 :                 (long int) tz->type[0].offset,
     174                 :                 tz->type[0].isdst,
     175                 :                 tz->type[0].abbr_idx,
     176                 :                 &tz->timezone_abbr[tz->type[0].abbr_idx],
     177                 :                 tz->type[0].isstdcnt,
     178                 :                 tz->type[0].isgmtcnt
     179                 :                 );
     180               0 :         for (i = 0; i < tz->timecnt; i++) {
     181               0 :                 printf ("%08X (%12d) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
     182                 :                         tz->trans[i], tz->trans[i], tz->trans_idx[i],
     183                 :                         (long int) tz->type[tz->trans_idx[i]].offset,
     184                 :                         tz->type[tz->trans_idx[i]].isdst,
     185                 :                         tz->type[tz->trans_idx[i]].abbr_idx,
     186                 :                         &tz->timezone_abbr[tz->type[tz->trans_idx[i]].abbr_idx],
     187                 :                         tz->type[tz->trans_idx[i]].isstdcnt,
     188                 :                         tz->type[tz->trans_idx[i]].isgmtcnt
     189                 :                         );
     190                 :         }
     191               0 :         for (i = 0; i < tz->leapcnt; i++) {
     192               0 :                 printf ("%08X (%12ld) = %d\n",
     193                 :                         tz->leap_times[i].trans,
     194                 :                         (long) tz->leap_times[i].trans,
     195                 :                         tz->leap_times[i].offset);
     196                 :         }
     197               0 : }
     198                 : 
     199                 : static int seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb)
     200               3 : {
     201               3 :         int left = 0, right = tzdb->index_size - 1;
     202                 : #ifdef HAVE_SETLOCALE
     203               3 :         char *cur_locale = NULL, *tmp;
     204                 : 
     205               3 :         tmp = setlocale(LC_CTYPE, NULL);
     206               3 :         if (tmp) {
     207               3 :                 cur_locale = strdup(tmp);
     208                 :         }
     209               3 :         setlocale(LC_CTYPE, "C");
     210                 : #endif  
     211                 : 
     212                 :         do {
     213              28 :                 int mid = ((unsigned)left + right) >> 1;
     214              28 :                 int cmp = strcasecmp(timezone, tzdb->index[mid].id);
     215                 : 
     216              28 :                 if (cmp < 0) {
     217              10 :                         right = mid - 1;
     218              18 :                 } else if (cmp > 0) {
     219              15 :                         left = mid + 1;
     220                 :                 } else { /* (cmp == 0) */
     221               3 :                         (*tzf) = &(tzdb->data[tzdb->index[mid].pos + 20]);
     222                 : #ifdef HAVE_SETLOCALE
     223               3 :                         setlocale(LC_CTYPE, cur_locale);
     224               3 :                         if (cur_locale) free(cur_locale);
     225                 : #endif  
     226               3 :                         return 1;
     227                 :                 }
     228                 : 
     229              25 :         } while (left <= right);
     230                 : 
     231                 : #ifdef HAVE_SETLOCALE
     232               0 :         setlocale(LC_CTYPE, cur_locale);
     233               0 :         if (cur_locale) free(cur_locale);
     234                 : #endif  
     235               0 :         return 0;
     236                 : }
     237                 : 
     238                 : const timelib_tzdb *timelib_builtin_db(void)
     239               5 : {
     240               5 :         return &timezonedb_builtin;
     241                 : }
     242                 : 
     243                 : const timelib_tzdb_index_entry *timelib_timezone_builtin_identifiers_list(int *count)
     244               0 : {
     245               0 :         *count = sizeof(timezonedb_idx_builtin) / sizeof(*timezonedb_idx_builtin);
     246               0 :         return timezonedb_idx_builtin;
     247                 : }
     248                 : 
     249                 : int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb)
     250               1 : {
     251                 :         const unsigned char *tzf;
     252               1 :         return (seek_to_tz_position(&tzf, timezone, tzdb));
     253                 : }
     254                 : 
     255                 : timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb)
     256               2 : {
     257                 :         const unsigned char *tzf;
     258                 :         timelib_tzinfo *tmp;
     259                 : 
     260               2 :         if (seek_to_tz_position(&tzf, timezone, tzdb)) {
     261               2 :                 tmp = timelib_tzinfo_ctor(timezone);
     262                 : 
     263               2 :                 read_header((char**) &tzf, tmp);
     264               2 :                 read_transistions((char**) &tzf, tmp);
     265               2 :                 read_types((char**) &tzf, tmp);
     266                 :         } else {
     267               0 :                 tmp = NULL;
     268                 :         }
     269                 : 
     270               2 :         return tmp;
     271                 : }
     272                 : 
     273                 : static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib_sll *transition_time)
     274               3 : {
     275                 :         uint32_t i;
     276                 : 
     277                 :         /* If there is no transistion time, we pick the first one, if that doesn't
     278                 :          * exist we return NULL */
     279               3 :         if (!tz->timecnt || !tz->trans) {
     280               1 :                 *transition_time = 0;
     281               1 :                 if (tz->typecnt == 1) {
     282               1 :                         return &(tz->type[0]);
     283                 :                 }
     284               0 :                 return NULL;
     285                 :         }
     286                 : 
     287                 :         /* If the TS is lower than the first transistion time, then we scan over
     288                 :          * all the transistion times to find the first non-DST one, or the first
     289                 :          * one in case there are only DST entries. Not sure which smartass came up
     290                 :          * with this idea in the first though :) */
     291               2 :         if (ts < tz->trans[0]) {
     292                 :                 uint32_t j;
     293                 : 
     294               0 :                 *transition_time = 0;
     295               0 :                 j = 0;
     296               0 :                 while (j < tz->timecnt && tz->type[j].isdst) {
     297               0 :                         ++j;
     298                 :                 }
     299               0 :                 if (j == tz->timecnt) {
     300               0 :                         j = 0;
     301                 :                 }
     302               0 :                 return &(tz->type[j]);
     303                 :         }
     304                 : 
     305                 :         /* In all other cases we loop through the available transtion times to find
     306                 :          * the correct entry */
     307             166 :         for (i = 0; i < tz->timecnt; i++) {
     308             166 :                 if (ts < tz->trans[i]) {
     309               2 :                         *transition_time = tz->trans[i - 1];
     310               2 :                         return &(tz->type[tz->trans_idx[i - 1]]);
     311                 :                 }
     312                 :         }
     313               0 :         *transition_time = tz->trans[tz->timecnt - 1];
     314               0 :         return &(tz->type[tz->trans_idx[tz->timecnt - 1]]);
     315                 : }
     316                 : 
     317                 : static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
     318               3 : {
     319                 :         int i;
     320                 : 
     321               3 :         if (!tz->leapcnt || !tz->leap_times) {
     322               3 :                 return NULL;
     323                 :         }
     324                 : 
     325               0 :         for (i = tz->leapcnt - 1; i > 0; i--) {
     326               0 :                 if (ts > tz->leap_times[i].trans) {
     327               0 :                         return &(tz->leap_times[i]);
     328                 :                 }
     329                 :         }
     330               0 :         return NULL;
     331                 : }
     332                 : 
     333                 : int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz)
     334               0 : {
     335                 :         ttinfo *to;
     336                 :         timelib_sll dummy;
     337                 :         
     338               0 :         if ((to = fetch_timezone_offset(tz, ts, &dummy))) {
     339               0 :                 return to->isdst;
     340                 :         }
     341               0 :         return -1;
     342                 : }
     343                 : 
     344                 : timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz)
     345               3 : {
     346                 :         ttinfo *to;
     347                 :         tlinfo *tl;
     348               3 :         int32_t offset = 0, leap_secs = 0;
     349                 :         char *abbr;
     350               3 :         timelib_time_offset *tmp = timelib_time_offset_ctor();
     351                 :         timelib_sll                transistion_time;
     352                 : 
     353               3 :         if ((to = fetch_timezone_offset(tz, ts, &transistion_time))) {
     354               3 :                 offset = to->offset;
     355               3 :                 abbr = &(tz->timezone_abbr[to->abbr_idx]);
     356               3 :                 tmp->is_dst = to->isdst;
     357               3 :                 tmp->transistion_time = transistion_time;
     358                 :         } else {
     359               0 :                 offset = 0;
     360               0 :                 abbr = tz->timezone_abbr;
     361               0 :                 tmp->is_dst = 0;
     362               0 :                 tmp->transistion_time = 0;
     363                 :         }
     364                 : 
     365               3 :         if ((tl = fetch_leaptime_offset(tz, ts))) {
     366               0 :                 leap_secs = -tl->offset;
     367                 :         }
     368                 : 
     369               3 :         tmp->offset = offset;
     370               3 :         tmp->leap_secs = leap_secs;
     371               3 :         tmp->abbr = abbr ? strdup(abbr) : strdup("GMT");
     372                 : 
     373               3 :         return tmp;
     374                 : }
     375                 : 
     376                 : timelib_sll timelib_get_current_offset(timelib_time *t)
     377               0 : {
     378                 :         timelib_time_offset *gmt_offset;
     379                 :         timelib_sll retval;
     380                 :                         
     381               0 :         switch (t->zone_type) {
     382                 :                 case TIMELIB_ZONETYPE_ABBR:
     383                 :                 case TIMELIB_ZONETYPE_OFFSET:
     384               0 :                         return t->z * 60;
     385                 :                         
     386                 :                 case TIMELIB_ZONETYPE_ID:
     387               0 :                         gmt_offset = timelib_get_time_zone_info(t->sse, t->tz_info);
     388               0 :                         retval = gmt_offset->offset;
     389               0 :                         timelib_time_offset_dtor(gmt_offset);
     390               0 :                         return retval;
     391                 : 
     392                 :                 default:
     393               0 :                         return 0;
     394                 :         }
     395                 : }

Generated by: LTP GCOV extension version 1.5