1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru********************************************************************** 450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* Copyright (c) 2003-2010, International Business Machines 5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Corporation and others. All Rights Reserved. 6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru********************************************************************** 7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Author: Alan Liu 8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Created: July 10 2003 9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Since: ICU 2.8 10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru********************************************************************** 11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "tzfile.h" // from Olson tzcode archive, copied to this dir 13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef WIN32 15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru #include <windows.h> 17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru #undef min // windows.h/STL conflict 18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru #undef max // windows.h/STL conflict 19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "identifier was truncated to 'number' characters" warning 20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru #pragma warning(disable: 4786) 21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else 23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru #include <unistd.h> 25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru #include <stdio.h> 26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru #include <dirent.h> 27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru #include <string.h> 28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru #include <sys/stat.h> 29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <algorithm> 33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <cassert> 34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <ctime> 35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <fstream> 36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <iomanip> 37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <iostream> 38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <iterator> 39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <limits> 40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <map> 41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <set> 42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <sstream> 43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <sstream> 44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdexcept> 45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <string> 46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <vector> 47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "tz2icu.h" 49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uversion.h" 50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing namespace std; 52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 5350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehobool ICU44PLUS = TRUE; 5450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostring TZ_RESOURCE_NAME = ICU_TZ_RESOURCE; 5550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Time utilities 58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int64_t SECS_PER_YEAR = 31536000; // 365 days 61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int64_t SECS_PER_LEAP_YEAR = 31622400; // 366 days 62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int64_t LOWEST_TIME32 = (int64_t)((int32_t)0x80000000); 63b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruconst int64_t HIGHEST_TIME32 = (int64_t)((int32_t)0x7fffffff); 64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querubool isLeap(int32_t y) { 66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return (y%4 == 0) && ((y%100 != 0) || (y%400 == 0)); // Gregorian 67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint64_t secsPerYear(int32_t y) { 70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return isLeap(y) ? SECS_PER_LEAP_YEAR : SECS_PER_YEAR; 71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Given a calendar year, return the GMT epoch seconds for midnight 75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * GMT of January 1 of that year. yearToSeconds(1970) == 0. 76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint64_t yearToSeconds(int32_t year) { 78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // inefficient but foolproof 79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t s = 0; 80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t y = 1970; 81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (y < year) { 82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru s += secsPerYear(y++); 83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (y > year) { 85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru s -= secsPerYear(--y); 86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return s; 88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Given 1970 GMT epoch seconds, return the calendar year containing 92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * that time. secondsToYear(0) == 1970. 93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t secondsToYear(int64_t seconds) { 95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // inefficient but foolproof 96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t y = 1970; 97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t s = 0; 98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (seconds >= 0) { 99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (;;) { 100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru s += secsPerYear(y++); 101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (s > seconds) break; 102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru --y; 104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (;;) { 106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru s -= secsPerYear(--y); 107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (s <= seconds) break; 108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return y; 111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Types 115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct FinalZone; 118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct FinalRule; 119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct SimplifiedZoneType; 120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// A transition from one ZoneType to another 122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Minimal size = 5 bytes (4+1) 123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct Transition { 124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t time; // seconds, 1970 epoch 125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t type; // index into 'ZoneInfo.types' 0..255 126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Transition(int64_t _time, int32_t _type) { 127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru time = _time; 128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru type = _type; 129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// A behavior mode (what zic calls a 'type') of a time zone. 133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Minimal size = 6 bytes (4+1+3bits) 134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// SEE: SimplifiedZoneType 135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct ZoneType { 136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t rawoffset; // raw seconds offset from GMT 137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t dstoffset; // dst seconds offset from GMT 138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We don't really need any of the following, but they are 140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // retained for possible future use. See SimplifiedZoneType. 141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t abbr; // index into ZoneInfo.abbrs 0..n-1 142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool isdst; 143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool isstd; 144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool isgmt; 145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZoneType(const SimplifiedZoneType&); // used by optimizeTypeList 147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZoneType() : rawoffset(-1), dstoffset(-1), abbr(-1) {} 149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // A restricted equality, of just the raw and dst offset 151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool matches(const ZoneType& other) { 152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return rawoffset == other.rawoffset && 153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dstoffset == other.dstoffset; 154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// A collection of transitions from one ZoneType to another, together 158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// with a list of the ZoneTypes. A ZoneInfo object may have a long 159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// list of transitions between a smaller list of ZoneTypes. 160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// This object represents the contents of a single zic-created 162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// zoneinfo file. 163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct ZoneInfo { 164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<Transition> transitions; 165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<ZoneType> types; 166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<string> abbrs; 167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string finalRuleID; 169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t finalOffset; 170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t finalYear; // -1 if none 171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If this is an alias, then all other fields are meaningless, and 173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // this field will point to the "real" zone 0..n-1. 174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t aliasTo; // -1 if this is a "real" zone 175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If there are aliases TO this zone, then the following set will 177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // contain their index numbers (each index >= 0). 178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set<int32_t> aliases; 179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZoneInfo() : finalYear(-1), aliasTo(-1) {} 181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void mergeFinalData(const FinalZone& fz); 183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void optimizeTypeList(); 185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set this zone to be an alias TO another zone. 187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void setAliasTo(int32_t index); 188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Clear the list of aliases OF this zone. 190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void clearAliases(); 191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Add an alias to the list of aliases OF this zone. 193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void addAlias(int32_t index); 194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Is this an alias to another zone? 196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool isAlias() const { 197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return aliasTo >= 0; 198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Retrieve alias list 201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const set<int32_t>& getAliases() const { 202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return aliases; 203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void print(ostream& os, const string& id) const; 206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ZoneInfo::clearAliases() { 209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(aliasTo < 0); 210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru aliases.clear(); 211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ZoneInfo::addAlias(int32_t index) { 214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(aliasTo < 0 && index >= 0 && aliases.find(index) == aliases.end()); 215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru aliases.insert(index); 216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ZoneInfo::setAliasTo(int32_t index) { 219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(index >= 0); 220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(aliases.size() == 0); 221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru aliasTo = index; 222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef map<string, ZoneInfo> ZoneMap; 225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef ZoneMap::const_iterator ZoneMapIter; 227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ZONEINFO 230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Global map holding all our ZoneInfo objects, indexed by id. 233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruZoneMap ZONEINFO; 234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// zoneinfo file parsing 237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Read zic-coded 32-bit integer from file 240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint64_t readcoded(ifstream& file, int64_t minv=numeric_limits<int64_t>::min(), 241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t maxv=numeric_limits<int64_t>::max()) { 242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru unsigned char buf[4]; // must be UNSIGNED 243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t val=0; 244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file.read((char*)buf, 4); 245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for(int32_t i=0,shift=24;i<4;++i,shift-=8) { 246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru val |= buf[i] << shift; 247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (val < minv || val > maxv) { 249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ostringstream os; 250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "coded value out-of-range: " << val << ", expected [" 251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << minv << ", " << maxv << "]"; 252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw out_of_range(os.str()); 253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return val; 255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Read zic-coded 64-bit integer from file 258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint64_t readcoded64(ifstream& file, int64_t minv=numeric_limits<int64_t>::min(), 259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t maxv=numeric_limits<int64_t>::max()) { 260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru unsigned char buf[8]; // must be UNSIGNED 261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t val=0; 262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file.read((char*)buf, 8); 263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for(int32_t i=0,shift=56;i<8;++i,shift-=8) { 264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru val |= (int64_t)buf[i] << shift; 265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (val < minv || val > maxv) { 267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ostringstream os; 268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "coded value out-of-range: " << val << ", expected [" 269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << minv << ", " << maxv << "]"; 270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw out_of_range(os.str()); 271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return val; 273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Read a boolean value 276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querubool readbool(ifstream& file) { 277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char c; 278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file.read(&c, 1); 279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (c!=0 && c!=1) { 280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ostringstream os; 281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "boolean value out-of-range: " << (int32_t)c; 282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw out_of_range(os.str()); 283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return (c!=0); 285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Read the zoneinfo file structure (see tzfile.h) into a ZoneInfo 289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param file an already-open file stream 290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 29150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid readzoneinfo(ifstream& file, ZoneInfo& info, bool is64bitData) { 292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t i; 293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check for TZ_ICU_MAGIC signature at file start. If we get a 295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // signature mismatch, it means we're trying to read a file which 296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // isn't a ICU-modified-zic-created zoneinfo file. Typically this 297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // means the user is passing in a "normal" zoneinfo directory, or 298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // a zoneinfo directory that is polluted with other files, or that 299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the user passed in the wrong directory. 300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char buf[32]; 301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file.read(buf, 4); 302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (strncmp(buf, TZ_ICU_MAGIC, 4) != 0) { 303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("TZ_ICU_MAGIC signature missing"); 304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // skip additional Olson byte version 306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file.read(buf, 1); 307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // if '\0', we have just one copy of data, if '2', there is additional 308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 64 bit version at the end. 309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(buf[0]!=0 && buf[0]!='2') { 310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("Bad Olson version info"); 311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Read reserved bytes. The first of these will be a version byte. 314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file.read(buf, 15); 315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (*(ICUZoneinfoVersion*)&buf != TZ_ICU_VERSION) { 316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("File version mismatch"); 317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Read array sizes 320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t isgmtcnt = readcoded(file, 0); 321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t isdstcnt = readcoded(file, 0); 322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t leapcnt = readcoded(file, 0); 323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t timecnt = readcoded(file, 0); 324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t typecnt = readcoded(file, 0); 325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t charcnt = readcoded(file, 0); 326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Confirm sizes that we assume to be equal. These assumptions 328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // are drawn from a reading of the zic source (2003a), so they 329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // should hold unless the zic source changes. 330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (isgmtcnt != typecnt || isdstcnt != typecnt) { 331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("count mismatch between tzh_ttisgmtcnt, tzh_ttisdstcnt, tth_typecnt"); 332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Used temporarily to store transition times and types. We need 335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to do this because the times and types are stored in two 336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // separate arrays. 337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<int64_t> transitionTimes(timecnt, -1); // temporary 338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<int32_t> transitionTypes(timecnt, -1); // temporary 339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Read transition times 341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<timecnt; ++i) { 342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (is64bitData) { 343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru transitionTimes[i] = readcoded64(file); 344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru transitionTimes[i] = readcoded(file); 346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Read transition types 350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<timecnt; ++i) { 351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru unsigned char c; 352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file.read((char*) &c, 1); 353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t t = (int32_t) c; 354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (t < 0 || t >= typecnt) { 355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ostringstream os; 356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "illegal type: " << t << ", expected [0, " << (typecnt-1) << "]"; 357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw out_of_range(os.str()); 358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru transitionTypes[i] = t; 360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Build transitions vector out of corresponding times and types. 363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool insertInitial = false; 36450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (is64bitData && !ICU44PLUS) { 365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (timecnt > 0) { 366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t minidx = -1; 367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<timecnt; ++i) { 368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (transitionTimes[i] < LOWEST_TIME32) { 369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (minidx == -1 || transitionTimes[i] > transitionTimes[minidx]) { 370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Preserve the latest transition before the 32bit minimum time 371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru minidx = i; 372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (transitionTimes[i] > HIGHEST_TIME32) { 374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Skipping the rest of the transition data. We cannot put such 375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // transitions into zoneinfo.res, because data is limited to singed 376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 32bit int by the ICU resource bundle. 377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru info.transitions.push_back(Transition(transitionTimes[i], transitionTypes[i])); 380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (minidx != -1) { 384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If there are any transitions before the 32bit minimum time, 385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // put the type information with the 32bit minimum time 386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<Transition>::iterator itr = info.transitions.begin(); 387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru info.transitions.insert(itr, Transition(LOWEST_TIME32, transitionTypes[minidx])); 388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Otherwise, we need insert the initial type later 390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru insertInitial = true; 391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<timecnt; ++i) { 395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru info.transitions.push_back(Transition(transitionTimes[i], transitionTypes[i])); 396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Read types (except for the isdst and isgmt flags, which come later (why??)) 400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<typecnt; ++i) { 401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZoneType type; 402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru type.rawoffset = readcoded(file); 404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru type.dstoffset = readcoded(file); 405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru type.isdst = readbool(file); 406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru unsigned char c; 408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file.read((char*) &c, 1); 409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru type.abbr = (int32_t) c; 410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (type.isdst != (type.dstoffset != 0)) { 412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("isdst does not reflect dstoffset"); 413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru info.types.push_back(type); 416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(info.types.size() == (unsigned) typecnt); 419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (insertInitial) { 421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(timecnt > 0); 422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(typecnt > 0); 423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t initialTypeIdx = -1; 425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check if the first type is not dst 427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (info.types.at(0).dstoffset != 0) { 428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Initial type's rawoffset is same with the rawoffset after the 429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // first transition, but no DST is observed. 430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t rawoffset0 = (info.types.at(info.transitions.at(0).type)).rawoffset; 431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Look for matching type 432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<(int32_t)info.types.size(); ++i) { 433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (info.types.at(i).rawoffset == rawoffset0 434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru && info.types.at(i).dstoffset == 0) { 435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initialTypeIdx = i; 436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 44050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho initialTypeIdx = 0; 441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(initialTypeIdx >= 0); 443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Add the initial type associated with the lowest int32 time 444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<Transition>::iterator itr = info.transitions.begin(); 445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru info.transitions.insert(itr, Transition(LOWEST_TIME32, initialTypeIdx)); 446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Read the abbreviation string 450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (charcnt) { 451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // All abbreviations are concatenated together, with a 0 at 452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the end of each abbr. 453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char* str = new char[charcnt + 8]; 454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file.read(str, charcnt); 455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Split abbreviations apart into individual strings. Record 457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // offset of each abbr in a vector. 458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<int32_t> abbroffset; 459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char *limit=str+charcnt; 460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (char* p=str; p<limit; ++p) { 461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char* start = p; 462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (*p != 0) ++p; 463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru info.abbrs.push_back(string(start, p-start)); 464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru abbroffset.push_back(start-str); 465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Remap all the abbrs. Old value is offset into concatenated 468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // raw abbr strings. New value is index into vector of 469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // strings. E.g., 0,5,10,14 => 0,1,2,3. 470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Keep track of which abbreviations get used. 472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<bool> abbrseen(abbroffset.size(), false); 473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (vector<ZoneType>::iterator it=info.types.begin(); 475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru it!=info.types.end(); 476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ++it) { 477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<int32_t>::const_iterator x= 478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru find(abbroffset.begin(), abbroffset.end(), it->abbr); 479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (x==abbroffset.end()) { 480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // TODO: Modify code to add a new string to the end of 481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the abbr list when a middle offset is given, e.g., 482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "abc*def*" where * == '\0', take offset of 1 and 483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // make the array "abc", "def", "bc", and translate 1 484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // => 2. NOT CRITICAL since we don't even use the 485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // abbr at this time. 486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if 0 487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // TODO: Re-enable this warning if we start using 488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the Olson abbr data, or if the above TODO is completed. 489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ostringstream os; 490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "Warning: unusual abbr offset " << it->abbr 491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << ", expected one of"; 492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (vector<int32_t>::const_iterator y=abbroffset.begin(); 493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru y!=abbroffset.end(); ++y) { 494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << ' ' << *y; 495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << os.str() << "; using 0" << endl; 497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru it->abbr = 0; 499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t index = x - abbroffset.begin(); 501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru it->abbr = index; 502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru abbrseen[index] = true; 503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int32_t ii=0;ii<(int32_t) abbrseen.size();++ii) { 507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!abbrseen[ii]) { 508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Warning: unused abbreviation: " << ii << endl; 509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Read leap second info, if any. 514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // *** We discard leap second data. *** 515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<leapcnt; ++i) { 516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru readcoded(file); // transition time 517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru readcoded(file); // total correction after above 518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Read isstd flags 521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<typecnt; ++i) info.types[i].isstd = readbool(file); 522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Read isgmt flags 524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<typecnt; ++i) info.types[i].isgmt = readbool(file); 525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Directory and file reading 529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Process a single zoneinfo file, adding the data to ZONEINFO 533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param path the full path to the file, e.g., ".\zoneinfo\America\Los_Angeles" 534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param id the zone ID, e.g., "America/Los_Angeles" 535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid handleFile(string path, string id) { 537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check for duplicate id 538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ZONEINFO.find(id) != ZONEINFO.end()) { 539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ostringstream os; 540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "duplicate zone ID: " << id; 541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument(os.str()); 542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ifstream file(path.c_str(), ios::in | ios::binary); 545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!file) { 546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("can't open file"); 547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 54950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // eat 32bit data part 550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZoneInfo info; 55150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho readzoneinfo(file, info, false); 552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check for errors 554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!file) { 555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("read error"); 556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 55850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // we only use 64bit part 559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZoneInfo info64; 560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru readzoneinfo(file, info64, true); 561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool alldone = false; 563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t eofPos = (int64_t) file.tellg(); 564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // '\n' + <envvar string> + '\n' after the 64bit version data 566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char ch = file.get(); 567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ch == 0x0a) { 568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool invalidchar = false; 569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (file.get(ch)) { 570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ch == 0x0a) { 571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ch < 0x20) { 574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // must be printable ascii 575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru invalidchar = true; 576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!invalidchar) { 580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru eofPos = (int64_t) file.tellg(); 581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file.seekg(0, ios::end); 582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru eofPos = eofPos - (int64_t) file.tellg(); 583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (eofPos == 0) { 584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru alldone = true; 585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!alldone) { 589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ostringstream os; 590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << (-eofPos) << " unprocessed bytes at end"; 591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument(os.str()); 592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZONEINFO[id] = info64; 595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Recursively scan the given directory, calling handleFile() for each 599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * file in the tree. The user should call with the root directory and 600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * a prefix of "". The function will call itself with non-empty 601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * prefix values. 602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef WIN32 604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid scandir(string dirname, string prefix="") { 606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru HANDLE hList; 607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru WIN32_FIND_DATA FileData; 608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the first file 610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru hList = FindFirstFile((dirname + "\\*").c_str(), &FileData); 611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (hList == INVALID_HANDLE_VALUE) { 612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: Invalid directory: " << dirname << endl; 613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(1); 614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (;;) { 616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string name(FileData.cFileName); 617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string path(dirname + "\\" + name); 618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (name != "." && name != "..") { 620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru scandir(path, prefix + name + "/"); 621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru try { 624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string id = prefix + name; 625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru handleFile(path, id); 626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } catch (const exception& e) { 627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: While processing \"" << path << "\", " 628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << e.what() << endl; 629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(1); 630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!FindNextFile(hList, &FileData)) { 634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (GetLastError() == ERROR_NO_MORE_FILES) { 635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } // else...? 637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru FindClose(hList); 640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else 643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid scandir(string dir, string prefix="") { 645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DIR *dp; 646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru struct dirent *dir_entry; 647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru struct stat stat_info; 648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char pwd[512]; 649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<string> subdirs; 650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<string> subfiles; 651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((dp = opendir(dir.c_str())) == NULL) { 653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: Invalid directory: " << dir << endl; 654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(1); 655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!getcwd(pwd, sizeof(pwd))) { 657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: Directory name too long" << endl; 658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(1); 659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru chdir(dir.c_str()); 661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while ((dir_entry = readdir(dp)) != NULL) { 662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string name = dir_entry->d_name; 663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string path = dir + "/" + name; 664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lstat(dir_entry->d_name,&stat_info); 665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (S_ISDIR(stat_info.st_mode)) { 666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (name != "." && name != "..") { 667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru subdirs.push_back(path); 668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru subdirs.push_back(prefix + name + "/"); 669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // scandir(path, prefix + name + "/"); 670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru try { 673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string id = prefix + name; 674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru subfiles.push_back(path); 675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru subfiles.push_back(id); 676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // handleFile(path, id); 677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } catch (const exception& e) { 678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: While processing \"" << path << "\", " 679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << e.what() << endl; 680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(1); 681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru closedir(dp); 685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru chdir(pwd); 686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for(int32_t i=0;i<(int32_t)subfiles.size();i+=2) { 688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru try { 689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru handleFile(subfiles[i], subfiles[i+1]); 690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } catch (const exception& e) { 691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: While processing \"" << subfiles[i] << "\", " 692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << e.what() << endl; 693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru exit(1); 694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for(int32_t i=0;i<(int32_t)subdirs.size();i+=2) { 697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru scandir(subdirs[i], subdirs[i+1]); 698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Final zone and rule info 705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Read and discard the current line. 709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid consumeLine(istream& in) { 711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t c; 712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru do { 713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = in.get(); 714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } while (c != EOF && c != '\n'); 715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruenum { 718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DOM = 0, 719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DOWGEQ = 1, 720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DOWLEQ = 2 721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char* TIME_MODE[] = {"w", "s", "u"}; 724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Allow 29 days in February because zic outputs February 29 726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// for rules like "last Sunday in February". 727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int32_t MONTH_LEN[] = {31,29,31,30,31,30,31,31,30,31,30,31}; 728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst int32_t HOUR = 3600; 730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct FinalZone { 732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t offset; // raw offset 733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t year; // takes effect for y >= year 734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string ruleid; 735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set<string> aliases; 736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru FinalZone(int32_t _offset, int32_t _year, const string& _ruleid) : 737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru offset(_offset), year(_year), ruleid(_ruleid) { 738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (offset <= -16*HOUR || offset >= 16*HOUR) { 739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ostringstream os; 740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "Invalid input offset " << offset 741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " for year " << year 742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " and rule ID " << ruleid; 743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument(os.str()); 744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (year < 1900 || year >= 2050) { 746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ostringstream os; 747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "Invalid input year " << year 748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " with offset " << offset 749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " and rule ID " << ruleid; 750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument(os.str()); 751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru FinalZone() : offset(-1), year(-1) {} 754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void addLink(const string& alias) { 755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (aliases.find(alias) != aliases.end()) { 756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ostringstream os; 757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "Duplicate alias " << alias; 758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument(os.str()); 759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru aliases.insert(alias); 761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct FinalRulePart { 765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t mode; 766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t month; 767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dom; 768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dow; 769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t time; 770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t offset; // dst offset, usually either 0 or 1:00 771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Isstd and isgmt only have 3 valid states, corresponding to local 773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // wall time, local standard time, and GMT standard time. 774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Here is how the isstd & isgmt flags are set by zic: 775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //| case 's': /* Standard */ 776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //| rp->r_todisstd = TRUE; 777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //| rp->r_todisgmt = FALSE; 778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //| case 'w': /* Wall */ 779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //| rp->r_todisstd = FALSE; 780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //| rp->r_todisgmt = FALSE; 781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //| case 'g': /* Greenwich */ 782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //| case 'u': /* Universal */ 783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //| case 'z': /* Zulu */ 784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //| rp->r_todisstd = TRUE; 785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //| rp->r_todisgmt = TRUE; 786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool isstd; 787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool isgmt; 788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool isset; // used during building; later ignored 790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru FinalRulePart() : isset(false) {} 792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void set(const string& id, 793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const string& _mode, 794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t _month, 795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t _dom, 796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t _dow, 797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t _time, 798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool _isstd, 799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool _isgmt, 800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t _offset) { 801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (isset) { 802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("FinalRulePart set twice"); 803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru isset = true; 805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (_mode == "DOWLEQ") { 806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru mode = DOWLEQ; 807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (_mode == "DOWGEQ") { 808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru mode = DOWGEQ; 809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (_mode == "DOM") { 810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru mode = DOM; 811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("Unrecognized FinalRulePart mode"); 813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru month = _month; 815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dom = _dom; 816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dow = _dow; 817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru time = _time; 818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru isstd = _isstd; 819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru isgmt = _isgmt; 820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru offset = _offset; 821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ostringstream os; 823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (month < 0 || month >= 12) { 824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "Invalid input month " << month; 825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (dom < 1 || dom > MONTH_LEN[month]) { 827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "Invalid input day of month " << dom; 828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (mode != DOM && (dow < 0 || dow >= 7)) { 830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "Invalid input day of week " << dow; 831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (offset < 0 || offset > HOUR) { 833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "Invalid input offset " << offset; 834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (isgmt && !isstd) { 836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "Invalid input isgmt && !isstd"; 837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!os.str().empty()) { 839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << " for rule " 840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << id 841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << _mode 842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << month << dom << dow << time 843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << isstd << isgmt 844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << offset; 845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument(os.str()); 846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /** 850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Return the time mode as an ICU SimpleTimeZone int from 0..2; 851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * see simpletz.h. 852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t timemode() const { 854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (isgmt) { 855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(isstd); 856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 2; // gmt standard 857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (isstd) { 859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; // local standard 860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; // local wall 862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The SimpleTimeZone encoding method for rules is as follows: 865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // stz_dowim stz_dow 866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // DOM: dom 0 867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // DOWGEQ: dom -(dow+1) 868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // DOWLEQ: -dom -(dow+1) 869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // E.g., to encode Mon>=7, use stz_dowim=7, stz_dow=-2 870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to encode Mon<=7, use stz_dowim=-7, stz_dow=-2 871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to encode 7, use stz_dowim=7, stz_dow=0 872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Note that for this program and for SimpleTimeZone, 0==Jan, 873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // but for this program 0==Sun while for SimpleTimeZone 1==Sun. 874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /** 876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Return a "dowim" param suitable for SimpleTimeZone. 877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t stz_dowim() const { 879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return (mode == DOWLEQ) ? -dom : dom; 880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /** 883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Return a "dow" param suitable for SimpleTimeZone. 884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t stz_dow() const { 886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return (mode == DOM) ? 0 : -(dow+1); 887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct FinalRule { 891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru FinalRulePart part[2]; 892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool isset() const { 894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return part[0].isset && part[1].isset; 895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void print(ostream& os) const; 898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querumap<string,FinalZone> finalZones; 901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querumap<string,FinalRule> finalRules; 902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querumap<string, set<string> > links; 904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querumap<string, string> reverseLinks; 905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querumap<string, string> linkSource; // id => "Olson link" or "ICU alias" 906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Predicate used to find FinalRule objects that do not have both 909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * sub-parts set (indicating an error in the input file). 910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querubool isNotSet(const pair<const string,FinalRule>& p) { 912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return !p.second.isset(); 913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Predicate used to find FinalZone objects that do not map to a known 917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * rule (indicating an error in the input file). 918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querubool mapsToUnknownRule(const pair<const string,FinalZone>& p) { 920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return finalRules.find(p.second.ruleid) == finalRules.end(); 921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This set is used to make sure each rule in finalRules is used at 925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * least once. First we populate it with all the rules from 926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * finalRules; then we remove all the rules referred to in 927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * finaleZones. 928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruset<string> ruleIDset; 930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid insertRuleID(const pair<string,FinalRule>& p) { 932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ruleIDset.insert(p.first); 933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid eraseRuleID(const pair<string,FinalZone>& p) { 936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ruleIDset.erase(p.second.ruleid); 937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Populate finalZones and finalRules from the given istream. 941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid readFinalZonesAndRules(istream& in) { 943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (;;) { 945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string token; 946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru in >> token; 947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (in.eof() || !in) { 948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (token == "zone") { 950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // zone Africa/Cairo 7200 1995 Egypt # zone Africa/Cairo, offset 7200, year >= 1995, rule Egypt (0) 951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string id, ruleid; 952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t offset, year; 953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru in >> id >> offset >> year >> ruleid; 954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru consumeLine(in); 955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru finalZones[id] = FinalZone(offset, year, ruleid); 956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (token == "rule") { 957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // rule US DOWGEQ 3 1 0 7200 0 0 3600 # 52: US, file data/northamerica, line 119, mode DOWGEQ, April, dom 1, Sunday, time 7200, isstd 0, isgmt 0, offset 3600 958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // rule US DOWLEQ 9 31 0 7200 0 0 0 # 53: US, file data/northamerica, line 114, mode DOWLEQ, October, dom 31, Sunday, time 7200, isstd 0, isgmt 0, offset 0 959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string id, mode; 960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t month, dom, dow, time, offset; 961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool isstd, isgmt; 962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru in >> id >> mode >> month >> dom >> dow >> time >> isstd >> isgmt >> offset; 963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru consumeLine(in); 964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru FinalRule& fr = finalRules[id]; 965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t p = fr.part[0].isset ? 1 : 0; 966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fr.part[p].set(id, mode, month, dom, dow, time, isstd, isgmt, offset); 967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (token == "link") { 968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string fromid, toid; // fromid == "real" zone, toid == alias 969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru in >> fromid >> toid; 970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // DO NOT consumeLine(in); 971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (finalZones.find(toid) != finalZones.end()) { 972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("Bad link: `to' id is a \"real\" zone"); 973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru links[fromid].insert(toid); 976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru reverseLinks[toid] = fromid; 977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru linkSource[fromid] = "Olson link"; 979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru linkSource[toid] = "Olson link"; 980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (token.length() > 0 && token[0] == '#') { 981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru consumeLine(in); 982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("Unrecognized keyword"); 984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!in.eof() && !in) { 988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("Parse failure"); 989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Perform validity check: Each rule should have data for 2 parts. 992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (count_if(finalRules.begin(), finalRules.end(), isNotSet) != 0) { 993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("One or more incomplete rule pairs"); 994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Perform validity check: Each zone should map to a known rule. 997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (count_if(finalZones.begin(), finalZones.end(), mapsToUnknownRule) != 0) { 998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("One or more zones refers to an unknown rule"); 999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Perform validity check: Each rule should be referred to by a zone. 1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ruleIDset.clear(); 1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for_each(finalRules.begin(), finalRules.end(), insertRuleID); 1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for_each(finalZones.begin(), finalZones.end(), eraseRuleID); 1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ruleIDset.size() != 0) { 1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("Unused rules"); 1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Resource bundle output 1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// SEE olsontz.h FOR RESOURCE BUNDLE DATA LAYOUT 1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ZoneInfo::print(ostream& os, const string& id) const { 1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Implement compressed format #2: 1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << " /* " << id << " */ "; 1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (aliasTo >= 0) { 1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(aliases.size() == 0); 1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << ":int { " << aliasTo << " } "; // No endl - save room for comment. 1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 102650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ICU44PLUS) { 102750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << ":table {" << endl; 102850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 102950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << ":array {" << endl; 103050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<Transition>::const_iterator trn; 1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<ZoneType>::const_iterator typ; 1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 103550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bool first; 103650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 103750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ICU44PLUS) { 103850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho trn = transitions.begin(); 103950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 104050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // pre 32bit transitions 104150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (trn != transitions.end() && trn->time < LOWEST_TIME32) { 104250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " transPre32:intvector { "; 104350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (first = true; trn != transitions.end() && trn->time < LOWEST_TIME32; ++trn) { 104450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!first) { 104550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os<< ", "; 104650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 104750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho first = false; 104850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << (int32_t)(trn->time >> 32) << ", " << (int32_t)(trn->time & 0x00000000ffffffff); 104950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 105050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " }" << endl; 105150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 105250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 105350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // 32bit transtions 105450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (trn != transitions.end() && trn->time < HIGHEST_TIME32) { 105550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " trans:intvector { "; 105650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (first = true; trn != transitions.end() && trn->time < HIGHEST_TIME32; ++trn) { 105750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!first) { 105850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << ", "; 105950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 106050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho first = false; 106150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << trn->time; 106250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 106350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " }" << endl; 106450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 106550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 106650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // post 32bit transitons 106750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (trn != transitions.end()) { 106850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " transPost32:intvector { "; 106950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (first = true; trn != transitions.end(); ++trn) { 107050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!first) { 107150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os<< ", "; 107250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 107350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho first = false; 107450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << (int32_t)(trn->time >> 32) << ", " << (int32_t)(trn->time & 0x00000000ffffffff); 107550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 107650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " }" << endl; 107750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 107850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 107950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " :intvector { "; 108050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (trn = transitions.begin(), first = true; trn != transitions.end(); ++trn) { 108150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!first) os << ", "; 108250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho first = false; 108350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << trn->time; 108450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 108550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " }" << endl; 1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 108750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru first=true; 109050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ICU44PLUS) { 109150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " typeOffsets:intvector { "; 109250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 109350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " :intvector { "; 109450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (typ = types.begin(); typ != types.end(); ++typ) { 1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!first) os << ", "; 1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru first = false; 1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << typ->rawoffset << ", " << typ->dstoffset; 1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << " }" << endl; 1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 110250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ICU44PLUS) { 110350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (transitions.size() != 0) { 110450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " typeMap:bin { \"" << hex << setfill('0'); 110550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (trn = transitions.begin(); trn != transitions.end(); ++trn) { 110650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << setw(2) << trn->type; 110750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 110850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << dec << "\" }" << endl; 110950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 111050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 111150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " :bin { \"" << hex << setfill('0'); 111250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (trn = transitions.begin(); trn != transitions.end(); ++trn) { 111350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << setw(2) << trn->type; 111450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 111550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << dec << "\" }" << endl; 1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Final zone info, if any 1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (finalYear != -1) { 112050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ICU44PLUS) { 112150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " finalRule { \"" << finalRuleID << "\" }" << endl; 112250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " finalRaw:int { " << finalOffset << " }" << endl; 112350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " finalYear:int { " << finalYear << " }" << endl; 112450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 112550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " \"" << finalRuleID << "\"" << endl; 112650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " :intvector { " << finalOffset << ", " 112750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho << finalYear << " }" << endl; 112850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Alias list, if any 1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (aliases.size() != 0) { 1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru first = true; 113450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ICU44PLUS) { 113550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " links:intvector { "; 113650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 113750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho os << " :intvector { "; 113850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (set<int32_t>::const_iterator i=aliases.begin(); i!=aliases.end(); ++i) { 1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!first) os << ", "; 1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru first = false; 1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << *i; 1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << " }" << endl; 1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << " } "; // no trailing 'endl', so comments can be placed. 1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruinline ostream& 1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruoperator<<(ostream& os, const ZoneMap& zoneinfo) { 1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t c = 0; 1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (ZoneMapIter it = zoneinfo.begin(); 1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru it != zoneinfo.end(); 1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ++it) { 115650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(c && !ICU44PLUS) os << ","; 1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru it->second.print(os, it->first); 1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "//Z#" << c++ << endl; 1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return os; 1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// print the string list 1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruostream& printStringList( ostream& os, const ZoneMap& zoneinfo) { 1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t n = 0; // count 1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t col = 0; // column 1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << " Names {" << endl 1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " "; 1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (ZoneMapIter it = zoneinfo.begin(); 1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru it != zoneinfo.end(); 1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ++it) { 1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(n) { 1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << ","; 1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru col ++; 1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const string& id = it->first; 1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << "\"" << id << "\""; 1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru col += id.length() + 2; 1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(col >= 50) { 1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << " // " << n << endl 1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " "; 1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru col = 0; 1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru n++; 1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << " // " << (n-1) << endl 1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " }" << endl; 1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return os; 1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// main 1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------------------------------- 1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Unary predicate for finding transitions after a given time 1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querubool isAfter(const Transition t, int64_t thresh) { 1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return t.time >= thresh; 1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * A zone type that contains only the raw and dst offset. Used by the 1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * optimizeTypeList() method. 1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct SimplifiedZoneType { 1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t rawoffset; 1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t dstoffset; 1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru SimplifiedZoneType() : rawoffset(-1), dstoffset(-1) {} 1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru SimplifiedZoneType(const ZoneType& t) : rawoffset(t.rawoffset), 1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dstoffset(t.dstoffset) {} 1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bool operator<(const SimplifiedZoneType& t) const { 1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return rawoffset < t.rawoffset || 1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (rawoffset == t.rawoffset && 1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dstoffset < t.dstoffset); 1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Construct a ZoneType from a SimplifiedZoneType. Note that this 1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * discards information; the new ZoneType will have meaningless 1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * (empty) abbr, isdst, isstd, and isgmt flags; this is appropriate, 1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * since ignoring these is how we do optimization (we have no use for 1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * these in historical transitions). 1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruZoneType::ZoneType(const SimplifiedZoneType& t) : 1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rawoffset(t.rawoffset), dstoffset(t.dstoffset), 1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru abbr(-1), isdst(false), isstd(false), isgmt(false) {} 1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Optimize the type list to remove excess entries. The type list may 1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * contain entries that are distinct only in terms of their dst, std, 1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * or gmt flags. Since we don't care about those flags, we can reduce 1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the type list to a set of unique raw/dst offset pairs, and remap 1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the type indices in the transition list, which stores, for each 1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * transition, a transition time and a type index. 1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ZoneInfo::optimizeTypeList() { 1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Assemble set of unique types; only those in the `transitions' 1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // list, since there may be unused types in the `types' list 1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // corresponding to transitions that have been trimmed (during 1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // merging of final data). 1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (aliasTo >= 0) return; // Nothing to do for aliases 1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 124550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!ICU44PLUS) { 124650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // This is the old logic which has a bug, which occasionally removes 124750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // the type before the first transition. The problem was fixed 124850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // by inserting the dummy transition indirectly. 124950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 125050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // If there are zero transitions and one type, then leave that as-is. 125150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (transitions.size() == 0) { 125250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (types.size() != 1) { 125350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cerr << "Error: transition count = 0, type count = " << types.size() << endl; 125450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 125550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 125850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho set<SimplifiedZoneType> simpleset; 125950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (vector<Transition>::const_iterator i=transitions.begin(); 126050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho i!=transitions.end(); ++i) { 126150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(i->type < (int32_t)types.size()); 126250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho simpleset.insert(types[i->type]); 126350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 126550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Map types to integer indices 126650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho map<SimplifiedZoneType,int32_t> simplemap; 126750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t n=0; 126850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (set<SimplifiedZoneType>::const_iterator i=simpleset.begin(); 126950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho i!=simpleset.end(); ++i) { 127050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho simplemap[*i] = n++; 127150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 127250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 127350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Remap transitions 127450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (vector<Transition>::iterator i=transitions.begin(); 127550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho i!=transitions.end(); ++i) { 127650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(i->type < (int32_t)types.size()); 127750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ZoneType oldtype = types[i->type]; 127850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho SimplifiedZoneType newtype(oldtype); 127950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(simplemap.find(newtype) != simplemap.end()); 128050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho i->type = simplemap[newtype]; 128150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 128250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 128350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Replace type list 128450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho types.clear(); 128550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho copy(simpleset.begin(), simpleset.end(), back_inserter(types)); 128650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 128750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 128850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (types.size() > 1) { 128950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Note: localtime uses the very first non-dst type as initial offsets. 129050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // If all types are DSTs, the very first type is treated as the initial offsets. 129150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 129250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Decide a type used as the initial offsets. ICU put the type at index 0. 129350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ZoneType initialType = types[0]; 129450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (vector<ZoneType>::const_iterator i=types.begin(); i!=types.end(); ++i) { 129550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (i->dstoffset == 0) { 129650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho initialType = *i; 129750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 129850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 129950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 130050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 130150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho SimplifiedZoneType initialSimplifiedType(initialType); 130250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 130350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // create a set of unique types, but ignoring fields which we're not interested in 130450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho set<SimplifiedZoneType> simpleset; 130550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho simpleset.insert(initialSimplifiedType); 130650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (vector<Transition>::const_iterator i=transitions.begin(); i!=transitions.end(); ++i) { 130750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(i->type < (int32_t)types.size()); 130850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho simpleset.insert(types[i->type]); 130950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 131050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 131150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Map types to integer indices, however, keeping the first type at offset 0 131250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho map<SimplifiedZoneType,int32_t> simplemap; 131350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho simplemap[initialSimplifiedType] = 0; 131450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t n = 1; 131550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (set<SimplifiedZoneType>::const_iterator i=simpleset.begin(); i!=simpleset.end(); ++i) { 131650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*i < initialSimplifiedType || initialSimplifiedType < *i) { 131750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho simplemap[*i] = n++; 131850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 131950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 132050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 132150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Remap transitions 132250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (vector<Transition>::iterator i=transitions.begin(); 132350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho i!=transitions.end(); ++i) { 132450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(i->type < (int32_t)types.size()); 132550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ZoneType oldtype = types[i->type]; 132650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho SimplifiedZoneType newtype(oldtype); 132750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(simplemap.find(newtype) != simplemap.end()); 132850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho i->type = simplemap[newtype]; 132950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 133050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 133150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Replace type list 133250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho types.clear(); 133350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho types.push_back(initialSimplifiedType); 133450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (set<SimplifiedZoneType>::const_iterator i=simpleset.begin(); i!=simpleset.end(); ++i) { 133550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*i < initialSimplifiedType || initialSimplifiedType < *i) { 133650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho types.push_back(*i); 133750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 133850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 134050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Reiterating transitions to remove any transitions which 134150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // do not actually change the raw/dst offsets 134250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t prevTypeIdx = 0; 134350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (vector<Transition>::iterator i=transitions.begin(); i!=transitions.end();) { 134450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (i->type == prevTypeIdx) { 134550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // this is not a time transition, probably just name change 134650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // e.g. America/Resolute after 2006 in 2010b 134750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho transitions.erase(i); 134850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 134950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho prevTypeIdx = i->type; 135050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho i++; 135150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 135250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 135350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Merge final zone data into this zone. 1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ZoneInfo::mergeFinalData(const FinalZone& fz) { 1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t year = fz.year; 1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t seconds = yearToSeconds(year); 136450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 136550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!ICU44PLUS) { 136650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (seconds > HIGHEST_TIME32) { 136750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Avoid transitions beyond signed 32bit max second. 136850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // This may result incorrect offset computation around 136950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // HIGHEST_TIME32. This is a limitation of ICU 137050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // before 4.4. 137150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho seconds = HIGHEST_TIME32; 137250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 137350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 137450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<Transition>::iterator it = 1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru find_if(transitions.begin(), transitions.end(), 1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bind2nd(ptr_fun(isAfter), seconds)); 1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru transitions.erase(it, transitions.end()); 1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (finalYear != -1) { 1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("Final zone already merged in"); 1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru finalYear = fz.year; 1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru finalOffset = fz.offset; 1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru finalRuleID = fz.ruleid; 1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Merge the data from the given final zone into the core zone data by 1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * calling the ZoneInfo member function mergeFinalData. 1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid mergeOne(const string& zoneid, const FinalZone& fz) { 1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ZONEINFO.find(zoneid) == ZONEINFO.end()) { 1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru throw invalid_argument("Unrecognized final zone ID"); 1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZONEINFO[zoneid].mergeFinalData(fz); 1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Visitor function that merges the final zone data into the main zone 1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * data structures. It calls mergeOne for each final zone and its 1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * list of aliases. 1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid mergeFinalZone(const pair<string,FinalZone>& p) { 1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const string& id = p.first; 1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const FinalZone& fz = p.second; 1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru mergeOne(id, fz); 1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Print this rule in resource bundle format to os. ID and enclosing 1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * braces handled elsewhere. 1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid FinalRule::print(ostream& os) const { 1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // First print the rule part that enters DST; then the rule part 1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // that exits it. 1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t whichpart = (part[0].offset != 0) ? 0 : 1; 1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(part[whichpart].offset != 0); 1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(part[1-whichpart].offset == 0); 1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << " "; 1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int32_t i=0; i<2; ++i) { 1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const FinalRulePart& p = part[whichpart]; 1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru whichpart = 1-whichpart; 1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << p.month << ", " << p.stz_dowim() << ", " << p.stz_dow() << ", " 1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << p.time << ", " << p.timemode() << ", "; 1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru os << part[whichpart].offset << endl; 1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint main(int argc, char *argv[]) { 1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string rootpath, zonetab, version; 143450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bool validArgs = FALSE; 1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 143650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (argc == 4 || argc == 5) { 143750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho validArgs = TRUE; 1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rootpath = argv[1]; 1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru zonetab = argv[2]; 1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru version = argv[3]; 144150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (argc == 5) { 144250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (strcmp(argv[4], "--old") == 0) { 144350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ICU44PLUS = FALSE; 144450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho TZ_RESOURCE_NAME = ICU_TZ_RESOURCE_OLD; 144550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 144650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho validArgs = FALSE; 144750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 144850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 144950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 145050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!validArgs) { 145150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cout << "Usage: tz2icu <dir> <cmap> <tzver> [--old]" << endl 145250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho << " <dir> path to zoneinfo file tree generated by" << endl 145350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho << " ICU-patched version of zic" << endl 145450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho << " <cmap> country map, from tzdata archive," << endl 145550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho << " typically named \"zone.tab\"" << endl 145650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho << " <tzver> version string, such as \"2003e\"" << endl 145750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho << " --old generating resource format before ICU4.4" << endl; 145850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho exit(1); 1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cout << "Olson data version: " << version << endl; 146250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cout << "ICU 4.4+ format: " << (ICU44PLUS ? "Yes" : "No") << endl; 1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru try { 1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ifstream finals(ICU_ZONE_FILE); 1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (finals) { 1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru readFinalZonesAndRules(finals); 1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cout << "Finished reading " << finalZones.size() 1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " final zones and " << finalRules.size() 1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " final rules from " ICU_ZONE_FILE << endl; 1472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: Unable to open " ICU_ZONE_FILE << endl; 1474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } catch (const exception& error) { 1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: While reading " ICU_ZONE_FILE ": " << error.what() << endl; 1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru try { 1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Recursively scan all files below the given path, accumulating 1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // their data into ZONEINFO. All files must be TZif files. Any 1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // failure along the way will result in a call to exit(1). 1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru scandir(rootpath); 1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } catch (const exception& error) { 1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: While scanning " << rootpath << ": " << error.what() << endl; 1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cout << "Finished reading " << ZONEINFO.size() << " zoneinfo files [" 1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << (ZONEINFO.begin())->first << ".." 1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << (--ZONEINFO.end())->first << "]" << endl; 1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru try { 1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for_each(finalZones.begin(), finalZones.end(), mergeFinalZone); 1497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } catch (const exception& error) { 1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: While merging final zone data: " << error.what() << endl; 1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Process links (including ICU aliases). For each link set we have 1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // a canonical ID (e.g., America/Los_Angeles) and a set of one or more 1504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // aliases (e.g., PST, PST8PDT, ...). 1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 1. Add all aliases as zone objects in ZONEINFO 1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (map<string,set<string> >::const_iterator i = links.begin(); 1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru i!=links.end(); ++i) { 1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const string& olson = i->first; 1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const set<string>& aliases = i->second; 1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ZONEINFO.find(olson) == ZONEINFO.end()) { 1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: Invalid " << linkSource[olson] << " to non-existent \"" 1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << olson << "\"" << endl; 1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (set<string>::const_iterator j=aliases.begin(); 1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru j!=aliases.end(); ++j) { 1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZONEINFO[*j] = ZoneInfo(); 1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 2. Create a mapping from zones to index numbers 0..n-1. 1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru map<string,int32_t> zoneIDs; 1524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru vector<string> zoneIDlist; 1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t z=0; 1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (ZoneMap::iterator i=ZONEINFO.begin(); i!=ZONEINFO.end(); ++i) { 1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru zoneIDs[i->first] = z++; 1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru zoneIDlist.push_back(i->first); 1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(z == (int32_t) ZONEINFO.size()); 1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 3. Merge aliases. Sometimes aliases link to other aliases; we 1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // resolve these into simplest possible sets. 1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru map<string,set<string> > links2; 1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru map<string,string> reverse2; 1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (map<string,set<string> >::const_iterator i = links.begin(); 1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru i!=links.end(); ++i) { 1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string olson = i->first; 1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (reverseLinks.find(olson) != reverseLinks.end()) { 1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru olson = reverseLinks[olson]; 1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (set<string>::const_iterator j=i->second.begin(); j!=i->second.end(); ++j) { 1543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru links2[olson].insert(*j); 1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru reverse2[*j] = olson; 1545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru links = links2; 1548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru reverseLinks = reverse2; 1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (false) { // Debugging: Emit link map 1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (map<string,set<string> >::const_iterator i = links.begin(); 1552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru i!=links.end(); ++i) { 1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cout << i->first << ": "; 1554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (set<string>::const_iterator j=i->second.begin(); j!=i->second.end(); ++j) { 1555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cout << *j << ", "; 1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cout << endl; 1558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 4. Update aliases 1562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (map<string,set<string> >::const_iterator i = links.begin(); 1563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru i!=links.end(); ++i) { 1564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const string& olson = i->first; 1565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const set<string>& aliases = i->second; 1566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZONEINFO[olson].clearAliases(); 1567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZONEINFO[olson].addAlias(zoneIDs[olson]); 1568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (set<string>::const_iterator j=aliases.begin(); 1569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru j!=aliases.end(); ++j) { 1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(zoneIDs.find(olson) != zoneIDs.end()); 1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(zoneIDs.find(*j) != zoneIDs.end()); 1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru assert(ZONEINFO.find(*j) != ZONEINFO.end()); 1573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZONEINFO[*j].setAliasTo(zoneIDs[olson]); 1574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ZONEINFO[olson].addAlias(zoneIDs[*j]); 1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Once merging of final data is complete, we can optimize the type list 1579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (ZoneMap::iterator i=ZONEINFO.begin(); i!=ZONEINFO.end(); ++i) { 1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru i->second.optimizeTypeList(); 1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Create the country map 1584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru map<string, set<string> > countryMap; // country -> set of zones 1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru map<string, string> reverseCountryMap; // zone -> country 1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru try { 1587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ifstream f(zonetab.c_str()); 1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!f) { 1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: Unable to open " << zonetab << endl; 1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 1591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t n = 0; 1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string line; 1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (getline(f, line)) { 1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string::size_type lb = line.find('#'); 1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (lb != string::npos) { 1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru line.resize(lb); // trim comments 1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string country, coord, zone; 1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru istringstream is(line); 1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru is >> country >> coord >> zone; 1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (country.size() == 0) continue; 1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (country.size() != 2 || zone.size() < 1) { 1604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: Can't parse " << line << " in " << zonetab << endl; 1605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ZONEINFO.find(zone) == ZONEINFO.end()) { 1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: Country maps to invalid zone " << zone 1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " in " << zonetab << endl; 1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru countryMap[country].insert(zone); 1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru reverseCountryMap[zone] = country; 1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //cerr << (n+1) << ": " << country << " <=> " << zone << endl; 1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ++n; 1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cout << "Finished reading " << n 1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " country entries from " << zonetab << endl; 1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } catch (const exception& error) { 1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cerr << "Error: While reading " << zonetab << ": " << error.what() << endl; 1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Merge ICU aliases into country map. Don't merge any alias 1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // that already has a country map, since that doesn't make sense. 1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // E.g. "Link Europe/Oslo Arctic/Longyearbyen" doesn't mean we 1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // should cross-map the countries between these two zones. 1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (map<string,set<string> >::const_iterator i = links.begin(); 1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru i!=links.end(); ++i) { 1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const string& olson(i->first); 1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (reverseCountryMap.find(olson) == reverseCountryMap.end()) { 1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru continue; 1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string c = reverseCountryMap[olson]; 1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const set<string>& aliases(i->second); 1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (set<string>::const_iterator j=aliases.begin(); 1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru j != aliases.end(); ++j) { 1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (reverseCountryMap.find(*j) == reverseCountryMap.end()) { 1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru countryMap[c].insert(*j); 1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru reverseCountryMap[*j] = c; 1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //cerr << "Aliased country: " << c << " <=> " << *j << endl; 1642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Create a pseudo-country containing all zones belonging to no country 1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set<string> nocountry; 1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (ZoneMap::iterator i=ZONEINFO.begin(); i!=ZONEINFO.end(); ++i) { 1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (reverseCountryMap.find(i->first) == reverseCountryMap.end()) { 1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru nocountry.insert(i->first); 1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru countryMap[""] = nocountry; 1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get local time & year for below 1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru time_t sec; 1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru time(&sec); 1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru struct tm* now = localtime(&sec); 1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t thisYear = now->tm_year + 1900; 1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 166150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho string filename = TZ_RESOURCE_NAME + ".txt"; 1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Write out a resource-bundle source file containing data for 1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // all zones. 166450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ofstream file(filename.c_str()); 1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (file) { 1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file << "//---------------------------------------------------------" << endl 1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << "// Copyright (C) 2003"; 1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (thisYear > 2003) { 1669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file << "-" << thisYear; 1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file << ", International Business Machines" << endl 1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << "// Corporation and others. All Rights Reserved." << endl 1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << "//---------------------------------------------------------" << endl 1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << "// Build tool: tz2icu" << endl 1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << "// Build date: " << asctime(now) /* << endl -- asctime emits CR */ 1676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << "// Olson source: ftp://elsie.nci.nih.gov/pub/" << endl 1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << "// Olson version: " << version << endl 1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << "// ICU version: " << U_ICU_VERSION << endl 1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << "//---------------------------------------------------------" << endl 1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << "// >> !!! >> THIS IS A MACHINE-GENERATED FILE << !!! <<" << endl 1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << "// >> !!! >>> DO NOT EDIT <<< !!! <<" << endl 1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << "//---------------------------------------------------------" << endl 1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << endl 168450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho << TZ_RESOURCE_NAME << ":table(nofallback) {" << endl 1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " TZVersion { \"" << version << "\" }" << endl 1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " Zones:array { " << endl 1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << ZONEINFO // Zones (the actual data) 1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru << " }" << endl; 1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Names correspond to the Zones list, used for binary searching. 1691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru printStringList ( file, ZONEINFO ); // print the Names list 1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Final Rules are used if requested by the zone 1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file << " Rules { " << endl; 1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Emit final rules 1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t frc = 0; 1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for(map<string,FinalRule>::iterator i=finalRules.begin(); 1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru i!=finalRules.end(); ++i) { 1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const string& id = i->first; 1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const FinalRule& r = i->second; 1701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file << " " << id << ":intvector {" << endl; 1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru r.print(file); 1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file << " } //_#" << frc++ << endl; 1704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file << " }" << endl; 1706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 170750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Emit country (region) map. 170850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ICU44PLUS) { 170950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho file << " Regions:array {" << endl; 171050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t zn = 0; 171150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (ZoneMap::iterator i=ZONEINFO.begin(); i!=ZONEINFO.end(); ++i) { 171250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho map<string, string>::iterator cit = reverseCountryMap.find(i->first); 171350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (cit == reverseCountryMap.end()) { 171450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho file << " \"001\","; 171550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 171650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho file << " \"" << cit->second << "\", "; 171750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 171850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho file << "//Z#" << zn++ << " " << i->first << endl; 1719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 172050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho file << " }" << endl; 172150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 172250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho file << " Regions { " << endl; 172350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t rc = 0; 172450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (map<string, set<string> >::const_iterator i=countryMap.begin(); 172550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho i != countryMap.end(); ++i) { 172650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho string country = i->first; 172750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const set<string>& zones(i->second); 172850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho file << " "; 172950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(country[0]==0) { 173050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho file << "Default"; 173150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 173250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho file << country << ":intvector { "; 173350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bool first = true; 173450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (set<string>::const_iterator j=zones.begin(); 173550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho j != zones.end(); ++j) { 173650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!first) file << ", "; 173750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho first = false; 173850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (zoneIDs.find(*j) == zoneIDs.end()) { 173950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cerr << "Error: Nonexistent zone in country map: " << *j << endl; 174050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1; 174150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 174250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho file << zoneIDs[*j]; // emit the zone's index number 1743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 174450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho file << " } //R#" << rc++ << endl; 1745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 174650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho file << " }" << endl; 1747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file << "}" << endl; 1750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru file.close(); 1753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (file) { // recheck error bit 175550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cout << "Finished writing " << TZ_RESOURCE_NAME << ".txt" << endl; 1756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 175750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cerr << "Error: Unable to open/write to " << TZ_RESOURCE_NAME << ".txt" << endl; 1758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 1759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof 1762