PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/date/lib - parse_tz.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 157 232 67.7 %
Date: 2014-12-13 Functions: 13 16 81.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 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$ */
      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        1754 : static void read_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
      53             : {
      54             :         /* skip ID */
      55        1754 :         *tzf += 4;
      56             :         
      57             :         /* read BC flag */
      58        1754 :         tz->bc = (**tzf == '\1');
      59        1754 :         *tzf += 1;
      60             : 
      61             :         /* read country code */
      62        1754 :         memcpy(tz->location.country_code, *tzf, 2);
      63        1754 :         tz->location.country_code[2] = '\0';
      64        1754 :         *tzf += 2;
      65             : 
      66             :         /* skip read of preamble */
      67        1754 :         *tzf += 13;
      68        1754 : }
      69             : 
      70        1754 : static void read_header(const unsigned char **tzf, timelib_tzinfo *tz)
      71             : {
      72             :         uint32_t buffer[6];
      73             : 
      74        1754 :         memcpy(&buffer, *tzf, sizeof(buffer));
      75        1754 :         tz->ttisgmtcnt = timelib_conv_int(buffer[0]);
      76        1754 :         tz->ttisstdcnt = timelib_conv_int(buffer[1]);
      77        1754 :         tz->leapcnt    = timelib_conv_int(buffer[2]);
      78        1754 :         tz->timecnt    = timelib_conv_int(buffer[3]);
      79        1754 :         tz->typecnt    = timelib_conv_int(buffer[4]);
      80        1754 :         tz->charcnt    = timelib_conv_int(buffer[5]);
      81        1754 :         *tzf += sizeof(buffer);
      82        1754 : }
      83             : 
      84        1754 : static void read_transistions(const unsigned char **tzf, timelib_tzinfo *tz)
      85             : {
      86        1754 :         int32_t *buffer = NULL;
      87             :         uint32_t i;
      88        1754 :         unsigned char *cbuffer = NULL;
      89             : 
      90        1754 :         if (tz->timecnt) {
      91        1409 :                 buffer = (int32_t*) malloc(tz->timecnt * sizeof(int32_t));
      92        1409 :                 if (!buffer) {
      93           0 :                         return;
      94             :                 }
      95        1409 :                 memcpy(buffer, *tzf, sizeof(int32_t) * tz->timecnt);
      96        1409 :                 *tzf += (sizeof(int32_t) * tz->timecnt);
      97      149114 :                 for (i = 0; i < tz->timecnt; i++) {
      98      147705 :                         buffer[i] = timelib_conv_int(buffer[i]);
      99             :                 }
     100             : 
     101        1409 :                 cbuffer = (unsigned char*) malloc(tz->timecnt * sizeof(unsigned char));
     102        1409 :                 if (!cbuffer) {
     103           0 :                         free(buffer);
     104           0 :                         return;
     105             :                 }
     106        1409 :                 memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->timecnt);
     107        1409 :                 *tzf += sizeof(unsigned char) * tz->timecnt;
     108             :         }
     109             :         
     110        1754 :         tz->trans = buffer;
     111        1754 :         tz->trans_idx = cbuffer;
     112             : }
     113             : 
     114        1754 : 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        1754 :         buffer = (unsigned char*) malloc(tz->typecnt * sizeof(unsigned char) * 6);
     121        1754 :         if (!buffer) {
     122           0 :                 return;
     123             :         }
     124        1754 :         memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->typecnt);
     125        1754 :         *tzf += sizeof(unsigned char) * 6 * tz->typecnt;
     126             : 
     127        1754 :         tz->type = (ttinfo*) malloc(tz->typecnt * sizeof(struct ttinfo));
     128        1754 :         if (!tz->type) {
     129           0 :                 free(buffer);
     130           0 :                 return;
     131             :         }
     132             : 
     133       10060 :         for (i = 0; i < tz->typecnt; i++) {
     134        8306 :                 j = i * 6;
     135        8306 :                 tz->type[i].offset = (buffer[j] * 16777216) + (buffer[j + 1] * 65536) + (buffer[j + 2] * 256) + buffer[j + 3];
     136        8306 :                 tz->type[i].isdst = buffer[j + 4];
     137        8306 :                 tz->type[i].abbr_idx = buffer[j + 5];
     138             :         }
     139        1754 :         free(buffer);
     140             : 
     141        1754 :         tz->timezone_abbr = (char*) malloc(tz->charcnt);
     142        1754 :         if (!tz->timezone_abbr) {
     143           0 :                 return;
     144             :         }
     145        1754 :         memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->charcnt);
     146        1754 :         *tzf += sizeof(char) * tz->charcnt;
     147             : 
     148        1754 :         if (tz->leapcnt) {
     149           0 :                 leap_buffer = (int32_t *) malloc(tz->leapcnt * 2 * sizeof(int32_t));
     150           0 :                 if (!leap_buffer) {
     151           0 :                         return;
     152             :                 }
     153           0 :                 memcpy(leap_buffer, *tzf, sizeof(int32_t) * tz->leapcnt * 2);
     154           0 :                 *tzf += sizeof(int32_t) * tz->leapcnt * 2;
     155             : 
     156           0 :                 tz->leap_times = (tlinfo*) malloc(tz->leapcnt * sizeof(tlinfo));
     157           0 :                 if (!tz->leap_times) {
     158           0 :                         free(leap_buffer);
     159           0 :                         return;
     160             :                 }
     161           0 :                 for (i = 0; i < tz->leapcnt; i++) {
     162           0 :                         tz->leap_times[i].trans = timelib_conv_int(leap_buffer[i * 2]);
     163           0 :                         tz->leap_times[i].offset = timelib_conv_int(leap_buffer[i * 2 + 1]);
     164             :                 }
     165           0 :                 free(leap_buffer);
     166             :         }
     167             : 
     168        1754 :         if (tz->ttisstdcnt) {
     169        1754 :                 buffer = (unsigned char*) malloc(tz->ttisstdcnt * sizeof(unsigned char));
     170        1754 :                 if (!buffer) {
     171           0 :                         return;
     172             :                 }
     173        1754 :                 memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisstdcnt);
     174        1754 :                 *tzf += sizeof(unsigned char) * tz->ttisstdcnt;
     175             : 
     176       10060 :                 for (i = 0; i < tz->ttisstdcnt; i++) {
     177        8306 :                         tz->type[i].isstdcnt = buffer[i];
     178             :                 }
     179        1754 :                 free(buffer);
     180             :         }
     181             : 
     182        1754 :         if (tz->ttisgmtcnt) {
     183        1754 :                 buffer = (unsigned char*) malloc(tz->ttisgmtcnt * sizeof(unsigned char));
     184        1754 :                 if (!buffer) {
     185           0 :                         return;
     186             :                 }
     187        1754 :                 memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisgmtcnt);
     188        1754 :                 *tzf += sizeof(unsigned char) * tz->ttisgmtcnt;
     189             : 
     190       10060 :                 for (i = 0; i < tz->ttisgmtcnt; i++) {
     191        8306 :                         tz->type[i].isgmtcnt = buffer[i];
     192             :                 }
     193        1754 :                 free(buffer);
     194             :         }
     195             : }
     196             : 
     197        1754 : static void read_location(const unsigned char **tzf, timelib_tzinfo *tz)
     198             : {
     199             :         uint32_t buffer[3];
     200             :         uint32_t comments_len;
     201             : 
     202        1754 :         memcpy(&buffer, *tzf, sizeof(buffer));
     203        1754 :         tz->location.latitude = timelib_conv_int(buffer[0]);
     204        1754 :         tz->location.latitude = (tz->location.latitude / 100000) - 90;
     205        1754 :         tz->location.longitude = timelib_conv_int(buffer[1]);
     206        1754 :         tz->location.longitude = (tz->location.longitude / 100000) - 180;
     207        1754 :         comments_len = timelib_conv_int(buffer[2]);
     208        1754 :         *tzf += sizeof(buffer);
     209             : 
     210        1754 :         tz->location.comments = malloc(comments_len + 1);
     211        1754 :         memcpy(tz->location.comments, *tzf, comments_len);
     212        1754 :         tz->location.comments[comments_len] = '\0';
     213        1754 :         *tzf += comments_len;
     214        1754 : }
     215             : 
     216           0 : void timelib_dump_tzinfo(timelib_tzinfo *tz)
     217             : {
     218             :         uint32_t i;
     219             : 
     220           0 :         printf("Country Code:      %s\n", tz->location.country_code);
     221           0 :         printf("Geo Location:      %f,%f\n", tz->location.latitude, tz->location.longitude);
     222           0 :         printf("Comments:\n%s\n",          tz->location.comments);
     223           0 :         printf("BC:                %s\n",  tz->bc ? "" : "yes");
     224           0 :         printf("UTC/Local count:   " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->ttisgmtcnt);
     225           0 :         printf("Std/Wall count:    " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->ttisstdcnt);
     226           0 :         printf("Leap.sec. count:   " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->leapcnt);
     227           0 :         printf("Trans. count:      " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->timecnt);
     228           0 :         printf("Local types count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->typecnt);
     229           0 :         printf("Zone Abbr. count:  " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->charcnt);
     230             : 
     231           0 :         printf ("%8s (%12s) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
     232             :                 "", "", 0,
     233           0 :                 (long int) tz->type[0].offset,
     234           0 :                 tz->type[0].isdst,
     235           0 :                 tz->type[0].abbr_idx,
     236           0 :                 &tz->timezone_abbr[tz->type[0].abbr_idx],
     237           0 :                 tz->type[0].isstdcnt,
     238           0 :                 tz->type[0].isgmtcnt
     239             :                 );
     240           0 :         for (i = 0; i < tz->timecnt; i++) {
     241           0 :                 printf ("%08X (%12d) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
     242           0 :                         tz->trans[i], tz->trans[i], tz->trans_idx[i],
     243           0 :                         (long int) tz->type[tz->trans_idx[i]].offset,
     244           0 :                         tz->type[tz->trans_idx[i]].isdst,
     245           0 :                         tz->type[tz->trans_idx[i]].abbr_idx,
     246           0 :                         &tz->timezone_abbr[tz->type[tz->trans_idx[i]].abbr_idx],
     247           0 :                         tz->type[tz->trans_idx[i]].isstdcnt,
     248           0 :                         tz->type[tz->trans_idx[i]].isgmtcnt
     249             :                         );
     250             :         }
     251           0 :         for (i = 0; i < tz->leapcnt; i++) {
     252           0 :                 printf ("%08X (%12ld) = %d\n",
     253           0 :                         tz->leap_times[i].trans,
     254           0 :                         (long) tz->leap_times[i].trans,
     255           0 :                         tz->leap_times[i].offset);
     256             :         }
     257           0 : }
     258             : 
     259        2695 : static int seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb)
     260             : {
     261        2695 :         int left = 0, right = tzdb->index_size - 1;
     262             : #ifdef HAVE_SETLOCALE
     263        2695 :         char *cur_locale = NULL, *tmp;
     264             : 
     265        2695 :         tmp = setlocale(LC_CTYPE, NULL);
     266        2695 :         if (tmp) {
     267        2695 :                 cur_locale = strdup(tmp);
     268             :         }
     269        2695 :         setlocale(LC_CTYPE, "C");
     270             : #endif  
     271             : 
     272             :         do {
     273       22029 :                 int mid = ((unsigned)left + right) >> 1;
     274       22029 :                 int cmp = strcasecmp(timezone, tzdb->index[mid].id);
     275             : 
     276       22029 :                 if (cmp < 0) {
     277        8602 :                         right = mid - 1;
     278       13427 :                 } else if (cmp > 0) {
     279       10854 :                         left = mid + 1;
     280             :                 } else { /* (cmp == 0) */
     281        2573 :                         (*tzf) = &(tzdb->data[tzdb->index[mid].pos]);
     282             : #ifdef HAVE_SETLOCALE
     283        2573 :                         setlocale(LC_CTYPE, cur_locale);
     284        2573 :                         if (cur_locale) free(cur_locale);
     285             : #endif  
     286        2573 :                         return 1;
     287             :                 }
     288             : 
     289       19456 :         } while (left <= right);
     290             : 
     291             : #ifdef HAVE_SETLOCALE
     292         122 :         setlocale(LC_CTYPE, cur_locale);
     293         122 :         if (cur_locale) free(cur_locale);
     294             : #endif  
     295         122 :         return 0;
     296             : }
     297             : 
     298       37054 : const timelib_tzdb *timelib_builtin_db(void)
     299             : {
     300       37054 :         return &timezonedb_builtin;
     301             : }
     302             : 
     303           0 : const timelib_tzdb_index_entry *timelib_timezone_builtin_identifiers_list(int *count)
     304             : {
     305           0 :         *count = sizeof(timezonedb_idx_builtin) / sizeof(*timezonedb_idx_builtin);
     306           0 :         return timezonedb_idx_builtin;
     307             : }
     308             : 
     309         846 : int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb)
     310             : {
     311             :         const unsigned char *tzf;
     312         846 :         return (seek_to_tz_position(&tzf, timezone, tzdb));
     313             : }
     314             : 
     315        1849 : timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb)
     316             : {
     317             :         const unsigned char *tzf;
     318             :         timelib_tzinfo *tmp;
     319             : 
     320        1849 :         if (seek_to_tz_position(&tzf, timezone, tzdb)) {
     321        1754 :                 tmp = timelib_tzinfo_ctor(timezone);
     322             : 
     323        1754 :                 read_preamble(&tzf, tmp);
     324        1754 :                 read_header(&tzf, tmp);
     325        1754 :                 read_transistions(&tzf, tmp);
     326        1754 :                 read_types(&tzf, tmp);
     327        1754 :                 read_location(&tzf, tmp);
     328             :         } else {
     329          95 :                 tmp = NULL;
     330             :         }
     331             : 
     332        1849 :         return tmp;
     333             : }
     334             : 
     335     2322527 : 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 transition time, we pick the first one, if that doesn't
     340             :          * exist we return NULL */
     341     2322527 :         if (!tz->timecnt || !tz->trans) {
     342     2285015 :                 *transition_time = 0;
     343     2285015 :                 if (tz->typecnt == 1) {
     344     2285015 :                         return &(tz->type[0]);
     345             :                 }
     346           0 :                 return NULL;
     347             :         }
     348             : 
     349             :         /* If the TS is lower than the first transition time, then we scan over
     350             :          * all the transition 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       37512 :         if (ts < tz->trans[0]) {
     354             :                 uint32_t j;
     355             : 
     356         633 :                 *transition_time = 0;
     357         633 :                 j = 0;
     358        1786 :                 while (j < tz->timecnt && tz->type[j].isdst) {
     359         520 :                         ++j;
     360             :                 }
     361         633 :                 if (j == tz->timecnt) {
     362           0 :                         j = 0;
     363             :                 }
     364         633 :                 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     4898039 :         for (i = 0; i < tz->timecnt; i++) {
     370     4892058 :                 if (ts < tz->trans[i]) {
     371       30898 :                         *transition_time = tz->trans[i - 1];
     372       30898 :                         return &(tz->type[tz->trans_idx[i - 1]]);
     373             :                 }
     374             :         }
     375        5981 :         *transition_time = tz->trans[tz->timecnt - 1];
     376        5981 :         return &(tz->type[tz->trans_idx[tz->timecnt - 1]]);
     377             : }
     378             : 
     379     2322527 : static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
     380             : {
     381             :         int i;
     382             : 
     383     2322527 :         if (!tz->leapcnt || !tz->leap_times) {
     384     2322527 :                 return NULL;
     385             :         }
     386             : 
     387           0 :         for (i = tz->leapcnt - 1; i > 0; i--) {
     388           0 :                 if (ts > tz->leap_times[i].trans) {
     389           0 :                         return &(tz->leap_times[i]);
     390             :                 }
     391             :         }
     392           0 :         return NULL;
     393             : }
     394             : 
     395           0 : int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz)
     396             : {
     397             :         ttinfo *to;
     398             :         timelib_sll dummy;
     399             :         
     400           0 :         if ((to = fetch_timezone_offset(tz, ts, &dummy))) {
     401           0 :                 return to->isdst;
     402             :         }
     403           0 :         return -1;
     404             : }
     405             : 
     406     2322527 : timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz)
     407             : {
     408             :         ttinfo *to;
     409             :         tlinfo *tl;
     410     2322527 :         int32_t offset = 0, leap_secs = 0;
     411             :         char *abbr;
     412     2322527 :         timelib_time_offset *tmp = timelib_time_offset_ctor();
     413             :         timelib_sll                transistion_time;
     414             : 
     415     2322527 :         if ((to = fetch_timezone_offset(tz, ts, &transistion_time))) {
     416     2322527 :                 offset = to->offset;
     417     2322527 :                 abbr = &(tz->timezone_abbr[to->abbr_idx]);
     418     2322527 :                 tmp->is_dst = to->isdst;
     419     2322527 :                 tmp->transistion_time = transistion_time;
     420             :         } else {
     421           0 :                 offset = 0;
     422           0 :                 abbr = tz->timezone_abbr;
     423           0 :                 tmp->is_dst = 0;
     424           0 :                 tmp->transistion_time = 0;
     425             :         }
     426             : 
     427     2322527 :         if ((tl = fetch_leaptime_offset(tz, ts))) {
     428           0 :                 leap_secs = -tl->offset;
     429             :         }
     430             : 
     431     2322527 :         tmp->offset = offset;
     432     2322527 :         tmp->leap_secs = leap_secs;
     433     2322527 :         tmp->abbr = abbr ? strdup(abbr) : strdup("GMT");
     434             : 
     435     2322527 :         return tmp;
     436             : }
     437             : 
     438          48 : timelib_sll timelib_get_current_offset(timelib_time *t)
     439             : {
     440             :         timelib_time_offset *gmt_offset;
     441             :         timelib_sll retval;
     442             :                         
     443          48 :         switch (t->zone_type) {
     444             :                 case TIMELIB_ZONETYPE_ABBR:
     445             :                 case TIMELIB_ZONETYPE_OFFSET:
     446           0 :                         return (t->z + t->dst) * -60;
     447             :                         
     448             :                 case TIMELIB_ZONETYPE_ID:
     449          48 :                         gmt_offset = timelib_get_time_zone_info(t->sse, t->tz_info);
     450          48 :                         retval = gmt_offset->offset;
     451          48 :                         timelib_time_offset_dtor(gmt_offset);
     452          48 :                         return retval;
     453             : 
     454             :                 default:
     455           0 :                         return 0;
     456             :         }
     457             : }

Generated by: LCOV version 1.10

Generated at Sat, 13 Dec 2014 06:16:11 +0000 (9 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.