2 *******************************************************************************
3 * Copyright (C) 1996-2010, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
7 package com.ibm.icu.impl;
9 import java.io.DataInputStream;
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.util.Arrays;
15 * <p>Internal reader class for ICU data file uname.dat containing
16 * Unicode codepoint name data.</p>
17 * <p>This class simply reads unames.icu, authenticates that it is a valid
18 * ICU data file and split its contents up into blocks of data for use in
19 * <a href=UCharacterName.html>com.ibm.icu.impl.UCharacterName</a>.
21 * <p>unames.icu which is in big-endian format is jared together with this
23 * @author Syn Wee Quek
24 * @since release 2.1, February 1st 2002
27 final class UCharacterNameReader implements ICUBinary.Authenticate
29 // public methods ----------------------------------------------------
31 public boolean isDataVersionAcceptable(byte version[])
33 return version[0] == DATA_FORMAT_VERSION_[0];
36 // protected constructor ---------------------------------------------
39 * <p>Protected constructor.</p>
40 * @param inputStream ICU uprop.dat file input stream
41 * @exception IOException throw if data file fails authentication
43 protected UCharacterNameReader(InputStream inputStream)
46 ICUBinary.readHeader(inputStream, DATA_FORMAT_ID_, this);
47 m_dataInputStream_ = new DataInputStream(inputStream);
50 // protected methods -------------------------------------------------
53 * Read and break up the stream of data passed in as arguments
54 * and fills up UCharacterName.
55 * If unsuccessful false will be returned.
56 * @param data instance of datablock
57 * @exception IOException thrown when there's a data error.
59 protected void read(UCharacterName data) throws IOException
62 m_tokenstringindex_ = m_dataInputStream_.readInt();
63 m_groupindex_ = m_dataInputStream_.readInt();
64 m_groupstringindex_ = m_dataInputStream_.readInt();
65 m_algnamesindex_ = m_dataInputStream_.readInt();
68 int count = m_dataInputStream_.readChar();
69 char token[] = new char[count];
70 for (char i = 0; i < count; i ++) {
71 token[i] = m_dataInputStream_.readChar();
73 int size = m_groupindex_ - m_tokenstringindex_;
74 byte tokenstr[] = new byte[size];
75 m_dataInputStream_.readFully(tokenstr);
76 data.setToken(token, tokenstr);
78 // reading the group information records
79 count = m_dataInputStream_.readChar();
80 data.setGroupCountSize(count, GROUP_INFO_SIZE_);
81 count *= GROUP_INFO_SIZE_;
82 char group[] = new char[count];
83 for (int i = 0; i < count; i ++) {
84 group[i] = m_dataInputStream_.readChar();
87 size = m_algnamesindex_ - m_groupstringindex_;
88 byte groupstring[] = new byte[size];
89 m_dataInputStream_.readFully(groupstring);
91 data.setGroup(group, groupstring);
93 count = m_dataInputStream_.readInt();
94 UCharacterName.AlgorithmName alg[] =
95 new UCharacterName.AlgorithmName[count];
97 for (int i = 0; i < count; i ++)
99 UCharacterName.AlgorithmName an = readAlg();
101 throw new IOException("unames.icu read error: Algorithmic names creation error");
105 data.setAlgorithm(alg);
109 * <p>Checking the file for the correct format.</p>
110 * @param dataformatid
111 * @param dataformatversion
112 * @return true if the file format version is correct
115 protected boolean authenticate(byte dataformatid[],
116 byte dataformatversion[])
118 return Arrays.equals(DATA_FORMAT_ID_, dataformatid) &&
119 Arrays.equals(DATA_FORMAT_VERSION_, dataformatversion);
123 // private variables -------------------------------------------------
126 * Data input stream for names
128 private DataInputStream m_dataInputStream_;
130 * Size of the group information block in number of char
132 private static final int GROUP_INFO_SIZE_ = 3;
135 * Index of the offset information
137 private int m_tokenstringindex_;
138 private int m_groupindex_;
139 private int m_groupstringindex_;
140 private int m_algnamesindex_;
143 * Size of an algorithmic name information group
144 * start code point size + end code point size + type size + variant size +
147 private static final int ALG_INFO_SIZE_ = 12;
150 * File format version and id that this class understands.
151 * No guarantees are made if a older version is used
153 private static final byte DATA_FORMAT_VERSION_[] =
154 {(byte)0x1, (byte)0x0, (byte)0x0, (byte)0x0};
155 private static final byte DATA_FORMAT_ID_[] = {(byte)0x75, (byte)0x6E,
156 (byte)0x61, (byte)0x6D};
158 // private methods ---------------------------------------------------
161 * Reads an individual record of AlgorithmNames
162 * @return an instance of AlgorithNames if read is successful otherwise null
163 * @exception IOException thrown when file read error occurs or data is corrupted
165 private UCharacterName.AlgorithmName readAlg() throws IOException
167 UCharacterName.AlgorithmName result =
168 new UCharacterName.AlgorithmName();
169 int rangestart = m_dataInputStream_.readInt();
170 int rangeend = m_dataInputStream_.readInt();
171 byte type = m_dataInputStream_.readByte();
172 byte variant = m_dataInputStream_.readByte();
173 if (!result.setInfo(rangestart, rangeend, type, variant)) {
177 int size = m_dataInputStream_.readChar();
178 if (type == UCharacterName.AlgorithmName.TYPE_1_)
180 char factor[] = new char[variant];
181 for (int j = 0; j < variant; j ++) {
182 factor[j] = m_dataInputStream_.readChar();
185 result.setFactor(factor);
186 size -= (variant << 1);
189 StringBuilder prefix = new StringBuilder();
190 char c = (char)(m_dataInputStream_.readByte() & 0x00FF);
194 c = (char)(m_dataInputStream_.readByte() & 0x00FF);
197 result.setPrefix(prefix.toString());
199 size -= (ALG_INFO_SIZE_ + prefix.length() + 1);
203 byte string[] = new byte[size];
204 m_dataInputStream_.readFully(string);
205 result.setFactorString(string);