17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 1996-2014, International Business Machines Corporation and
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved.
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.impl;
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.IOException;
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.nio.ByteBuffer;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Arrays;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* <p>Internal reader class for ICU data file uname.dat containing
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* Unicode codepoint name data.</p>
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* <p>This class simply reads unames.icu, authenticates that it is a valid
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* ICU data file and split its contents up into blocks of data for use in
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* <a href=UCharacterName.html>com.ibm.icu.impl.UCharacterName</a>.
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* </p>
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* <p>unames.icu which is in big-endian format is jared together with this
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* package.</p>
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* @author Syn Wee Quek
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* @since release 2.1, February 1st 2002
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertfinal class UCharacterNameReader implements ICUBinary.Authenticate
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert{
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // public methods ----------------------------------------------------
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean isDataVersionAcceptable(byte version[])
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return version[0] == 1;
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // protected constructor ---------------------------------------------
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * <p>Protected constructor.</p>
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @param bytes ICU uprop.dat file buffer
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @exception IOException throw if data file fails authentication
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected UCharacterNameReader(ByteBuffer bytes) throws IOException
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ICUBinary.readHeader(bytes, DATA_FORMAT_ID_, this);
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_byteBuffer_ = bytes;
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // protected methods -------------------------------------------------
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * Read and break up the stream of data passed in as arguments
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * and fills up UCharacterName.
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * If unsuccessful false will be returned.
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @param data instance of datablock
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @exception IOException thrown when there's a data error.
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected void read(UCharacterName data) throws IOException
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // reading index
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_tokenstringindex_ = m_byteBuffer_.getInt();
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_groupindex_       = m_byteBuffer_.getInt();
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_groupstringindex_ = m_byteBuffer_.getInt();
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_algnamesindex_    = m_byteBuffer_.getInt();
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // reading tokens
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int count = m_byteBuffer_.getChar();
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char token[] = new char[count];
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (char i = 0; i < count; i ++) {
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            token[i] = m_byteBuffer_.getChar();
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int size = m_groupindex_ - m_tokenstringindex_;
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        byte tokenstr[] = new byte[size];
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_byteBuffer_.get(tokenstr);
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        data.setToken(token, tokenstr);
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // reading the group information records
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        count = m_byteBuffer_.getChar();
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        data.setGroupCountSize(count, GROUP_INFO_SIZE_);
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        count *= GROUP_INFO_SIZE_;
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char group[] = new char[count];
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < count; i ++) {
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            group[i] = m_byteBuffer_.getChar();
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        size = m_algnamesindex_ - m_groupstringindex_;
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        byte groupstring[] = new byte[size];
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_byteBuffer_.get(groupstring);
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        data.setGroup(group, groupstring);
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        count = m_byteBuffer_.getInt();
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        UCharacterName.AlgorithmName alg[] =
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                 new UCharacterName.AlgorithmName[count];
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < count; i ++)
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            UCharacterName.AlgorithmName an = readAlg();
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (an == null) {
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                throw new IOException("unames.icu read error: Algorithmic names creation error");
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            alg[i] = an;
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        data.setAlgorithm(alg);
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * <p>Checking the file for the correct format.</p>
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @param dataformatid
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @param dataformatversion
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @return true if the file format version is correct
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ///CLOVER:OFF
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected boolean authenticate(byte dataformatid[],
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                   byte dataformatversion[])
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return Arrays.equals(
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ICUBinary.getVersionByteArrayFromCompactInt(DATA_FORMAT_ID_),
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                dataformatid) &&
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert               isDataVersionAcceptable(dataformatversion);
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    ///CLOVER:ON
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // private variables -------------------------------------------------
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * Byte buffer for names
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private ByteBuffer m_byteBuffer_;
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * Size of the group information block in number of char
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int GROUP_INFO_SIZE_ = 3;
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * Index of the offset information
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int m_tokenstringindex_;
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int m_groupindex_;
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int m_groupstringindex_;
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int m_algnamesindex_;
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * Size of an algorithmic name information group
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * start code point size + end code point size + type size + variant size +
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * size of data size
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int ALG_INFO_SIZE_ = 12;
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * File format id that this class understands.
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int DATA_FORMAT_ID_ = 0x756E616D;
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // private methods ---------------------------------------------------
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * Reads an individual record of AlgorithmNames
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @return an instance of AlgorithNames if read is successful otherwise null
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @exception IOException thrown when file read error occurs or data is corrupted
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private UCharacterName.AlgorithmName readAlg() throws IOException
1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        UCharacterName.AlgorithmName result =
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                       new UCharacterName.AlgorithmName();
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int rangestart = m_byteBuffer_.getInt();
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int rangeend   = m_byteBuffer_.getInt();
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        byte type      = m_byteBuffer_.get();
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        byte variant   = m_byteBuffer_.get();
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!result.setInfo(rangestart, rangeend, type, variant)) {
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null;
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int size = m_byteBuffer_.getChar();
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (type == UCharacterName.AlgorithmName.TYPE_1_)
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            char factor[] = new char[variant];
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int j = 0; j < variant; j ++) {
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                factor[j] = m_byteBuffer_.getChar();
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.setFactor(factor);
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            size -= (variant << 1);
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StringBuilder prefix = new StringBuilder();
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char c = (char)(m_byteBuffer_.get() & 0x00FF);
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (c != 0)
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            prefix.append(c);
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            c = (char)(m_byteBuffer_.get() & 0x00FF);
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result.setPrefix(prefix.toString());
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        size -= (ALG_INFO_SIZE_ + prefix.length() + 1);
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (size > 0)
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte string[] = new byte[size];
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            m_byteBuffer_.get(string);
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.setFactorString(string);
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result;
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
207