001: /**
002: *******************************************************************************
003: * Copyright (C) 1996-2006, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: */package com.ibm.icu.impl;
007:
008: import java.io.InputStream;
009: import java.io.DataInputStream;
010: import java.io.IOException;
011: import java.util.Arrays;
012:
013: /**
014: * <p>Internal reader class for ICU data file uname.dat containing
015: * Unicode codepoint name data.</p>
016: * <p>This class simply reads unames.icu, authenticates that it is a valid
017: * ICU data file and split its contents up into blocks of data for use in
018: * <a href=UCharacterName.html>com.ibm.icu.impl.UCharacterName</a>.
019: * </p>
020: * <p>unames.icu which is in big-endian format is jared together with this
021: * package.</p>
022: * @author Syn Wee Quek
023: * @since release 2.1, February 1st 2002
024: * @draft 2.1
025: */
026:
027: final class UCharacterNameReader implements ICUBinary.Authenticate {
028: // public methods ----------------------------------------------------
029:
030: public boolean isDataVersionAcceptable(byte version[]) {
031: return version[0] == DATA_FORMAT_VERSION_[0];
032: }
033:
034: // protected constructor ---------------------------------------------
035:
036: /**
037: * <p>Protected constructor.</p>
038: * @param inputStream ICU uprop.dat file input stream
039: * @exception IOException throw if data file fails authentication
040: * @draft 2.1
041: */
042: protected UCharacterNameReader(InputStream inputStream)
043: throws IOException {
044: ICUBinary.readHeader(inputStream, DATA_FORMAT_ID_, this );
045: m_dataInputStream_ = new DataInputStream(inputStream);
046: }
047:
048: // protected methods -------------------------------------------------
049:
050: /**
051: * Read and break up the stream of data passed in as arguments
052: * and fills up UCharacterName.
053: * If unsuccessful false will be returned.
054: * @param data instance of datablock
055: * @exception IOException thrown when there's a data error.
056: */
057: protected void read(UCharacterName data) throws IOException {
058: // reading index
059: m_tokenstringindex_ = m_dataInputStream_.readInt();
060: m_groupindex_ = m_dataInputStream_.readInt();
061: m_groupstringindex_ = m_dataInputStream_.readInt();
062: m_algnamesindex_ = m_dataInputStream_.readInt();
063:
064: // reading tokens
065: int count = m_dataInputStream_.readChar();
066: char token[] = new char[count];
067: for (char i = 0; i < count; i++) {
068: token[i] = m_dataInputStream_.readChar();
069: }
070: int size = m_groupindex_ - m_tokenstringindex_;
071: byte tokenstr[] = new byte[size];
072: m_dataInputStream_.readFully(tokenstr);
073: data.setToken(token, tokenstr);
074:
075: // reading the group information records
076: count = m_dataInputStream_.readChar();
077: data.setGroupCountSize(count, GROUP_INFO_SIZE_);
078: count *= GROUP_INFO_SIZE_;
079: char group[] = new char[count];
080: for (int i = 0; i < count; i++) {
081: group[i] = m_dataInputStream_.readChar();
082: }
083:
084: size = m_algnamesindex_ - m_groupstringindex_;
085: byte groupstring[] = new byte[size];
086: m_dataInputStream_.readFully(groupstring);
087:
088: data.setGroup(group, groupstring);
089:
090: count = m_dataInputStream_.readInt();
091: UCharacterName.AlgorithmName alg[] = new UCharacterName.AlgorithmName[count];
092:
093: for (int i = 0; i < count; i++) {
094: UCharacterName.AlgorithmName an = readAlg();
095: if (an == null) {
096: throw new IOException(
097: "unames.icu read error: Algorithmic names creation error");
098: }
099: alg[i] = an;
100: }
101: data.setAlgorithm(alg);
102: }
103:
104: /**
105: * <p>Checking the file for the correct format.</p>
106: * @param dataformatid
107: * @param dataformatversion
108: * @return true if the file format version is correct
109: * @draft 2.1
110: */
111: ///CLOVER:OFF
112: protected boolean authenticate(byte dataformatid[],
113: byte dataformatversion[]) {
114: return Arrays.equals(DATA_FORMAT_ID_, dataformatid)
115: && Arrays.equals(DATA_FORMAT_VERSION_,
116: dataformatversion);
117: }
118:
119: ///CLOVER:ON
120:
121: // private variables -------------------------------------------------
122:
123: /**
124: * Data input stream for names
125: */
126: private DataInputStream m_dataInputStream_;
127: /**
128: * Size of the group information block in number of char
129: */
130: private static final int GROUP_INFO_SIZE_ = 3;
131:
132: /**
133: * Index of the offset information
134: */
135: private int m_tokenstringindex_;
136: private int m_groupindex_;
137: private int m_groupstringindex_;
138: private int m_algnamesindex_;
139:
140: /**
141: * Size of an algorithmic name information group
142: * start code point size + end code point size + type size + variant size +
143: * size of data size
144: */
145: private static final int ALG_INFO_SIZE_ = 12;
146:
147: /**
148: * File format version and id that this class understands.
149: * No guarantees are made if a older version is used
150: */
151: private static final byte DATA_FORMAT_VERSION_[] = { (byte) 0x1,
152: (byte) 0x0, (byte) 0x0, (byte) 0x0 };
153: private static final byte DATA_FORMAT_ID_[] = { (byte) 0x75,
154: (byte) 0x6E, (byte) 0x61, (byte) 0x6D };
155:
156: // private methods ---------------------------------------------------
157:
158: /**
159: * Reads an individual record of AlgorithmNames
160: * @return an instance of AlgorithNames if read is successful otherwise null
161: * @exception IOException thrown when file read error occurs or data is corrupted
162: */
163: private UCharacterName.AlgorithmName readAlg() throws IOException {
164: UCharacterName.AlgorithmName result = new UCharacterName.AlgorithmName();
165: int rangestart = m_dataInputStream_.readInt();
166: int rangeend = m_dataInputStream_.readInt();
167: byte type = m_dataInputStream_.readByte();
168: byte variant = m_dataInputStream_.readByte();
169: if (!result.setInfo(rangestart, rangeend, type, variant)) {
170: return null;
171: }
172:
173: int size = m_dataInputStream_.readChar();
174: if (type == UCharacterName.AlgorithmName.TYPE_1_) {
175: char factor[] = new char[variant];
176: for (int j = 0; j < variant; j++) {
177: factor[j] = m_dataInputStream_.readChar();
178: }
179:
180: result.setFactor(factor);
181: size -= (variant << 1);
182: }
183:
184: StringBuffer prefix = new StringBuffer();
185: char c = (char) (m_dataInputStream_.readByte() & 0x00FF);
186: while (c != 0) {
187: prefix.append(c);
188: c = (char) (m_dataInputStream_.readByte() & 0x00FF);
189: }
190:
191: result.setPrefix(prefix.toString());
192:
193: size -= (ALG_INFO_SIZE_ + prefix.length() + 1);
194:
195: if (size > 0) {
196: byte string[] = new byte[size];
197: m_dataInputStream_.readFully(string);
198: result.setFactorString(string);
199: }
200: return result;
201: }
202: }
|