Skip to content

Commit 912e42f

Browse files
committed
Split header reading in 32bit and 64bit variants.
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.
1 parent cdd2b8a commit 912e42f

File tree

3 files changed

+127
-103
lines changed

3 files changed

+127
-103
lines changed

ext/date/lib/parse_tz.c

Lines changed: 91 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -77,20 +77,20 @@ static void read_header(const unsigned char **tzf, timelib_tzinfo *tz)
7777
uint32_t buffer[6];
7878

7979
memcpy(&buffer, *tzf, sizeof(buffer));
80-
tz->ttisgmtcnt = timelib_conv_int(buffer[0]);
81-
tz->ttisstdcnt = timelib_conv_int(buffer[1]);
82-
tz->leapcnt = timelib_conv_int(buffer[2]);
83-
tz->timecnt = timelib_conv_int(buffer[3]);
84-
tz->typecnt = timelib_conv_int(buffer[4]);
85-
tz->charcnt = timelib_conv_int(buffer[5]);
80+
tz->bit32.ttisgmtcnt = timelib_conv_int(buffer[0]);
81+
tz->bit32.ttisstdcnt = timelib_conv_int(buffer[1]);
82+
tz->bit32.leapcnt = timelib_conv_int(buffer[2]);
83+
tz->bit32.timecnt = timelib_conv_int(buffer[3]);
84+
tz->bit32.typecnt = timelib_conv_int(buffer[4]);
85+
tz->bit32.charcnt = timelib_conv_int(buffer[5]);
8686
*tzf += sizeof(buffer);
8787
}
8888

89-
static void skip_transistions_64bit(const unsigned char **tzf, timelib_tzinfo *tz)
89+
static void skip_64bit_transistions(const unsigned char **tzf, timelib_tzinfo *tz)
9090
{
91-
if (tz->timecnt) {
92-
*tzf += (sizeof(int64_t) * (tz->timecnt + 1));
93-
*tzf += (sizeof(unsigned char) * (tz->timecnt + 1));
91+
if (tz->bit64.timecnt) {
92+
*tzf += (sizeof(int64_t) * tz->bit64.timecnt);
93+
*tzf += (sizeof(unsigned char) * tz->bit64.timecnt);
9494
}
9595
}
9696

@@ -100,42 +100,42 @@ static void read_transistions(const unsigned char **tzf, timelib_tzinfo *tz)
100100
uint32_t i;
101101
unsigned char *cbuffer = NULL;
102102

103-
if (tz->timecnt) {
104-
buffer = (int32_t*) malloc(tz->timecnt * sizeof(int32_t));
103+
if (tz->bit32.timecnt) {
104+
buffer = (int32_t*) malloc(tz->bit32.timecnt * sizeof(int32_t));
105105
if (!buffer) {
106106
return;
107107
}
108-
memcpy(buffer, *tzf, sizeof(int32_t) * tz->timecnt);
109-
*tzf += (sizeof(int32_t) * tz->timecnt);
110-
for (i = 0; i < tz->timecnt; i++) {
108+
memcpy(buffer, *tzf, sizeof(int32_t) * tz->bit32.timecnt);
109+
*tzf += (sizeof(int32_t) * tz->bit32.timecnt);
110+
for (i = 0; i < tz->bit32.timecnt; i++) {
111111
buffer[i] = timelib_conv_int(buffer[i]);
112112
}
113113

114-
cbuffer = (unsigned char*) malloc(tz->timecnt * sizeof(unsigned char));
114+
cbuffer = (unsigned char*) malloc(tz->bit32.timecnt * sizeof(unsigned char));
115115
if (!cbuffer) {
116116
free(buffer);
117117
return;
118118
}
119-
memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->timecnt);
120-
*tzf += sizeof(unsigned char) * tz->timecnt;
119+
memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->bit32.timecnt);
120+
*tzf += sizeof(unsigned char) * tz->bit32.timecnt;
121121
}
122122

123123
tz->trans = buffer;
124124
tz->trans_idx = cbuffer;
125125
}
126126

127-
static void skip_types_64bit(const unsigned char **tzf, timelib_tzinfo *tz)
127+
static void skip_64bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
128128
{
129-
*tzf += sizeof(unsigned char) * 6 * tz->typecnt;
130-
*tzf += sizeof(char) * tz->charcnt;
131-
if (tz->leapcnt) {
132-
*tzf += sizeof(int64_t) * tz->leapcnt * 2;
129+
*tzf += sizeof(unsigned char) * 6 * tz->bit64.typecnt;
130+
*tzf += sizeof(char) * tz->bit64.charcnt;
131+
if (tz->bit64.leapcnt) {
132+
*tzf += sizeof(int64_t) * tz->bit64.leapcnt * 2;
133133
}
134-
if (tz->ttisstdcnt) {
135-
*tzf += sizeof(unsigned char) * tz->ttisstdcnt;
134+
if (tz->bit64.ttisstdcnt) {
135+
*tzf += sizeof(unsigned char) * tz->bit64.ttisstdcnt;
136136
}
137-
if (tz->ttisgmtcnt) {
138-
*tzf += sizeof(unsigned char) * tz->ttisgmtcnt;
137+
if (tz->bit64.ttisgmtcnt) {
138+
*tzf += sizeof(unsigned char) * tz->bit64.ttisgmtcnt;
139139
}
140140
}
141141

@@ -145,77 +145,77 @@ static void read_types(const unsigned char **tzf, timelib_tzinfo *tz)
145145
int32_t *leap_buffer;
146146
unsigned int i, j;
147147

148-
buffer = (unsigned char*) malloc(tz->typecnt * sizeof(unsigned char) * 6);
148+
buffer = (unsigned char*) malloc(tz->bit32.typecnt * sizeof(unsigned char) * 6);
149149
if (!buffer) {
150150
return;
151151
}
152-
memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->typecnt);
153-
*tzf += sizeof(unsigned char) * 6 * tz->typecnt;
152+
memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->bit32.typecnt);
153+
*tzf += sizeof(unsigned char) * 6 * tz->bit32.typecnt;
154154

155-
tz->type = (ttinfo*) malloc(tz->typecnt * sizeof(struct ttinfo));
155+
tz->type = (ttinfo*) malloc(tz->bit32.typecnt * sizeof(struct ttinfo));
156156
if (!tz->type) {
157157
free(buffer);
158158
return;
159159
}
160160

161-
for (i = 0; i < tz->typecnt; i++) {
161+
for (i = 0; i < tz->bit32.typecnt; i++) {
162162
j = i * 6;
163163
tz->type[i].offset = (buffer[j] * 16777216) + (buffer[j + 1] * 65536) + (buffer[j + 2] * 256) + buffer[j + 3];
164164
tz->type[i].isdst = buffer[j + 4];
165165
tz->type[i].abbr_idx = buffer[j + 5];
166166
}
167167
free(buffer);
168168

169-
tz->timezone_abbr = (char*) malloc(tz->charcnt);
169+
tz->timezone_abbr = (char*) malloc(tz->bit32.charcnt);
170170
if (!tz->timezone_abbr) {
171171
return;
172172
}
173-
memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->charcnt);
174-
*tzf += sizeof(char) * tz->charcnt;
173+
memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->bit32.charcnt);
174+
*tzf += sizeof(char) * tz->bit32.charcnt;
175175

176-
if (tz->leapcnt) {
177-
leap_buffer = (int32_t *) malloc(tz->leapcnt * 2 * sizeof(int32_t));
176+
if (tz->bit32.leapcnt) {
177+
leap_buffer = (int32_t *) malloc(tz->bit32.leapcnt * 2 * sizeof(int32_t));
178178
if (!leap_buffer) {
179179
return;
180180
}
181-
memcpy(leap_buffer, *tzf, sizeof(int32_t) * tz->leapcnt * 2);
182-
*tzf += sizeof(int32_t) * tz->leapcnt * 2;
181+
memcpy(leap_buffer, *tzf, sizeof(int32_t) * tz->bit32.leapcnt * 2);
182+
*tzf += sizeof(int32_t) * tz->bit32.leapcnt * 2;
183183

184-
tz->leap_times = (tlinfo*) malloc(tz->leapcnt * sizeof(tlinfo));
184+
tz->leap_times = (tlinfo*) malloc(tz->bit32.leapcnt * sizeof(tlinfo));
185185
if (!tz->leap_times) {
186186
free(leap_buffer);
187187
return;
188188
}
189-
for (i = 0; i < tz->leapcnt; i++) {
189+
for (i = 0; i < tz->bit32.leapcnt; i++) {
190190
tz->leap_times[i].trans = timelib_conv_int(leap_buffer[i * 2]);
191191
tz->leap_times[i].offset = timelib_conv_int(leap_buffer[i * 2 + 1]);
192192
}
193193
free(leap_buffer);
194194
}
195195

196-
if (tz->ttisstdcnt) {
197-
buffer = (unsigned char*) malloc(tz->ttisstdcnt * sizeof(unsigned char));
196+
if (tz->bit32.ttisstdcnt) {
197+
buffer = (unsigned char*) malloc(tz->bit32.ttisstdcnt * sizeof(unsigned char));
198198
if (!buffer) {
199199
return;
200200
}
201-
memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisstdcnt);
202-
*tzf += sizeof(unsigned char) * tz->ttisstdcnt;
201+
memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit32.ttisstdcnt);
202+
*tzf += sizeof(unsigned char) * tz->bit32.ttisstdcnt;
203203

204-
for (i = 0; i < tz->ttisstdcnt; i++) {
204+
for (i = 0; i < tz->bit32.ttisstdcnt; i++) {
205205
tz->type[i].isstdcnt = buffer[i];
206206
}
207207
free(buffer);
208208
}
209209

210-
if (tz->ttisgmtcnt) {
211-
buffer = (unsigned char*) malloc(tz->ttisgmtcnt * sizeof(unsigned char));
210+
if (tz->bit32.ttisgmtcnt) {
211+
buffer = (unsigned char*) malloc(tz->bit32.ttisgmtcnt * sizeof(unsigned char));
212212
if (!buffer) {
213213
return;
214214
}
215-
memcpy(buffer, *tzf, sizeof(unsigned char) * tz->ttisgmtcnt);
216-
*tzf += sizeof(unsigned char) * tz->ttisgmtcnt;
215+
memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit32.ttisgmtcnt);
216+
*tzf += sizeof(unsigned char) * tz->bit32.ttisgmtcnt;
217217

218-
for (i = 0; i < tz->ttisgmtcnt; i++) {
218+
for (i = 0; i < tz->bit32.ttisgmtcnt; i++) {
219219
tz->type[i].isgmtcnt = buffer[i];
220220
}
221221
free(buffer);
@@ -261,12 +261,12 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz)
261261
printf("Geo Location: %f,%f\n", tz->location.latitude, tz->location.longitude);
262262
printf("Comments:\n%s\n", tz->location.comments);
263263
printf("BC: %s\n", tz->bc ? "" : "yes");
264-
printf("UTC/Local count: %lu\n", (unsigned long) tz->ttisgmtcnt);
265-
printf("Std/Wall count: %lu\n", (unsigned long) tz->ttisstdcnt);
266-
printf("Leap.sec. count: %lu\n", (unsigned long) tz->leapcnt);
267-
printf("Trans. count: %lu\n", (unsigned long) tz->timecnt);
268-
printf("Local types count: %lu\n", (unsigned long) tz->typecnt);
269-
printf("Zone Abbr. count: %lu\n", (unsigned long) tz->charcnt);
264+
printf("UTC/Local count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.ttisgmtcnt);
265+
printf("Std/Wall count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.ttisstdcnt);
266+
printf("Leap.sec. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.leapcnt);
267+
printf("Trans. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.timecnt);
268+
printf("Local types count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.typecnt);
269+
printf("Zone Abbr. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.charcnt);
270270

271271
printf ("%8s (%12s) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
272272
"", "", 0,
@@ -277,7 +277,7 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz)
277277
tz->type[0].isstdcnt,
278278
tz->type[0].isgmtcnt
279279
);
280-
for (i = 0; i < tz->timecnt; i++) {
280+
for (i = 0; i < tz->bit32.timecnt; i++) {
281281
printf ("%08X (%12d) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
282282
tz->trans[i], tz->trans[i], tz->trans_idx[i],
283283
(long int) tz->type[tz->trans_idx[i]].offset,
@@ -288,7 +288,7 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz)
288288
tz->type[tz->trans_idx[i]].isgmtcnt
289289
);
290290
}
291-
for (i = 0; i < tz->leapcnt; i++) {
291+
for (i = 0; i < tz->bit32.leapcnt; i++) {
292292
printf ("%08X (%12ld) = %d\n",
293293
tz->leap_times[i].trans,
294294
(long) tz->leap_times[i].trans,
@@ -352,10 +352,23 @@ int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb)
352352
return (seek_to_tz_position(&tzf, timezone, tzdb));
353353
}
354354

355-
static void skip_2nd_header_and_data(const unsigned char **tzf, timelib_tzinfo *tz)
355+
static void skip_64bit_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
356356
{
357-
*tzf += 20; /* skip 2nd header (preamble) */
358-
*tzf += sizeof(int32_t) * 6; /* Counts */
357+
*tzf += 20;
358+
}
359+
360+
static void read_64bit_header(const unsigned char **tzf, timelib_tzinfo *tz)
361+
{
362+
uint32_t buffer[6];
363+
364+
memcpy(&buffer, *tzf, sizeof(buffer));
365+
tz->bit64.ttisgmtcnt = timelib_conv_int(buffer[0]);
366+
tz->bit64.ttisstdcnt = timelib_conv_int(buffer[1]);
367+
tz->bit64.leapcnt = timelib_conv_int(buffer[2]);
368+
tz->bit64.timecnt = timelib_conv_int(buffer[3]);
369+
tz->bit64.typecnt = timelib_conv_int(buffer[4]);
370+
tz->bit64.charcnt = timelib_conv_int(buffer[5]);
371+
*tzf += sizeof(buffer);
359372
}
360373

361374
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)
372385
read_transistions(&tzf, tmp);
373386
read_types(&tzf, tmp);
374387
if (version == 2) {
375-
skip_2nd_header_and_data(&tzf, tmp);
376-
skip_transistions_64bit(&tzf, tmp);
377-
skip_types_64bit(&tzf, tmp);
388+
skip_64bit_preamble(&tzf, tmp);
389+
read_64bit_header(&tzf, tmp);
390+
skip_64bit_transistions(&tzf, tmp);
391+
skip_64bit_types(&tzf, tmp);
378392
skip_posix_string(&tzf, tmp);
379393
}
380394
read_location(&tzf, tmp);
@@ -389,55 +403,55 @@ static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib
389403
{
390404
uint32_t i;
391405

392-
/* If there is no transistion time, we pick the first one, if that doesn't
406+
/* If there is no transition time, we pick the first one, if that doesn't
393407
* exist we return NULL */
394-
if (!tz->timecnt || !tz->trans) {
408+
if (!tz->bit32.timecnt || !tz->trans) {
395409
*transition_time = 0;
396-
if (tz->typecnt == 1) {
410+
if (tz->bit32.typecnt == 1) {
397411
return &(tz->type[0]);
398412
}
399413
return NULL;
400414
}
401415

402-
/* If the TS is lower than the first transistion time, then we scan over
403-
* all the transistion times to find the first non-DST one, or the first
416+
/* If the TS is lower than the first transition time, then we scan over
417+
* all the transition times to find the first non-DST one, or the first
404418
* one in case there are only DST entries. Not sure which smartass came up
405419
* with this idea in the first though :) */
406420
if (ts < tz->trans[0]) {
407421
uint32_t j;
408422

409423
*transition_time = 0;
410424
j = 0;
411-
while (j < tz->timecnt && tz->type[j].isdst) {
425+
while (j < tz->bit32.timecnt && tz->type[j].isdst) {
412426
++j;
413427
}
414-
if (j == tz->timecnt) {
428+
if (j == tz->bit32.timecnt) {
415429
j = 0;
416430
}
417431
return &(tz->type[j]);
418432
}
419433

420434
/* In all other cases we loop through the available transtion times to find
421435
* the correct entry */
422-
for (i = 0; i < tz->timecnt; i++) {
436+
for (i = 0; i < tz->bit32.timecnt; i++) {
423437
if (ts < tz->trans[i]) {
424438
*transition_time = tz->trans[i - 1];
425439
return &(tz->type[tz->trans_idx[i - 1]]);
426440
}
427441
}
428-
*transition_time = tz->trans[tz->timecnt - 1];
429-
return &(tz->type[tz->trans_idx[tz->timecnt - 1]]);
442+
*transition_time = tz->trans[tz->bit32.timecnt - 1];
443+
return &(tz->type[tz->trans_idx[tz->bit32.timecnt - 1]]);
430444
}
431445

432446
static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
433447
{
434448
int i;
435449

436-
if (!tz->leapcnt || !tz->leap_times) {
450+
if (!tz->bit32.leapcnt || !tz->leap_times) {
437451
return NULL;
438452
}
439453

440-
for (i = tz->leapcnt - 1; i > 0; i--) {
454+
for (i = tz->bit32.leapcnt - 1; i > 0; i--) {
441455
if (ts > tz->leap_times[i].trans) {
442456
return &(tz->leap_times[i]);
443457
}

ext/date/lib/timelib.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -116,26 +116,26 @@ timelib_tzinfo* timelib_tzinfo_ctor(char *name)
116116
timelib_tzinfo *timelib_tzinfo_clone(timelib_tzinfo *tz)
117117
{
118118
timelib_tzinfo *tmp = timelib_tzinfo_ctor(tz->name);
119-
tmp->ttisgmtcnt = tz->ttisgmtcnt;
120-
tmp->ttisstdcnt = tz->ttisstdcnt;
121-
tmp->leapcnt = tz->leapcnt;
122-
tmp->timecnt = tz->timecnt;
123-
tmp->typecnt = tz->typecnt;
124-
tmp->charcnt = tz->charcnt;
125-
126-
tmp->trans = (int32_t *) malloc(tz->timecnt * sizeof(int32_t));
127-
tmp->trans_idx = (unsigned char*) malloc(tz->timecnt * sizeof(unsigned char));
128-
memcpy(tmp->trans, tz->trans, tz->timecnt * sizeof(int32_t));
129-
memcpy(tmp->trans_idx, tz->trans_idx, tz->timecnt * sizeof(unsigned char));
130-
131-
tmp->type = (ttinfo*) malloc(tz->typecnt * sizeof(struct ttinfo));
132-
memcpy(tmp->type, tz->type, tz->typecnt * sizeof(struct ttinfo));
133-
134-
tmp->timezone_abbr = (char*) malloc(tz->charcnt);
135-
memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->charcnt);
136-
137-
tmp->leap_times = (tlinfo*) malloc(tz->leapcnt * sizeof(tlinfo));
138-
memcpy(tmp->leap_times, tz->leap_times, tz->leapcnt * sizeof(tlinfo));
119+
tmp->bit32.ttisgmtcnt = tz->bit32.ttisgmtcnt;
120+
tmp->bit32.ttisstdcnt = tz->bit32.ttisstdcnt;
121+
tmp->bit32.leapcnt = tz->bit32.leapcnt;
122+
tmp->bit32.timecnt = tz->bit32.timecnt;
123+
tmp->bit32.typecnt = tz->bit32.typecnt;
124+
tmp->bit32.charcnt = tz->bit32.charcnt;
125+
126+
tmp->trans = (int32_t *) malloc(tz->bit32.timecnt * sizeof(int32_t));
127+
tmp->trans_idx = (unsigned char*) malloc(tz->bit32.timecnt * sizeof(unsigned char));
128+
memcpy(tmp->trans, tz->trans, tz->bit32.timecnt * sizeof(int32_t));
129+
memcpy(tmp->trans_idx, tz->trans_idx, tz->bit32.timecnt * sizeof(unsigned char));
130+
131+
tmp->type = (ttinfo*) malloc(tz->bit32.typecnt * sizeof(struct ttinfo));
132+
memcpy(tmp->type, tz->type, tz->bit32.typecnt * sizeof(struct ttinfo));
133+
134+
tmp->timezone_abbr = (char*) malloc(tz->bit32.charcnt);
135+
memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->bit32.charcnt);
136+
137+
tmp->leap_times = (tlinfo*) malloc(tz->bit32.leapcnt * sizeof(tlinfo));
138+
memcpy(tmp->leap_times, tz->leap_times, tz->bit32.leapcnt * sizeof(tlinfo));
139139

140140
return tmp;
141141
}

0 commit comments

Comments
 (0)