Пример #1
0
        private void ReadData(ByteBuffer bytes)
        {
            // read the header
            ICUBinary.ReadHeader(bytes, FMT, new IsAcceptable());

            // read indexes[]
            int i, count;

            count = bytes.GetInt32();
            if (count < IX_TOP)
            {
                throw new IOException("indexes[0] too small in " + DATA_FILE_NAME);
            }
            indexes = new int[count];

            indexes[0] = count;
            for (i = 1; i < count; ++i)
            {
                indexes[i] = bytes.GetInt32();
            }

            // read the trie
            trie = Trie2_16.CreateFromSerialized(bytes);
            int expectedTrieLength = indexes[IX_TRIE_SIZE];
            int trieLength         = trie.SerializedLength;

            if (trieLength > expectedTrieLength)
            {
                throw new IOException(DATA_FILE_NAME + ": not enough bytes for the trie");
            }
            // skip padding after trie bytes
            ICUBinary.SkipBytes(bytes, expectedTrieLength - trieLength);

            // read mirrors[]
            count = indexes[IX_MIRROR_LENGTH];
            if (count > 0)
            {
                mirrors = ICUBinary.GetInt32s(bytes, count, 0);
            }

            // read jgArray[]
            count   = indexes[IX_JG_LIMIT] - indexes[IX_JG_START];
            jgArray = new byte[count];
            bytes.Get(jgArray);

            // read jgArray2[]
            count    = indexes[IX_JG_LIMIT2] - indexes[IX_JG_START2];
            jgArray2 = new byte[count];
            bytes.Get(jgArray2);
        }
Пример #2
0
        private void ReadData(ByteBuffer bytes)
        {
            // read the header
            ICUBinary.ReadHeader(bytes, FMT, new IsAcceptable());

            // read indexes[]
            int count = bytes.GetInt32();

            if (count < IX_TOP)
            {
                throw new IOException("indexes[0] too small in " + DATA_FILE_NAME);
            }
            indexes = new int[count];

            indexes[0] = count;
            for (int i = 1; i < count; ++i)
            {
                indexes[i] = bytes.GetInt32();
            }

            // read the trie
            trie = Trie2_16.CreateFromSerialized(bytes);
            int expectedTrieLength = indexes[IX_TRIE_SIZE];
            int trieLength         = trie.GetSerializedLength();

            if (trieLength > expectedTrieLength)
            {
                throw new IOException(DATA_FILE_NAME + ": not enough bytes for the trie");
            }
            // skip padding after trie bytes
            ICUBinary.SkipBytes(bytes, expectedTrieLength - trieLength);

            // read exceptions[]
            count = indexes[IX_EXC_LENGTH];
            if (count > 0)
            {
                exceptions = ICUBinary.GetString(bytes, count, 0);
            }

            // read unfold[]
            count = indexes[IX_UNFOLD_LENGTH];
            if (count > 0)
            {
                unfold = ICUBinary.GetChars(bytes, count, 0);
            }
        }
Пример #3
0
        /// <summary>
        /// Create a <see cref="Trie2"/> from its serialized form.  Inverse of utrie2_serialize().
        /// </summary>
        /// <remarks>
        /// Reads from the current position and leaves the buffer after the end of the trie.
        /// <para/>
        /// The serialized format is identical between ICU4C, ICU4J, and ICU4N, so this function
        /// will work with serialized <see cref="Trie2"/>s from any.
        /// <para/>
        /// The actual type of the returned <see cref="Trie2"/> will be either <see cref="Trie2_16"/> or <see cref="Trie2_32"/>, depending
        /// on the width of the data.
        /// <para/>
        /// To obtain the width of the <see cref="Trie2"/>, check the actual class type of the returned <see cref="Trie2"/>.
        /// Or use the <see cref="Trie2_16.CreateFromSerialized(ByteBuffer)"/> or <see cref="Trie2_32.CreateFromSerialized(ByteBuffer)"/> method, which will
        /// return only <see cref="Trie"/>s of their specific type/size.
        /// <para/>
        /// The serialized <see cref="Trie2"/> on the stream may be in either little or big endian byte order.
        /// This allows using serialized <see cref="Trie"/>s from ICU4C without needing to consider the
        /// byte order of the system that created them.
        /// </remarks>
        /// <param name="bytes">A byte buffer to the serialized form of a UTrie2.</param>
        /// <returns>An unserialized <see cref="Trie2"/>, ready for use.</returns>
        /// <exception cref="ArgumentException">If the stream does not contain a serialized <see cref="Trie2"/>.</exception>
        /// <exception cref="IOException">If a read error occurs in the buffer.</exception>
        public static Trie2 CreateFromSerialized(ByteBuffer bytes) // ICU4N TODO: API Create overload that accepts byte[]
        {
            //    From ICU4C utrie2_impl.h
            //    * Trie2 data structure in serialized form:
            //     *
            //     * UTrie2Header header;
            //     * uint16_t index[header.index2Length];
            //     * uint16_t data[header.shiftedDataLength<<2];  -- or uint32_t data[...]
            //     * @internal
            //     */
            //    typedef struct UTrie2Header {
            //        /** "Tri2" in big-endian US-ASCII (0x54726932) */
            //        uint32_t signature;

            //       /**
            //         * options bit field:
            //         * 15.. 4   reserved (0)
            //         *  3.. 0   UTrie2ValueBits valueBits
            //         */
            //        uint16_t options;
            //
            //        /** UTRIE2_INDEX_1_OFFSET..UTRIE2_MAX_INDEX_LENGTH */
            //        uint16_t indexLength;
            //
            //        /** (UTRIE2_DATA_START_OFFSET..UTRIE2_MAX_DATA_LENGTH)>>UTRIE2_INDEX_SHIFT */
            //        uint16_t shiftedDataLength;
            //
            //        /** Null index and data blocks, not shifted. */
            //        uint16_t index2NullOffset, dataNullOffset;
            //
            //        /**
            //         * First code point of the single-value range ending with U+10ffff,
            //         * rounded up and then shifted right by UTRIE2_SHIFT_1.
            //         */
            //        uint16_t shiftedHighStart;
            //    } UTrie2Header;

            ByteOrder outerByteOrder = bytes.Order;

            try
            {
                UTrie2Header header = new UTrie2Header();

                /* check the signature */
                header.signature = bytes.GetInt32();
                switch (header.signature)
                {
                case 0x54726932:
                    // The buffer is already set to the trie data byte order.
                    break;

                case 0x32697254:
                    // Temporarily reverse the byte order.
                    bool isBigEndian = outerByteOrder == ByteOrder.BigEndian;
                    bytes.Order      = isBigEndian ? ByteOrder.LittleEndian : ByteOrder.BigEndian;
                    header.signature = 0x54726932;
                    break;

                default:
                    throw new ArgumentException("Buffer does not contain a serialized UTrie2");
                }

                header.options           = bytes.GetChar();
                header.indexLength       = bytes.GetChar();
                header.shiftedDataLength = bytes.GetChar();
                header.index2NullOffset  = bytes.GetChar();
                header.dataNullOffset    = bytes.GetChar();
                header.shiftedHighStart  = bytes.GetChar();

                // Trie2 data width - 0: 16 bits
                //                    1: 32 bits
                if ((header.options & UTRIE2_OPTIONS_VALUE_BITS_MASK) > 1)
                {
                    throw new ArgumentException("UTrie2 serialized format error.");
                }
                ValueWidth width;
                Trie2      This;
                if ((header.options & UTRIE2_OPTIONS_VALUE_BITS_MASK) == 0)
                {
                    width = ValueWidth.BITS_16;
                    This  = new Trie2_16();
                }
                else
                {
                    width = ValueWidth.BITS_32;
                    This  = new Trie2_32();
                }
                This.header = header;

                /* get the length values and offsets */
                This.indexLength      = header.indexLength;
                This.dataLength       = header.shiftedDataLength << UTRIE2_INDEX_SHIFT;
                This.index2NullOffset = header.index2NullOffset;
                This.dataNullOffset   = header.dataNullOffset;
                This.highStart        = header.shiftedHighStart << UTRIE2_SHIFT_1;
                This.highValueIndex   = This.dataLength - UTRIE2_DATA_GRANULARITY;
                if (width == ValueWidth.BITS_16)
                {
                    This.highValueIndex += This.indexLength;
                }

                // Allocate the Trie2 index array. If the data width is 16 bits, the array also
                // includes the space for the data.

                int indexArraySize = This.indexLength;
                if (width == ValueWidth.BITS_16)
                {
                    indexArraySize += This.dataLength;
                }

                /* Read in the index */
                This.index = ICUBinary.GetChars(bytes, indexArraySize, 0);

                /* Read in the data. 16 bit data goes in the same array as the index.
                 * 32 bit data goes in its own separate data array.
                 */
                if (width == ValueWidth.BITS_16)
                {
                    This.data16 = This.indexLength;
                }
                else
                {
                    This.data32 = ICUBinary.GetInt32s(bytes, This.dataLength, 0);
                }

                switch (width)
                {
                case ValueWidth.BITS_16:
                    This.data32       = null;
                    This.initialValue = This.index[This.dataNullOffset];
                    This.errorValue   = This.index[This.data16 + UTRIE2_BAD_UTF8_DATA_OFFSET];
                    break;

                case ValueWidth.BITS_32:
                    This.data16       = 0;
                    This.initialValue = This.data32[This.dataNullOffset];
                    This.errorValue   = This.data32[UTRIE2_BAD_UTF8_DATA_OFFSET];
                    break;

                default:
                    throw new ArgumentException("UTrie2 serialized format error.");
                }

                return(This);
            }
            finally
            {
                bytes.Order = outerByteOrder;
            }
        }