1999-12-02 02:30:44 +00:00
|
|
|
/*
|
|
|
|
**********************************************************************
|
2001-03-21 20:31:13 +00:00
|
|
|
* Copyright (C) 1999-2001, International Business Machines
|
1999-12-02 02:30:44 +00:00
|
|
|
* Corporation and others. All Rights Reserved.
|
|
|
|
**********************************************************************
|
|
|
|
* Date Name Description
|
|
|
|
* 11/24/99 aliu Creation.
|
1999-12-14 00:43:47 +00:00
|
|
|
* 12/13/1999 srl Padded OffsetIndex to 4 byte values
|
2001-02-02 19:26:56 +00:00
|
|
|
* 02/01/01 aliu Added country index
|
1999-12-02 02:30:44 +00:00
|
|
|
**********************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef TZDAT_H
|
|
|
|
#define TZDAT_H
|
|
|
|
|
1999-12-28 23:57:50 +00:00
|
|
|
#include "unicode/utypes.h"
|
1999-12-02 02:30:44 +00:00
|
|
|
|
|
|
|
/* This file defines the format of the memory-mapped data file
|
|
|
|
* containing system time zone data for icu. See also gentz
|
|
|
|
* and tz.pl.
|
1999-12-05 06:09:44 +00:00
|
|
|
*
|
|
|
|
* The format is designed specifically to allow certain operations:
|
|
|
|
*
|
|
|
|
* 1. Performing a fast binary search by name, and locating the
|
|
|
|
* corresponding zone data. This is the most important operation.
|
|
|
|
* It corresponds to the TimeZone::createTimeZone() method.
|
|
|
|
*
|
|
|
|
* 2. Performing a fast iteration over zones having a specific GMT
|
|
|
|
* offset. For this operation, the zone data need not be
|
|
|
|
* retrieved, just the IDs. This corresponds to the
|
|
|
|
* TimeZone::createAvailableIDs(int32_t) method.
|
|
|
|
*
|
|
|
|
* 3. Iterating over all zone IDs. This corresponds to the
|
|
|
|
* TimeZone::createAvailableIDs() method.
|
|
|
|
*
|
|
|
|
* The createAvailableIDs() methods return arrays of pointers to
|
|
|
|
* existing static UnicodeString IDs that it owns. Thus
|
|
|
|
* createAvailableIDs() needs a way to reference one of these IDs when
|
|
|
|
* iterating. Note that these IDs are _not_ stored in the
|
|
|
|
* memory-mapped data file, so we cannot store offsets. To solve this
|
|
|
|
* problem, we define a canonical index number for each zone. This
|
|
|
|
* index number runs from 0..n-1, where n is the total number of
|
|
|
|
* zones. The name table is stored in index number order, and we
|
|
|
|
* provide a table that is sorted by GMT offset with keys being GMT
|
|
|
|
* offset values and values being canonical index numbers.
|
|
|
|
*
|
|
|
|
* (Later, we might change createAvailableIDs() to return char*
|
|
|
|
* strings rather than UnicodeString pointers. In that case, this
|
|
|
|
* data structure could be modified to index into the name table
|
|
|
|
* directly.)
|
|
|
|
*
|
|
|
|
* Any field with a name ending in "delta" is an offset value
|
|
|
|
* from the first byte of the TZHeader structure, unless otherwise
|
|
|
|
* specified.
|
|
|
|
*
|
|
|
|
* When using the name index table and the offset index table,
|
|
|
|
* code can determine whether an indexed zone is a standard
|
|
|
|
* zone or a DST zone by examining its delta. If the delta is
|
|
|
|
* less than dstDelta, it is a standard zone. Otherwise it
|
|
|
|
* is a DST zone.
|
1999-12-02 02:30:44 +00:00
|
|
|
*/
|
|
|
|
|
2000-09-27 16:37:26 +00:00
|
|
|
// Information used to identify and validate the data
|
|
|
|
|
|
|
|
#define TZ_DATA_NAME "tz"
|
|
|
|
#define TZ_DATA_TYPE "dat"
|
|
|
|
|
|
|
|
// Fields in UDataInfo:
|
|
|
|
|
|
|
|
// TZ_SIG[] is encoded as numeric literals for compatibility with the HP compiler
|
|
|
|
static const uint8_t TZ_SIG_0 = 0x7a; // z
|
|
|
|
static const uint8_t TZ_SIG_1 = 0x6f; // o
|
|
|
|
static const uint8_t TZ_SIG_2 = 0x6e; // n
|
|
|
|
static const uint8_t TZ_SIG_3 = 0x65; // e
|
|
|
|
|
|
|
|
// This must match the version number at the top of tz.txt as
|
|
|
|
// well as the version number in the udata header.
|
2001-02-02 19:26:56 +00:00
|
|
|
static const int8_t TZ_FORMAT_VERSION = 4; // formatVersion[0]
|
2000-09-27 16:37:26 +00:00
|
|
|
|
1999-12-02 02:30:44 +00:00
|
|
|
struct TZHeader {
|
|
|
|
uint16_t versionYear; // e.g. "1999j" -> 1999
|
|
|
|
uint16_t versionSuffix; // e.g. "1999j" -> 10
|
1999-12-05 06:09:44 +00:00
|
|
|
|
|
|
|
uint32_t count; // standardCount + dstCount
|
|
|
|
|
2000-09-27 16:37:26 +00:00
|
|
|
uint32_t equivTableDelta; // delta to equivalency group table
|
1999-12-05 06:09:44 +00:00
|
|
|
uint32_t offsetIndexDelta; // delta to gmtOffset index table
|
|
|
|
|
2001-02-02 19:26:56 +00:00
|
|
|
uint32_t countryIndexDelta; // delta to country code index table
|
|
|
|
|
2000-09-27 16:37:26 +00:00
|
|
|
uint32_t nameIndexDelta; // delta to name index table
|
|
|
|
// The name index table is an array of 'count' 32-bit offsets from
|
|
|
|
// the start of this header to equivalency group table entries.
|
|
|
|
|
|
|
|
uint32_t nameTableDelta; // delta to name (aka ID) table
|
|
|
|
// The name table contains all zone IDs, in sort order, each name
|
|
|
|
// terminated by a zero byte.
|
1999-12-02 02:30:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct StandardZone {
|
1999-12-05 06:09:44 +00:00
|
|
|
int32_t gmtOffset; // gmt offset in milliseconds
|
1999-12-02 02:30:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct TZRule {
|
|
|
|
uint8_t month; // month
|
|
|
|
int8_t dowim; // dowim
|
|
|
|
int8_t dow; // dow
|
1999-12-05 06:09:44 +00:00
|
|
|
uint16_t time; // time in minutes
|
|
|
|
int8_t mode; // (w/s/u) == TimeZone::TimeMode enum as int
|
1999-12-02 02:30:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct DSTZone {
|
1999-12-05 06:09:44 +00:00
|
|
|
int32_t gmtOffset; // gmtoffset in milliseconds
|
1999-12-02 02:30:44 +00:00
|
|
|
uint16_t dstSavings; // savings in minutes
|
|
|
|
TZRule onsetRule; // onset rule
|
|
|
|
TZRule ceaseRule; // cease rule
|
|
|
|
};
|
|
|
|
|
2000-09-27 16:37:26 +00:00
|
|
|
/**
|
|
|
|
* This variable-sized struct represents a time zone equivalency group.
|
|
|
|
* This is a set of one or more zones that are identical in GMT offset
|
|
|
|
* and rules, but differ in ID. The struct has a variable size because
|
|
|
|
* the standard zone has no rule data, and also because it contains a
|
|
|
|
* variable number of index values listing the zones in the group.
|
|
|
|
* The struct is padded to take up 4n bytes so that 4-byte integers
|
|
|
|
* within the struct stay 4-aligned (namely, the gmtOffset members of
|
|
|
|
* the zone structs).
|
|
|
|
*/
|
|
|
|
struct TZEquivalencyGroup {
|
|
|
|
uint16_t nextEntryDelta; // 0 for last entry
|
|
|
|
uint8_t isDST; // != 0 for DSTZone
|
|
|
|
uint8_t reserved;
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
StandardZone zone;
|
|
|
|
uint16_t count;
|
|
|
|
uint16_t index; // There are actually 'count' uint16_t's here
|
|
|
|
} s;
|
|
|
|
struct {
|
|
|
|
DSTZone zone;
|
|
|
|
uint16_t count;
|
|
|
|
uint16_t index; // There are actually 'count' uint16_t's here
|
|
|
|
} d;
|
|
|
|
} u;
|
|
|
|
// There may be two bytes of padding HERE to make the whole struct
|
|
|
|
// have size 4n bytes.
|
|
|
|
};
|
|
|
|
|
1999-12-05 06:09:44 +00:00
|
|
|
/**
|
|
|
|
* This variable-sized struct makes up the offset index table. To get
|
|
|
|
* from one table entry to the next, add the nextEntryDelta. If the
|
|
|
|
* nextEntryDelta is zero then this is the last entry. The offset
|
|
|
|
* index table is designed for sequential access, not random access.
|
|
|
|
* Given the small number of distinct offsets (39 in 1999j), this
|
|
|
|
* suffices.
|
1999-12-09 06:29:40 +00:00
|
|
|
*
|
|
|
|
* The value of default is the zone within this list that should be
|
|
|
|
* selected as the default zone in the absence of any other
|
|
|
|
* discriminating information. This information comes from the file
|
|
|
|
* tz.default. Note that this is itself a zone number, like
|
|
|
|
* those in the array starting at &zoneNumber.
|
1999-12-14 20:17:02 +00:00
|
|
|
*
|
|
|
|
* The gmtOffset field must be 4-aligned for some architectures. To
|
|
|
|
* ensure this, we do two things: 1. The entire struct is 4-aligned.
|
|
|
|
* 2. The gmtOffset is placed at a 4-aligned position within the
|
|
|
|
* struct. 3. The size of the whole structure is padded out to 4n
|
|
|
|
* bytes. We achieve this last condition by adding two bytes of
|
|
|
|
* padding after the last zoneNumber, if count is _even_. That is,
|
|
|
|
* the struct size is 10+2count+padding, where padding is (count%2==0
|
|
|
|
* ? 2:0). See gentz for implementation.
|
1999-12-05 06:09:44 +00:00
|
|
|
*/
|
|
|
|
struct OffsetIndex {
|
1999-12-14 20:17:02 +00:00
|
|
|
int32_t gmtOffset; // in ms - 4-aligned
|
1999-12-14 00:43:47 +00:00
|
|
|
uint16_t nextEntryDelta;
|
1999-12-09 06:29:40 +00:00
|
|
|
uint16_t defaultZone; // a zone number from 0..TZHeader.count-1
|
|
|
|
uint16_t count;
|
1999-12-05 06:09:44 +00:00
|
|
|
uint16_t zoneNumber; // There are actually 'count' uint16_t's here
|
1999-12-14 20:17:02 +00:00
|
|
|
// Following the 'count' uint16_t's starting with zoneNumber,
|
|
|
|
// there may be two bytes of padding to make the whole struct have
|
|
|
|
// a size of 4n. nextEntryDelta skips over any padding.
|
1999-12-05 06:09:44 +00:00
|
|
|
};
|
|
|
|
|
2001-02-02 19:26:56 +00:00
|
|
|
/**
|
|
|
|
* This variable-sized struct makes up the country index table. To get
|
|
|
|
* from one table entry to the next, add the nextEntryDelta. If the
|
|
|
|
* nextEntryDelta is zero then this is the last entry. The country
|
|
|
|
* index table is designed for sequential access, not random access.
|
|
|
|
*
|
|
|
|
* The intcode is an integer representation of the two-letter country
|
|
|
|
* code. It is computed as (c1-'A')*32 + (c0-'A') where the country
|
|
|
|
* code is a two-character string c1 c0, 'A' <= ci <= 'Z'.
|
|
|
|
*
|
|
|
|
* There are no 4-byte integers in this table, so we don't 4-align the
|
|
|
|
* entries.
|
|
|
|
*/
|
|
|
|
struct CountryIndex {
|
|
|
|
uint16_t intcode; // see above
|
|
|
|
uint16_t nextEntryDelta;
|
|
|
|
uint16_t count;
|
|
|
|
uint16_t zoneNumber; // There are actually 'count' uint16_t's here
|
|
|
|
};
|
|
|
|
|
1999-12-02 02:30:44 +00:00
|
|
|
#endif
|