1/* 2 ******************************************************************************* 3 * Copyright (C) 1996-2014, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ******************************************************************************* 6 */ 7 8package com.ibm.icu.impl; 9 10import java.io.IOException; 11import java.nio.ByteBuffer; 12import java.util.Arrays; 13 14/** 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>. 20* </p> 21* <p>unames.icu which is in big-endian format is jared together with this 22* package.</p> 23* @author Syn Wee Quek 24* @since release 2.1, February 1st 2002 25*/ 26 27final class UCharacterNameReader implements ICUBinary.Authenticate 28{ 29 // public methods ---------------------------------------------------- 30 31 public boolean isDataVersionAcceptable(byte version[]) 32 { 33 return version[0] == 1; 34 } 35 36 // protected constructor --------------------------------------------- 37 38 /** 39 * <p>Protected constructor.</p> 40 * @param bytes ICU uprop.dat file buffer 41 * @exception IOException throw if data file fails authentication 42 */ 43 protected UCharacterNameReader(ByteBuffer bytes) throws IOException 44 { 45 ICUBinary.readHeader(bytes, DATA_FORMAT_ID_, this); 46 m_byteBuffer_ = bytes; 47 } 48 49 // protected methods ------------------------------------------------- 50 51 /** 52 * Read and break up the stream of data passed in as arguments 53 * and fills up UCharacterName. 54 * If unsuccessful false will be returned. 55 * @param data instance of datablock 56 * @exception IOException thrown when there's a data error. 57 */ 58 protected void read(UCharacterName data) throws IOException 59 { 60 // reading index 61 m_tokenstringindex_ = m_byteBuffer_.getInt(); 62 m_groupindex_ = m_byteBuffer_.getInt(); 63 m_groupstringindex_ = m_byteBuffer_.getInt(); 64 m_algnamesindex_ = m_byteBuffer_.getInt(); 65 66 // reading tokens 67 int count = m_byteBuffer_.getChar(); 68 char token[] = new char[count]; 69 for (char i = 0; i < count; i ++) { 70 token[i] = m_byteBuffer_.getChar(); 71 } 72 int size = m_groupindex_ - m_tokenstringindex_; 73 byte tokenstr[] = new byte[size]; 74 m_byteBuffer_.get(tokenstr); 75 data.setToken(token, tokenstr); 76 77 // reading the group information records 78 count = m_byteBuffer_.getChar(); 79 data.setGroupCountSize(count, GROUP_INFO_SIZE_); 80 count *= GROUP_INFO_SIZE_; 81 char group[] = new char[count]; 82 for (int i = 0; i < count; i ++) { 83 group[i] = m_byteBuffer_.getChar(); 84 } 85 86 size = m_algnamesindex_ - m_groupstringindex_; 87 byte groupstring[] = new byte[size]; 88 m_byteBuffer_.get(groupstring); 89 90 data.setGroup(group, groupstring); 91 92 count = m_byteBuffer_.getInt(); 93 UCharacterName.AlgorithmName alg[] = 94 new UCharacterName.AlgorithmName[count]; 95 96 for (int i = 0; i < count; i ++) 97 { 98 UCharacterName.AlgorithmName an = readAlg(); 99 if (an == null) { 100 throw new IOException("unames.icu read error: Algorithmic names creation error"); 101 } 102 alg[i] = an; 103 } 104 data.setAlgorithm(alg); 105 } 106 107 /** 108 * <p>Checking the file for the correct format.</p> 109 * @param dataformatid 110 * @param dataformatversion 111 * @return true if the file format version is correct 112 */ 113 ///CLOVER:OFF 114 protected boolean authenticate(byte dataformatid[], 115 byte dataformatversion[]) 116 { 117 return Arrays.equals( 118 ICUBinary.getVersionByteArrayFromCompactInt(DATA_FORMAT_ID_), 119 dataformatid) && 120 isDataVersionAcceptable(dataformatversion); 121 } 122 ///CLOVER:ON 123 124 // private variables ------------------------------------------------- 125 126 /** 127 * Byte buffer for names 128 */ 129 private ByteBuffer m_byteBuffer_; 130 /** 131 * Size of the group information block in number of char 132 */ 133 private static final int GROUP_INFO_SIZE_ = 3; 134 135 /** 136 * Index of the offset information 137 */ 138 private int m_tokenstringindex_; 139 private int m_groupindex_; 140 private int m_groupstringindex_; 141 private int m_algnamesindex_; 142 143 /** 144 * Size of an algorithmic name information group 145 * start code point size + end code point size + type size + variant size + 146 * size of data size 147 */ 148 private static final int ALG_INFO_SIZE_ = 12; 149 150 /** 151 * File format id that this class understands. 152 */ 153 private static final int DATA_FORMAT_ID_ = 0x756E616D; 154 155 // private methods --------------------------------------------------- 156 157 /** 158 * Reads an individual record of AlgorithmNames 159 * @return an instance of AlgorithNames if read is successful otherwise null 160 * @exception IOException thrown when file read error occurs or data is corrupted 161 */ 162 private UCharacterName.AlgorithmName readAlg() throws IOException 163 { 164 UCharacterName.AlgorithmName result = 165 new UCharacterName.AlgorithmName(); 166 int rangestart = m_byteBuffer_.getInt(); 167 int rangeend = m_byteBuffer_.getInt(); 168 byte type = m_byteBuffer_.get(); 169 byte variant = m_byteBuffer_.get(); 170 if (!result.setInfo(rangestart, rangeend, type, variant)) { 171 return null; 172 } 173 174 int size = m_byteBuffer_.getChar(); 175 if (type == UCharacterName.AlgorithmName.TYPE_1_) 176 { 177 char factor[] = new char[variant]; 178 for (int j = 0; j < variant; j ++) { 179 factor[j] = m_byteBuffer_.getChar(); 180 } 181 182 result.setFactor(factor); 183 size -= (variant << 1); 184 } 185 186 StringBuilder prefix = new StringBuilder(); 187 char c = (char)(m_byteBuffer_.get() & 0x00FF); 188 while (c != 0) 189 { 190 prefix.append(c); 191 c = (char)(m_byteBuffer_.get() & 0x00FF); 192 } 193 194 result.setPrefix(prefix.toString()); 195 196 size -= (ALG_INFO_SIZE_ + prefix.length() + 1); 197 198 if (size > 0) 199 { 200 byte string[] = new byte[size]; 201 m_byteBuffer_.get(string); 202 result.setFactorString(string); 203 } 204 return result; 205 } 206} 207