]> granicus.if.org Git - php/commitdiff
Split header reading in 32bit and 64bit variants.
authorDerick Rethans <github@derickrethans.nl>
Tue, 28 Apr 2015 23:08:28 +0000 (00:08 +0100)
committerDerick Rethans <github@derickrethans.nl>
Tue, 28 Apr 2015 23:08:28 +0000 (00:08 +0100)
We need to use the 64bit header for the second set of transitions, as there
could be a different amount of transitions. This also opens up the way towards
real 64bit support.

ext/date/lib/parse_tz.c
ext/date/lib/timelib.c
ext/date/lib/timelib_structs.h

index db29495a85aa5f39f21926d9fbbb6ed1a264f8b9..8a48fadb6330aff4c834cb54a17797693da81380 100644 (file)
@@ -77,20 +77,20 @@ static void read_header(const unsigned char **tzf, timelib_tzinfo *tz)
        uint32_t buffer[6];
 
        memcpy(&buffer, *tzf, sizeof(buffer));
-       tz->ttisgmtcnt = timelib_conv_int(buffer[0]);
-       tz->ttisstdcnt = timelib_conv_int(buffer[1]);
-       tz->leapcnt    = timelib_conv_int(buffer[2]);
-       tz->timecnt    = timelib_conv_int(buffer[3]);
-       tz->typecnt    = timelib_conv_int(buffer[4]);
-       tz->charcnt    = timelib_conv_int(buffer[5]);
+       tz->bit32.ttisgmtcnt = timelib_conv_int(buffer[0]);
+       tz->bit32.ttisstdcnt = timelib_conv_int(buffer[1]);
+       tz->bit32.leapcnt    = timelib_conv_int(buffer[2]);
+       tz->bit32.timecnt    = timelib_conv_int(buffer[3]);
+       tz->bit32.typecnt    = timelib_conv_int(buffer[4]);
+       tz->bit32.charcnt    = timelib_conv_int(buffer[5]);
        *tzf += sizeof(buffer);
 }
 
-static void skip_transistions_64bit(const unsigned char **tzf, timelib_tzinfo *tz)
+static void skip_64bit_transistions(const unsigned char **tzf, timelib_tzinfo *tz)
 {
-       if (tz->timecnt) {
-               *tzf += (sizeof(int64_t) * (tz->timecnt + 1));
-               *tzf += (sizeof(unsigned char) * (tz->timecnt + 1));
+       if (tz->bit64.timecnt) {
+               *tzf += (sizeof(int64_t) * tz->bit64.timecnt);
+               *tzf += (sizeof(unsigned char) * tz->bit64.timecnt);
        }
 }
 
@@ -100,42 +100,42 @@ static void read_transistions(const unsigned char **tzf, timelib_tzinfo *tz)
        uint32_t i;
        unsigned char *cbuffer = NULL;
 
-       if (tz->timecnt) {
-               buffer = (int32_t*) malloc(tz->timecnt * sizeof(int32_t));
+       if (tz->bit32.timecnt) {
+               buffer = (int32_t*) malloc(tz->bit32.timecnt * sizeof(int32_t));
                if (!buffer) {
                        return;
                }
-               memcpy(buffer, *tzf, sizeof(int32_t) * tz->timecnt);
-               *tzf += (sizeof(int32_t) * tz->timecnt);
-               for (i = 0; i < tz->timecnt; i++) {
+               memcpy(buffer, *tzf, sizeof(int32_t) * tz->bit32.timecnt);
+               *tzf += (sizeof(int32_t) * tz->bit32.timecnt);
+               for (i = 0; i < tz->bit32.timecnt; i++) {
                        buffer[i] = timelib_conv_int(buffer[i]);
                }
 
-               cbuffer = (unsigned char*) malloc(tz->timecnt * sizeof(unsigned char));
+               cbuffer = (unsigned char*) malloc(tz->bit32.timecnt * sizeof(unsigned char));
                if (!cbuffer) {
                        free(buffer);
                        return;
                }
-               memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->timecnt);
-               *tzf += sizeof(unsigned char) * tz->timecnt;
+               memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->bit32.timecnt);
+               *tzf += sizeof(unsigned char) * tz->bit32.timecnt;
        }
 
        tz->trans = buffer;
        tz->trans_idx = cbuffer;
 }
 
-static void skip_types_64bit(const unsigned char **tzf, timelib_tzinfo *tz)
+static void skip_64bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
 {
-       *tzf += sizeof(unsigned char) * 6 * tz->typecnt;
-       *tzf += sizeof(char) * tz->charcnt;
-       if (tz->leapcnt) {
-               *tzf += sizeof(int64_t) * tz->leapcnt * 2;
+       *tzf += sizeof(unsigned char) * 6 * tz->bit64.typecnt;
+       *tzf += sizeof(char) * tz->bit64.charcnt;
+       if (tz->bit64.leapcnt) {
+               *tzf += sizeof(int64_t) * tz->bit64.leapcnt * 2;
        }
-       if (tz->ttisstdcnt) {
-               *tzf += sizeof(unsigned char) * tz->ttisstdcnt;
+       if (tz->bit64.ttisstdcnt) {
+               *tzf += sizeof(unsigned char) * tz->bit64.ttisstdcnt;
        }
-       if (tz->ttisgmtcnt) {
-               *tzf += sizeof(unsigned char) * tz->ttisgmtcnt;
+       if (tz->bit64.ttisgmtcnt) {
+               *tzf += sizeof(unsigned char) * tz->bit64.ttisgmtcnt;
        }
 }
 
@@ -145,20 +145,20 @@ static void read_types(const unsigned char **tzf, timelib_tzinfo *tz)
        int32_t *leap_buffer;
        unsigned int i, j;
 
-       buffer = (unsigned char*) malloc(tz->typecnt * sizeof(unsigned char) * 6);
+       buffer = (unsigned char*) malloc(tz->bit32.typecnt * sizeof(unsigned char) * 6);
        if (!buffer) {
                return;
        }
-       memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->typecnt);
-       *tzf += sizeof(unsigned char) * 6 * tz->typecnt;
+       memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->bit32.typecnt);
+       *tzf += sizeof(unsigned char) * 6 * tz->bit32.typecnt;
 
-       tz->type = (ttinfo*) malloc(tz->typecnt * sizeof(struct ttinfo));
+       tz->type = (ttinfo*) malloc(tz->bit32.typecnt * sizeof(struct ttinfo));
        if (!tz->type) {
                free(buffer);
                return;
        }
 
-       for (i = 0; i < tz->typecnt; i++) {
+       for (i = 0; i < tz->bit32.typecnt; i++) {
                j = i * 6;
                tz->type[i].offset = (buffer[j] * 16777216) + (buffer[j + 1] * 65536) + (buffer[j + 2] * 256) + buffer[j + 3];
                tz->type[i].isdst = buffer[j + 4];
@@ -166,56 +166,56 @@ static void read_types(const unsigned char **tzf, timelib_tzinfo *tz)
        }
        free(buffer);
 
-       tz->timezone_abbr = (char*) malloc(tz->charcnt);
+       tz->timezone_abbr = (char*) malloc(tz->bit32.charcnt);
        if (!tz->timezone_abbr) {
                return;
        }
-       memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->charcnt);
-       *tzf += sizeof(char) * tz->charcnt;
+       memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->bit32.charcnt);
+       *tzf += sizeof(char) * tz->bit32.charcnt;
 
-       if (tz->leapcnt) {
-               leap_buffer = (int32_t *) malloc(tz->leapcnt * 2 * sizeof(int32_t));
+       if (tz->bit32.leapcnt) {
+               leap_buffer = (int32_t *) malloc(tz->bit32.leapcnt * 2 * sizeof(int32_t));
                if (!leap_buffer) {
                        return;
                }
-               memcpy(leap_buffer, *tzf, sizeof(int32_t) * tz->leapcnt * 2);
-               *tzf += sizeof(int32_t) * tz->leapcnt * 2;
+               memcpy(leap_buffer, *tzf, sizeof(int32_t) * tz->bit32.leapcnt * 2);
+               *tzf += sizeof(int32_t) * tz->bit32.leapcnt * 2;
 
-               tz->leap_times = (tlinfo*) malloc(tz->leapcnt * sizeof(tlinfo));
+               tz->leap_times = (tlinfo*) malloc(tz->bit32.leapcnt * sizeof(tlinfo));
                if (!tz->leap_times) {
                        free(leap_buffer);
                        return;
                }
-               for (i = 0; i < tz->leapcnt; i++) {
+               for (i = 0; i < tz->bit32.leapcnt; i++) {
                        tz->leap_times[i].trans = timelib_conv_int(leap_buffer[i * 2]);
                        tz->leap_times[i].offset = timelib_conv_int(leap_buffer[i * 2 + 1]);
                }
                free(leap_buffer);
        }
 
-       if (tz->ttisstdcnt) {
-               buffer = (unsigned char*) malloc(tz->ttisstdcnt * sizeof(unsigned char));
+       if (tz->bit32.ttisstdcnt) {
+               buffer = (unsigned char*) malloc(tz->bit32.ttisstdcnt * sizeof(unsigned char));
                if (!buffer) {
                        return;
                }
-               memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisstdcnt);
-               *tzf += sizeof(unsigned char) * tz->ttisstdcnt;
+               memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit32.ttisstdcnt);
+               *tzf += sizeof(unsigned char) * tz->bit32.ttisstdcnt;
 
-               for (i = 0; i < tz->ttisstdcnt; i++) {
+               for (i = 0; i < tz->bit32.ttisstdcnt; i++) {
                        tz->type[i].isstdcnt = buffer[i];
                }
                free(buffer);
        }
 
-       if (tz->ttisgmtcnt) {
-               buffer = (unsigned char*) malloc(tz->ttisgmtcnt * sizeof(unsigned char));
+       if (tz->bit32.ttisgmtcnt) {
+               buffer = (unsigned char*) malloc(tz->bit32.ttisgmtcnt * sizeof(unsigned char));
                if (!buffer) {
                        return;
                }
-               memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisgmtcnt);
-               *tzf += sizeof(unsigned char) * tz->ttisgmtcnt;
+               memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit32.ttisgmtcnt);
+               *tzf += sizeof(unsigned char) * tz->bit32.ttisgmtcnt;
 
-               for (i = 0; i < tz->ttisgmtcnt; i++) {
+               for (i = 0; i < tz->bit32.ttisgmtcnt; i++) {
                        tz->type[i].isgmtcnt = buffer[i];
                }
                free(buffer);
@@ -261,12 +261,12 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz)
        printf("Geo Location:      %f,%f\n", tz->location.latitude, tz->location.longitude);
        printf("Comments:\n%s\n",          tz->location.comments);
        printf("BC:                %s\n",  tz->bc ? "" : "yes");
-       printf("UTC/Local count:   %lu\n", (unsigned long) tz->ttisgmtcnt);
-       printf("Std/Wall count:    %lu\n", (unsigned long) tz->ttisstdcnt);
-       printf("Leap.sec. count:   %lu\n", (unsigned long) tz->leapcnt);
-       printf("Trans. count:      %lu\n", (unsigned long) tz->timecnt);
-       printf("Local types count: %lu\n", (unsigned long) tz->typecnt);
-       printf("Zone Abbr. count:  %lu\n", (unsigned long) tz->charcnt);
+       printf("UTC/Local count:   " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.ttisgmtcnt);
+       printf("Std/Wall count:    " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.ttisstdcnt);
+       printf("Leap.sec. count:   " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.leapcnt);
+       printf("Trans. count:      " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.timecnt);
+       printf("Local types count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.typecnt);
+       printf("Zone Abbr. count:  " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.charcnt);
 
        printf ("%8s (%12s) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
                "", "", 0,
@@ -277,7 +277,7 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz)
                tz->type[0].isstdcnt,
                tz->type[0].isgmtcnt
                );
-       for (i = 0; i < tz->timecnt; i++) {
+       for (i = 0; i < tz->bit32.timecnt; i++) {
                printf ("%08X (%12d) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
                        tz->trans[i], tz->trans[i], tz->trans_idx[i],
                        (long int) tz->type[tz->trans_idx[i]].offset,
@@ -288,7 +288,7 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz)
                        tz->type[tz->trans_idx[i]].isgmtcnt
                        );
        }
-       for (i = 0; i < tz->leapcnt; i++) {
+       for (i = 0; i < tz->bit32.leapcnt; i++) {
                printf ("%08X (%12ld) = %d\n",
                        tz->leap_times[i].trans,
                        (long) tz->leap_times[i].trans,
@@ -352,10 +352,23 @@ int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb)
        return (seek_to_tz_position(&tzf, timezone, tzdb));
 }
 
-static void skip_2nd_header_and_data(const unsigned char **tzf, timelib_tzinfo *tz)
+static void skip_64bit_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
 {
-       *tzf += 20; /* skip 2nd header (preamble) */
-       *tzf += sizeof(int32_t) * 6; /* Counts */
+       *tzf += 20;
+}
+
+static void read_64bit_header(const unsigned char **tzf, timelib_tzinfo *tz)
+{
+       uint32_t buffer[6];
+
+       memcpy(&buffer, *tzf, sizeof(buffer));
+       tz->bit64.ttisgmtcnt = timelib_conv_int(buffer[0]);
+       tz->bit64.ttisstdcnt = timelib_conv_int(buffer[1]);
+       tz->bit64.leapcnt    = timelib_conv_int(buffer[2]);
+       tz->bit64.timecnt    = timelib_conv_int(buffer[3]);
+       tz->bit64.typecnt    = timelib_conv_int(buffer[4]);
+       tz->bit64.charcnt    = timelib_conv_int(buffer[5]);
+       *tzf += sizeof(buffer);
 }
 
 timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb)
@@ -372,9 +385,10 @@ timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb)
                read_transistions(&tzf, tmp);
                read_types(&tzf, tmp);
                if (version == 2) {
-                       skip_2nd_header_and_data(&tzf, tmp);
-                       skip_transistions_64bit(&tzf, tmp);
-                       skip_types_64bit(&tzf, tmp);
+                       skip_64bit_preamble(&tzf, tmp);
+                       read_64bit_header(&tzf, tmp);
+                       skip_64bit_transistions(&tzf, tmp);
+                       skip_64bit_types(&tzf, tmp);
                        skip_posix_string(&tzf, tmp);
                }
                read_location(&tzf, tmp);
@@ -389,18 +403,18 @@ static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib
 {
        uint32_t i;
 
-       /* If there is no transistion time, we pick the first one, if that doesn't
+       /* If there is no transition time, we pick the first one, if that doesn't
         * exist we return NULL */
-       if (!tz->timecnt || !tz->trans) {
+       if (!tz->bit32.timecnt || !tz->trans) {
                *transition_time = 0;
-               if (tz->typecnt == 1) {
+               if (tz->bit32.typecnt == 1) {
                        return &(tz->type[0]);
                }
                return NULL;
        }
 
-       /* If the TS is lower than the first transistion time, then we scan over
-        * all the transistion times to find the first non-DST one, or the first
+       /* If the TS is lower than the first transition time, then we scan over
+        * all the transition times to find the first non-DST one, or the first
         * one in case there are only DST entries. Not sure which smartass came up
         * with this idea in the first though :) */
        if (ts < tz->trans[0]) {
@@ -408,10 +422,10 @@ static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib
 
                *transition_time = 0;
                j = 0;
-               while (j < tz->timecnt && tz->type[j].isdst) {
+               while (j < tz->bit32.timecnt && tz->type[j].isdst) {
                        ++j;
                }
-               if (j == tz->timecnt) {
+               if (j == tz->bit32.timecnt) {
                        j = 0;
                }
                return &(tz->type[j]);
@@ -419,25 +433,25 @@ static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib
 
        /* In all other cases we loop through the available transtion times to find
         * the correct entry */
-       for (i = 0; i < tz->timecnt; i++) {
+       for (i = 0; i < tz->bit32.timecnt; i++) {
                if (ts < tz->trans[i]) {
                        *transition_time = tz->trans[i - 1];
                        return &(tz->type[tz->trans_idx[i - 1]]);
                }
        }
-       *transition_time = tz->trans[tz->timecnt - 1];
-       return &(tz->type[tz->trans_idx[tz->timecnt - 1]]);
+       *transition_time = tz->trans[tz->bit32.timecnt - 1];
+       return &(tz->type[tz->trans_idx[tz->bit32.timecnt - 1]]);
 }
 
 static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
 {
        int i;
 
-       if (!tz->leapcnt || !tz->leap_times) {
+       if (!tz->bit32.leapcnt || !tz->leap_times) {
                return NULL;
        }
 
-       for (i = tz->leapcnt - 1; i > 0; i--) {
+       for (i = tz->bit32.leapcnt - 1; i > 0; i--) {
                if (ts > tz->leap_times[i].trans) {
                        return &(tz->leap_times[i]);
                }
index b2da6f86c93ed6c29c236bfec0346e66fbb8c03d..b0bb699a967fa26532a3075f4e51545723d17eb7 100644 (file)
@@ -116,26 +116,26 @@ timelib_tzinfo* timelib_tzinfo_ctor(char *name)
 timelib_tzinfo *timelib_tzinfo_clone(timelib_tzinfo *tz)
 {
        timelib_tzinfo *tmp = timelib_tzinfo_ctor(tz->name);
-       tmp->ttisgmtcnt = tz->ttisgmtcnt;
-       tmp->ttisstdcnt = tz->ttisstdcnt;
-       tmp->leapcnt = tz->leapcnt;
-       tmp->timecnt = tz->timecnt;
-       tmp->typecnt = tz->typecnt;
-       tmp->charcnt = tz->charcnt;
-
-       tmp->trans = (int32_t *) malloc(tz->timecnt * sizeof(int32_t));
-       tmp->trans_idx = (unsigned char*) malloc(tz->timecnt * sizeof(unsigned char));
-       memcpy(tmp->trans, tz->trans, tz->timecnt * sizeof(int32_t));
-       memcpy(tmp->trans_idx, tz->trans_idx, tz->timecnt * sizeof(unsigned char));
-
-       tmp->type = (ttinfo*) malloc(tz->typecnt * sizeof(struct ttinfo));
-       memcpy(tmp->type, tz->type, tz->typecnt * sizeof(struct ttinfo));
-
-       tmp->timezone_abbr = (char*) malloc(tz->charcnt);
-       memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->charcnt);
-
-       tmp->leap_times = (tlinfo*) malloc(tz->leapcnt * sizeof(tlinfo));
-       memcpy(tmp->leap_times, tz->leap_times, tz->leapcnt * sizeof(tlinfo));
+       tmp->bit32.ttisgmtcnt = tz->bit32.ttisgmtcnt;
+       tmp->bit32.ttisstdcnt = tz->bit32.ttisstdcnt;
+       tmp->bit32.leapcnt = tz->bit32.leapcnt;
+       tmp->bit32.timecnt = tz->bit32.timecnt;
+       tmp->bit32.typecnt = tz->bit32.typecnt;
+       tmp->bit32.charcnt = tz->bit32.charcnt;
+
+       tmp->trans = (int32_t *) malloc(tz->bit32.timecnt * sizeof(int32_t));
+       tmp->trans_idx = (unsigned char*) malloc(tz->bit32.timecnt * sizeof(unsigned char));
+       memcpy(tmp->trans, tz->trans, tz->bit32.timecnt * sizeof(int32_t));
+       memcpy(tmp->trans_idx, tz->trans_idx, tz->bit32.timecnt * sizeof(unsigned char));
+
+       tmp->type = (ttinfo*) malloc(tz->bit32.typecnt * sizeof(struct ttinfo));
+       memcpy(tmp->type, tz->type, tz->bit32.typecnt * sizeof(struct ttinfo));
+
+       tmp->timezone_abbr = (char*) malloc(tz->bit32.charcnt);
+       memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->bit32.charcnt);
+
+       tmp->leap_times = (tlinfo*) malloc(tz->bit32.leapcnt * sizeof(tlinfo));
+       memcpy(tmp->leap_times, tz->leap_times, tz->bit32.leapcnt * sizeof(tlinfo));
 
        return tmp;
 }
index 8f36fe1ba7739a5beaa11fbce2e6aadd1f914587..f16dc4524269bc7ceaf94683314a844af0d8627f 100644 (file)
@@ -104,12 +104,22 @@ typedef struct tlocinfo
 typedef struct timelib_tzinfo
 {
        char    *name;
-       uint32_t ttisgmtcnt;
-       uint32_t ttisstdcnt;
-       uint32_t leapcnt;
-       uint32_t timecnt;
-       uint32_t typecnt;
-       uint32_t charcnt;
+       struct {
+               uint32_t ttisgmtcnt;
+               uint32_t ttisstdcnt;
+               uint32_t leapcnt;
+               uint32_t timecnt;
+               uint32_t typecnt;
+               uint32_t charcnt;
+       } bit32;
+       struct {
+               uint64_t ttisgmtcnt;
+               uint64_t ttisstdcnt;
+               uint64_t leapcnt;
+               uint64_t timecnt;
+               uint64_t typecnt;
+               uint64_t charcnt;
+       } bit64;
 
        int32_t *trans;
        unsigned char *trans_idx;