Switch bionic over to using libcore's copy of libcore.util.ZoneInfo.
Bug: 7012465
Change-Id: I1225494c5d77a20fd48be1e904d8695ef95860e3
diff --git a/libc/tools/zoneinfo/ZoneCompactor.java b/libc/tools/zoneinfo/ZoneCompactor.java
index b657748..814ef5b 100644
--- a/libc/tools/zoneinfo/ZoneCompactor.java
+++ b/libc/tools/zoneinfo/ZoneCompactor.java
@@ -1,6 +1,9 @@
import java.io.*;
+import java.nio.ByteOrder;
import java.util.*;
+import libcore.io.BufferIterator;
+import libcore.util.ZoneInfo;
// usage: java ZoneCompiler <setup file> <top-level directory>
//
@@ -30,27 +33,66 @@
// <produces zoneinfo.dat and zoneinfo.idx>
public class ZoneCompactor {
+ public static class ByteArrayBufferIteratorBE extends BufferIterator {
+ private final byte[] bytes;
+ private int offset = 0;
- // Zone name synonyms
- Map<String,String> links = new HashMap<String,String>();
+ public ByteArrayBufferIteratorBE(byte[] bytes) {
+ this.bytes = bytes;
+ this.offset = 0;
+ }
- // File starting bytes by zone name
- Map<String,Integer> starts = new HashMap<String,Integer>();
+ public void seek(int offset) {
+ this.offset = offset;
+ }
- // File lengths by zone name
- Map<String,Integer> lengths = new HashMap<String,Integer>();
+ public void skip(int byteCount) {
+ this.offset += byteCount;
+ }
- // Raw GMT offsets by zone name
- Map<String,Integer> offsets = new HashMap<String,Integer>();
- int start = 0;
+ public void readByteArray(byte[] dst, int dstOffset, int byteCount) {
+ System.arraycopy(bytes, offset, dst, dstOffset, byteCount);
+ offset += byteCount;
+ }
+
+ public byte readByte() {
+ return bytes[offset++];
+ }
+
+ public int readInt() {
+ return ((readByte() & 0xff) << 24) | ((readByte() & 0xff) << 16) | ((readByte() & 0xff) << 8) | (readByte() & 0xff);
+ }
+
+ public void readIntArray(int[] dst, int dstOffset, int intCount) {
+ for (int i = 0; i < intCount; ++i) {
+ dst[dstOffset++] = readInt();
+ }
+ }
+
+ public short readShort() {
+ throw new UnsupportedOperationException();
+ }
+ }
// Maximum number of characters in a zone name, including '\0' terminator
private static final int MAXNAME = 40;
+ // Zone name synonyms
+ private Map<String,String> links = new HashMap<String,String>();
+
+ // File starting bytes by zone name
+ private Map<String,Integer> starts = new HashMap<String,Integer>();
+
+ // File lengths by zone name
+ private Map<String,Integer> lengths = new HashMap<String,Integer>();
+
+ // Raw GMT offsets by zone name
+ private Map<String,Integer> offsets = new HashMap<String,Integer>();
+ private int start = 0;
+
// Concatenate the contents of 'inFile' onto 'out'
// and return the contents as a byte array.
- private static byte[] copyFile(File inFile, OutputStream out)
- throws Exception {
+ private static byte[] copyFile(File inFile, OutputStream out) throws Exception {
byte[] ret = new byte[0];
InputStream in = new FileInputStream(inFile);
@@ -70,7 +112,7 @@
out.flush();
return ret;
}
-
+
// Write a 32-bit integer in network byte order
private void writeInt(OutputStream os, int x) throws IOException {
os.write((x >> 24) & 0xff);
@@ -79,14 +121,13 @@
os.write( x & 0xff);
}
- public ZoneCompactor(String setupFilename, String dirName)
- throws Exception {
+ public ZoneCompactor(String setupFilename, String dirName) throws Exception {
File zoneInfoFile = new File("zoneinfo.dat");
zoneInfoFile.delete();
OutputStream zoneInfo = new FileOutputStream(zoneInfoFile);
BufferedReader rdr = new BufferedReader(new FileReader(setupFilename));
-
+
String s;
while ((s = rdr.readLine()) != null) {
s = s.trim();
@@ -107,7 +148,8 @@
start += length;
byte[] data = copyFile(f, zoneInfo);
- TimeZone tz = ZoneInfo.make(s, data);
+ BufferIterator it = new ByteArrayBufferIteratorBE(data);
+ TimeZone tz = ZoneInfo.makeTimeZone(s, it);
int gmtOffset = tz.getRawOffset();
offsets.put(s, new Integer(gmtOffset));
}
@@ -162,5 +204,4 @@
}
new ZoneCompactor(args[0], args[1]);
}
-
}
diff --git a/libc/tools/zoneinfo/ZoneInfo.java b/libc/tools/zoneinfo/ZoneInfo.java
deleted file mode 100644
index 99507ae..0000000
--- a/libc/tools/zoneinfo/ZoneInfo.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.TimeZone;
-
-/**
- * Copied from ZoneInfo and ZoneInfoDB in dalvik.
- * {@hide}
- */
-public class ZoneInfo extends TimeZone {
-
- private static final long MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
- private static final long MILLISECONDS_PER_400_YEARS =
- MILLISECONDS_PER_DAY * (400 * 365 + 100 - 3);
-
- private static final long UNIX_OFFSET = 62167219200000L;
-
- private static final int[] NORMAL = new int[] {
- 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
- };
-
- private static final int[] LEAP = new int[] {
- 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
- };
-
- private static String nullName(byte[] data, int where, int off) {
- if (off < 0)
- return null;
-
- int end = where + off;
- while (end < data.length && data[end] != '\0')
- end++;
-
- return new String(data, where + off, end - (where + off));
- }
-
- public static ZoneInfo make(String name, byte[] data) {
- int ntransition = read4(data, 32);
- int ngmtoff = read4(data, 36);
- int base = 44;
-
- int[] transitions = new int[ntransition];
- for (int i = 0; i < ntransition; i++)
- transitions[i] = read4(data, base + 4 * i);
- base += 4 * ntransition;
-
- byte[] type = new byte[ntransition];
- for (int i = 0; i < ntransition; i++)
- type[i] = data[base + i];
- base += ntransition;
-
- int[] gmtoff = new int[ngmtoff];
- byte[] isdst = new byte[ngmtoff];
- byte[] abbrev = new byte[ngmtoff];
- for (int i = 0; i < ngmtoff; i++) {
- gmtoff[i] = read4(data, base + 6 * i);
- isdst[i] = data[base + 6 * i + 4];
- abbrev[i] = data[base + 6 * i + 5];
- }
-
- base += 6 * ngmtoff;
-
- return new ZoneInfo(name, transitions, type, gmtoff, isdst, abbrev, data, base);
- }
-
- private static int read4(byte[] data, int off) {
- return ((data[off ] & 0xFF) << 24) |
- ((data[off + 1] & 0xFF) << 16) |
- ((data[off + 2] & 0xFF) << 8) |
- ((data[off + 3] & 0xFF) << 0);
- }
-
- /*package*/ ZoneInfo(String name, int[] transitions, byte[] type,
- int[] gmtoff, byte[] isdst, byte[] abbrev,
- byte[] data, int abbrevoff) {
- mTransitions = transitions;
- mTypes = type;
- mGmtOffs = gmtoff;
- mIsDsts = isdst;
- mUseDst = false;
- setID(name);
-
- // Find the latest GMT and non-GMT offsets for their abbreviations
-
- int lastdst;
- for (lastdst = mTransitions.length - 1; lastdst >= 0; lastdst--) {
- if (mIsDsts[mTypes[lastdst] & 0xFF] != 0)
- break;
- }
-
- int laststd;
- for (laststd = mTransitions.length - 1; laststd >= 0; laststd--) {
- if (mIsDsts[mTypes[laststd] & 0xFF] == 0)
- break;
- }
-
- if (lastdst >= 0) {
- mDaylightName = nullName(data, abbrevoff,
- abbrev[mTypes[lastdst] & 0xFF]);
- }
- if (laststd >= 0) {
- mStandardName = nullName(data, abbrevoff,
- abbrev[mTypes[laststd] & 0xFF]);
- }
-
- // Use the latest non-DST offset if any as the raw offset
-
- if (laststd < 0) {
- laststd = 0;
- }
-
- if (laststd >= mTypes.length) {
- mRawOffset = mGmtOffs[0];
- } else {
- mRawOffset = mGmtOffs[mTypes[laststd] & 0xFF];
- }
-
- // Subtract the raw offset from all offsets so it can be changed
- // and affect them too.
- // Find whether there exist any observances of DST.
-
- for (int i = 0; i < mGmtOffs.length; i++) {
- mGmtOffs[i] -= mRawOffset;
-
- if (mIsDsts[i] != 0) {
- mUseDst = true;
- }
- }
-
- mRawOffset *= 1000;
- }
-
- @Override
- public int getOffset(@SuppressWarnings("unused") int era,
- int year, int month, int day,
- @SuppressWarnings("unused") int dayOfWeek,
- int millis) {
- // XXX This assumes Gregorian always; Calendar switches from
- // Julian to Gregorian in 1582. What calendar system are the
- // arguments supposed to come from?
-
- long calc = (year / 400) * MILLISECONDS_PER_400_YEARS;
- year %= 400;
-
- calc += year * (365 * MILLISECONDS_PER_DAY);
- calc += ((year + 3) / 4) * MILLISECONDS_PER_DAY;
-
- if (year > 0)
- calc -= ((year - 1) / 100) * MILLISECONDS_PER_DAY;
-
- boolean isLeap = (year == 0 || (year % 4 == 0 && year % 100 != 0));
- int[] mlen = isLeap ? LEAP : NORMAL;
-
- calc += mlen[month] * MILLISECONDS_PER_DAY;
- calc += (day - 1) * MILLISECONDS_PER_DAY;
- calc += millis;
-
- calc -= mRawOffset;
- calc -= UNIX_OFFSET;
-
- return getOffset(calc);
- }
-
- @Override
- public int getOffset(long when) {
- int unix = (int) (when / 1000);
- int trans = Arrays.binarySearch(mTransitions, unix);
-
- if (trans == ~0) {
- return mGmtOffs[0] * 1000 + mRawOffset;
- }
- if (trans < 0) {
- trans = ~trans - 1;
- }
-
- return mGmtOffs[mTypes[trans] & 0xFF] * 1000 + mRawOffset;
- }
-
- @Override
- public int getRawOffset() {
- return mRawOffset;
- }
-
- @Override
- public void setRawOffset(int off) {
- mRawOffset = off;
- }
-
- @Override
- public boolean inDaylightTime(Date when) {
- int unix = (int) (when.getTime() / 1000);
- int trans = Arrays.binarySearch(mTransitions, unix);
-
- if (trans == ~0) {
- return mIsDsts[0] != 0;
- }
- if (trans < 0) {
- trans = ~trans - 1;
- }
-
- return mIsDsts[mTypes[trans] & 0xFF] != 0;
- }
-
- @Override
- public boolean useDaylightTime() {
- return mUseDst;
- }
-
- private int mRawOffset;
- private int[] mTransitions;
- private int[] mGmtOffs;
- private byte[] mTypes;
- private byte[] mIsDsts;
- private boolean mUseDst;
- private String mDaylightName;
- private String mStandardName;
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof ZoneInfo)) {
- return false;
- }
- ZoneInfo other = (ZoneInfo) obj;
- return mUseDst == other.mUseDst
- && (mDaylightName == null ? other.mDaylightName == null :
- mDaylightName.equals(other.mDaylightName))
- && (mStandardName == null ? other.mStandardName == null :
- mStandardName.equals(other.mStandardName))
- && mRawOffset == other.mRawOffset
- // Arrays.equals returns true if both arrays are null
- && Arrays.equals(mGmtOffs, other.mGmtOffs)
- && Arrays.equals(mIsDsts, other.mIsDsts)
- && Arrays.equals(mTypes, other.mTypes)
- && Arrays.equals(mTransitions, other.mTransitions);
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((mDaylightName == null) ? 0 :
- mDaylightName.hashCode());
- result = prime * result + Arrays.hashCode(mGmtOffs);
- result = prime * result + Arrays.hashCode(mIsDsts);
- result = prime * result + mRawOffset;
- result = prime * result + ((mStandardName == null) ? 0 :
- mStandardName.hashCode());
- result = prime * result + Arrays.hashCode(mTransitions);
- result = prime * result + Arrays.hashCode(mTypes);
- result = prime * result + (mUseDst ? 1231 : 1237);
- return result;
- }
-}
diff --git a/libc/tools/zoneinfo/generate b/libc/tools/zoneinfo/generate
index ab2617f..fd4e6d0 100755
--- a/libc/tools/zoneinfo/generate
+++ b/libc/tools/zoneinfo/generate
@@ -89,9 +89,11 @@
setup.close()
print 'Calling ZoneCompactor...'
+ libcore_src_dir = '%s/../libcore/luni/src/main/java/' % bionic_dir
subprocess.check_call(['javac', '-d', '.',
'%s/ZoneCompactor.java' % bionic_libc_tools_zoneinfo_dir,
- '%s/ZoneInfo.java' % bionic_libc_tools_zoneinfo_dir])
+ '%s/libcore/util/ZoneInfo.java' % libcore_src_dir,
+ '%s/libcore/io/BufferIterator.java' % libcore_src_dir])
subprocess.check_call(['java', 'ZoneCompactor', 'setup', 'data'])
print 'Updating bionic from %s to %s...' % (current_tzdata_version(), version)