/// <summary> /// Find the specified name in the index and load a time zone /// definition. If the name is not found then return null. /// </summary> static TimeZone loadTimeZone(string x) { string name = x; int slash = x.LastIndexOf('/'); if (slash > 0) name = name.Substring(slash+1); // find index, which maps the file offset // TODO: why doesn't BinarySearch work? // int ix = Array.BinarySearch(indexNames, name); int ix = -1; for (int i=0; i<indexNames.Length; ++i) if (name == indexNames[i]) { ix = i; break; } if (ix < 0) return null; // map full name string fullName = name; string prefix = prefixes[indexPrefixes[ix] & 0xff]; if (prefix.Length != 0) fullName = prefix + "/" + name; if (slash > 0 && x != fullName) return null; // create time zone instance TimeZone tz = new TimeZone(); tz.m_name = name; tz.m_fullName = fullName; // read time zone definition from database file FileStream f = dbFile.OpenRead(); DataReader d = new DataReader(f); try { f.Seek(indexOffsets[ix], SeekOrigin.Begin); int numRules = d.ReadUnsignedShort(); tz.rules = new Rule[numRules]; for (int i=0; i<numRules; ++i) { Rule r = tz.rules[i] = new Rule(); r.startYear = d.ReadUnsignedShort(); r.offset = d.ReadInt(); r.stdAbbr = d.ReadUTF(); r.dstOffset = d.ReadInt(); if (r.dstOffset == 0) continue; r.dstAbbr = d.ReadUTF(); r.dstStart = loadDstTime(d); r.dstEnd = loadDstTime(d); if (i != 0 && tz.rules[i-1].startYear <= r.startYear) throw new IOException("TimeZone rules not sorted: " + name); } } finally { f.Close(); } return tz; }
/* static void loadIndex() { DataReader reader = new DataReader(new BufferedStream(dbFile.OpenRead())); try { // check magic "fantz 01" long magic = reader.ReadLong(); if (magic != 0x66616e747a203031L) throw new IOException("Invalid magic 0x" + magic.ToString("X").ToLower()); reader.ReadUTF(); // load the name/offset pairs and verify in sort order int num = reader.ReadInt(); indexNames = new string[num]; indexTypes = new byte[num]; indexOffsets = new int[num]; for (int i=0; i<num; ++i) { indexNames[i] = reader.ReadUTF(); indexTypes[i] = (byte)reader.ReadByte(); indexOffsets[i] = reader.ReadInt(); if (i != 0 && String.Compare(indexNames[i-1], indexNames[i], StringComparison.Ordinal) >= 0) throw new IOException("Index not sorted"); } } finally { reader.Close(); } } static TimeZone loadTimeZone(string name) { // find index, which maps the file offset int ix = Array.BinarySearch(indexNames, name); if (ix < 0) return null; int seekOffset = indexOffsets[ix]; // create time zone instance TimeZone tz = new TimeZone(); tz.m_name = name; // read time zone definition from database file FileStream f = dbFile.OpenRead(); DataReader d = new DataReader(f); try { f.Seek(seekOffset, SeekOrigin.Begin); tz.m_name = d.ReadUTF(); tz.m_fullName = d.ReadUTF(); int numRules = d.ReadUnsignedShort(); tz.rules = new Rule[numRules]; for (int i=0; i<numRules; ++i) { Rule r = tz.rules[i] = new Rule(); r.startYear = d.ReadUnsignedShort(); r.offset = d.ReadInt(); r.stdAbbr = d.ReadUTF(); r.dstOffset = d.ReadInt(); if (r.dstOffset == 0) continue; r.dstAbbr = d.ReadUTF(); r.dstStart = loadDstTime(d); r.dstEnd = loadDstTime(d); if (i != 0 && tz.rules[i-1].startYear <= r.startYear) throw new IOException("TimeZone rules not sorted: " + name); } } finally { f.Close(); } return tz; } */ static DstTime loadDstTime(DataReader d) { DstTime t = new DstTime(); t.mon = d.ReadByte(); t.onMode = d.ReadByte(); t.onWeekday = d.ReadByte(); t.onDay = d.ReadByte(); t.atTime = d.ReadInt(); t.atMode = d.ReadByte(); return t; }
////////////////////////////////////////////////////////////////////////// // Database ////////////////////////////////////////////////////////////////////////// // // TimeZone database format: // // ftz // { // u8 magic ("fantz 02") // utf summary // u1 numPrefixes // utf[] prefixes // u2 numIndexItems // indexItems[] // sorted by name // { // u1 prefix id // utf name // u4 fileOffset // } // timeZones[] // { // u2 numRules // rules[] // { // u2 startYear // i4 utcOffset (seconds) // utf stdAbbr // i4 dstOffset (seconds); if zero rest is skipped // [ // utf dstAbbr // dstTime dstStart // dstTime dstEnd // ] // } // } // // dstTime // { // u1 month // u1 onMode 'd', 'l', '>', '<' (date, last, >=, and <=) // u1 onWeekday (0-6) // u1 onDay // i4 atTime (seconds) // u1 atMode 'w' , 's', 'u' (wall, standad, universal) // } // // The timezone database is generated by the "/adm/buildtz.fan" // script. Refer to the "zic.8.txt" source file the code // distribution of the Olson database to further describe // model of the original data. // /// <summary> /// Load the name and file offset list from file into memory. /// </summary> static void loadIndex() { DataReader reader = new DataReader(new BufferedStream(dbFile.OpenRead())); try { // check magic "fantz 02" long magic = reader.ReadLong(); if (magic != 0x66616e747a203032L) throw new IOException("Invalid magic 0x" + magic.ToString("X").ToLower()); reader.ReadUTF(); // load prefixes int numPrefixes = reader.ReadByte(); prefixes = new string[numPrefixes]; for (int i=0; i<numPrefixes; ++i) prefixes[i] = reader.ReadUTF(); // load the zones and verify in sort order int num = reader.ReadUnsignedShort(); indexPrefixes = new byte[num]; indexNames = new string[num]; indexOffsets = new int[num]; for (int i=0; i<num; ++i) { indexPrefixes[i] = reader.ReadByte(); indexNames[i] = reader.ReadUTF(); indexOffsets[i] = reader.ReadInt(); if (i != 0 && String.Compare(indexNames[i-1], indexNames[i], StringComparison.Ordinal) >= 0) throw new IOException("Index not sorted"); } } finally { reader.Close(); } }
////////////////////////////////////////////////////////////////////////// // Write ////////////////////////////////////////////////////////////////////////// public void code(FBuf code) { try { this.m_code = code; this.m_input = new DataReader(new MemoryStream(m_code.m_buf, 0, m_code.m_len)); /* if (false) { int c; while ((c = m_input.Read()) >= 0) WriteLine(" 0x" + c); return; } */ int op; while ((op = m_input.Read()) >= 0) { m_n++; this.op(op); } } catch (IOException e) { Err.dumpStack(e); } Flush(); this.m_code = null; this.m_input = null; }