// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
 *******************************************************************************
 * Copyright (C) 2006-2015, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 */

package com.ibm.icu.charset;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.IntBuffer;

import com.ibm.icu.charset.CharsetMBCS.MBCSHeader;
import com.ibm.icu.charset.CharsetMBCS.MBCSToUFallback;
import com.ibm.icu.charset.CharsetMBCS.UConverterMBCSTable;
import com.ibm.icu.impl.ICUBinary;
import com.ibm.icu.impl.InvalidFormatException;

/**
 * ucnvmbcs.h
 *
 * ICU conversion (.cnv) data file structure, following the usual UDataInfo
 * header.
 *
 * Format version: 6.2
 *
 * struct UConverterStaticData -- struct containing the converter name, IBM CCSID,
 *                                min/max bytes per character, etc.
 *                                see ucnv_bld.h
 *
 * --------------------
 *
 * The static data is followed by conversionType-specific data structures.
 * At the moment, there are only variations of MBCS converters. They all have
 * the same toUnicode structures, while the fromUnicode structures for SBCS
 * differ from those for other MBCS-style converters.
 *
 * _MBCSHeader.version 4.2 adds an optional conversion extension data structure.
 * If it is present, then an ICU version reading header versions 4.0 or 4.1
 * will be able to use the base table and ignore the extension.
 *
 * The unicodeMask in the static data is part of the base table data structure.
 * Especially, the UCNV_HAS_SUPPLEMENTARY flag determines the length of the
 * fromUnicode stage 1 array.
 * The static data unicodeMask refers only to the base table's properties if
 * a base table is included.
 * In an extension-only file, the static data unicodeMask is 0.
 * The extension data indexes have a separate field with the unicodeMask flags.
 *
 * MBCS-style data structure following the static data.
 * Offsets are counted in bytes from the beginning of the MBCS header structure.
 * Details about usage in comments in ucnvmbcs.c.
 *
 * struct _MBCSHeader (see the definition in this header file below)
 * contains 32-bit fields as follows:
 * 8 values:
 *  0   uint8_t[4]  MBCS version in UVersionInfo format (currently 4.2.0.0)
 *  1   uint32_t    countStates
 *  2   uint32_t    countToUFallbacks
 *  3   uint32_t    offsetToUCodeUnits
 *  4   uint32_t    offsetFromUTable
 *  5   uint32_t    offsetFromUBytes
 *  6   uint32_t    flags, bits:
 *                      31.. 8 offsetExtension -- _MBCSHeader.version 4.2 (ICU 2.8) and higher
 *                                                0 for older versions and if
 *                                                there is not extension structure
 *                       7.. 0 outputType
 *  7   uint32_t    fromUBytesLength -- _MBCSHeader.version 4.1 (ICU 2.4) and higher
 *                  counts bytes in fromUBytes[]
 *
 * if(outputType==MBCS_OUTPUT_EXT_ONLY) {
 *     -- base table name for extension-only table
 *     char baseTableName[variable]; -- with NUL plus padding for 4-alignment
 *
 *     -- all _MBCSHeader fields except for version and flags are 0
 * } else {
 *     -- normal base table with optional extension
 *
 *     int32_t stateTable[countStates][256];
 *
 *     struct _MBCSToUFallback { (fallbacks are sorted by offset)
 *         uint32_t offset;
 *         UChar32 codePoint;
 *     } toUFallbacks[countToUFallbacks];
 *
 *     uint16_t unicodeCodeUnits[(offsetFromUTable-offsetToUCodeUnits)/2];
 *                  (padded to an even number of units)
 *
 *     -- stage 1 tables
 *     if(staticData.unicodeMask&UCNV_HAS_SUPPLEMENTARY) {
 *         -- stage 1 table for all of Unicode
 *         uint16_t fromUTable[0x440]; (32-bit-aligned)
 *     } else {
 *         -- BMP-only tables have a smaller stage 1 table
 *         uint16_t fromUTable[0x40]; (32-bit-aligned)
 *     }
 *
 *     -- stage 2 tables
 *        length determined by top of stage 1 and bottom of stage 3 tables
 *     if(outputType==MBCS_OUTPUT_1) {
 *         -- SBCS: pure indexes
 *         uint16_t stage 2 indexes[?];
 *     } else {
 *         -- DBCS, MBCS, EBCDIC_STATEFUL, ...: roundtrip flags and indexes
 *         uint32_t stage 2 flags and indexes[?];
 *     }
 *
 *     -- stage 3 tables with byte results
 *     if(outputType==MBCS_OUTPUT_1) {
 *         -- SBCS: each 16-bit result contains flags and the result byte, see ucnvmbcs.c
 *         uint16_t fromUBytes[fromUBytesLength/2];
 *     } else {
 *         -- DBCS, MBCS, EBCDIC_STATEFUL, ... 2/3/4 bytes result, see ucnvmbcs.c
 *         uint8_t fromUBytes[fromUBytesLength]; or
 *         uint16_t fromUBytes[fromUBytesLength/2]; or
 *         uint32_t fromUBytes[fromUBytesLength/4];
 *     }
 * }
 *
 * -- extension table, details see ucnv_ext.h
 * int32_t indexes[>=32]; ...
 */
/*
 * ucnv_ext.h
 *
 * See icuhtml/design/conversion/conversion_extensions.html
 *
 * Conversion extensions serve two purposes:
 * 1. They support m:n mappings.
 * 2. They support extension-only conversion files that are used together
 *    with the regular conversion data in base files.
 *
 * A base file may contain an extension table (explicitly requested or
 * implicitly generated for m:n mappings), but its extension table is not
 * used when an extension-only file is used.
 *
 * It is an error if a base file contains any regular (not extension) mapping
 * from the same sequence as a mapping in the extension file
 * because the base mapping would hide the extension mapping.
 *
 *
 * Data for conversion extensions:
 *
 * One set of data structures per conversion direction (to/from Unicode).
 * The data structures are sorted by input units to allow for binary search.
 * Input sequences of more than one unit are handled like contraction tables
 * in collation:
 * The lookup value of a unit points to another table that is to be searched
 * for the next unit, recursively.
 *
 * For conversion from Unicode, the initial code point is looked up in
 * a 3-stage trie for speed,
 * with an additional table of unique results to save space.
 *
 * Long output strings are stored in separate arrays, with length and index
 * in the lookup tables.
 * Output results also include a flag distinguishing roundtrip from
 * (reverse) fallback mappings.
 *
 * Input Unicode strings must not begin or end with unpaired surrogates
 * to avoid problems with matches on parts of surrogate pairs.
 *
 * Mappings from multiple characters (code points or codepage state
 * table sequences) must be searched preferring the longest match.
 * For this to work and be efficient, the variable-width table must contain
 * all mappings that contain prefixes of the multiple characters.
 * If an extension table is built on top of a base table in another file
 * and a base table entry is a prefix of a multi-character mapping, then
 * this is an error.
 *
 *
 * Implementation note:
 *
 * Currently, the parser and several checks in the code limit the number
 * of UChars or bytes in a mapping to
 * UCNV_EXT_MAX_UCHARS and UCNV_EXT_MAX_BYTES, respectively,
 * which are output value limits in the data structure.
 *
 * For input, this is not strictly necessary - it is a hard limit only for the
 * buffers in UConverter that are used to store partial matches.
 *
 * Input sequences could otherwise be arbitrarily long if partial matches
 * need not be stored (i.e., if a sequence does not span several buffers with too
 * many units before the last buffer), although then results would differ
 * depending on whether partial matches exceed the limits or not,
 * which depends on the pattern of buffer sizes.
 *
 *
 * Data structure:
 *
 * int32_t indexes[>=32];
 *
 *   Array of indexes and lengths etc. The length of the array is at least 32.
 *   The actual length is stored in indexes[0] to be forward compatible.
 *
 *   Each index to another array is the number of bytes from indexes[].
 *   Each length of an array is the number of array base units in that array.
 *
 *   Some of the structures may not be present, in which case their indexes
 *   and lengths are 0.
 *
 *   Usage of indexes[i]:
 *   [0]  length of indexes[]
 *
 *   // to Unicode table
 *   [1]  index of toUTable[] (array of uint32_t)
 *   [2]  length of toUTable[]
 *   [3]  index of toUUChars[] (array of UChar)
 *   [4]  length of toUUChars[]
 *
 *   // from Unicode table, not for the initial code point
 *   [5]  index of fromUTableUChars[] (array of UChar)
 *   [6]  index of fromUTableValues[] (array of uint32_t)
 *   [7]  length of fromUTableUChars[] and fromUTableValues[]
 *   [8]  index of fromUBytes[] (array of char)
 *   [9]  length of fromUBytes[]
 *
 *   // from Unicode trie for initial-code point lookup
 *   [10] index of fromUStage12[] (combined array of uint16_t for stages 1 & 2)
 *   [11] length of stage 1 portion of fromUStage12[]
 *   [12] length of fromUStage12[]
 *   [13] index of fromUStage3[] (array of uint16_t indexes into fromUStage3b[])
 *   [14] length of fromUStage3[]
 *   [15] index of fromUStage3b[] (array of uint32_t like fromUTableValues[])
 *   [16] length of fromUStage3b[]
 *
 *   [17] Bit field containing numbers of bytes:
 *        31..24 reserved, 0
 *        23..16 maximum input bytes
 *        15.. 8 maximum output bytes
 *         7.. 0 maximum bytes per UChar
 *
 *   [18] Bit field containing numbers of UChars:
 *        31..24 reserved, 0
 *        23..16 maximum input UChars
 *        15.. 8 maximum output UChars
 *         7.. 0 maximum UChars per byte
 *
 *   [19] Bit field containing flags:
 *               (extension table unicodeMask)
 *         1     UCNV_HAS_SURROGATES flag for the extension table
 *         0     UCNV_HAS_SUPPLEMENTARY flag for the extension table
 *
 *   [20]..[30] reserved, 0
 *   [31] number of bytes for the entire extension structure
 *   [>31] reserved; there are indexes[0] indexes
 *
 *
 * uint32_t toUTable[];
 *
 *   Array of byte/value pairs for lookups for toUnicode conversion.
 *   The array is partitioned into sections like collation contraction tables.
 *   Each section contains one word with the number of following words and
 *   a default value for when the lookup in this section yields no match.
 *
 *   A section is sorted in ascending order of input bytes,
 *   allowing for fast linear or binary searches.
 *   The builder may store entries for a contiguous range of byte values
 *   (compare difference between the first and last one with count),
 *   which then allows for direct array access.
 *   The builder should always do this for the initial table section.
 *
 *   Entries may have 0 values, see below.
 *   No two entries in a section have the same byte values.
 *
 *   Each uint32_t contains an input byte value in bits 31..24 and the
 *   corresponding lookup value in bits 23..0.
 *   Interpret the value as follows:
 *     if(value==0) {
 *       no match, see below
 *     } else if(value<0x1f0000) {
 *       partial match - use value as index to the next toUTable section
 *       and match the next unit; (value indexes toUTable[value])
 *     } else {
 *       if(bit 23 set) {
 *         roundtrip;
 *       } else {
 *         fallback;
 *       }
 *       unset value bit 23;
 *       if(value<=0x2fffff) {
 *         (value-0x1f0000) is a code point; (BMP: value<=0x1fffff)
 *       } else {
 *         bits 17..0 (value&0x3ffff) is an index to
 *           the result UChars in toUUChars[]; (0 indexes toUUChars[0])
 *         length of the result=((value>>18)-12); (length=0..19)
 *       }
 *     }
 *
 *   The first word in a section contains the number of following words in the
 *   input byte position (bits 31..24, number=1..0xff).
 *   The value of the initial word is used when the current byte is not found
 *   in this section.
 *   If the value is not 0, then it represents a result as above.
 *   If the value is 0, then the search has to return a shorter match with an
 *   earlier default value as the result, or result in "unmappable" even for the
 *   initial bytes.
 *   If the value is 0 for the initial toUTable entry, then the initial byte
 *   does not start any mapping input.
 *
 *
 * UChar toUUChars[];
 *
 *   Contains toUnicode mapping results, stored as sequences of UChars.
 *   Indexes and lengths stored in the toUTable[].
 *
 *
 * UChar fromUTableUChars[];
 * uint32_t fromUTableValues[];
 *
 *   The fromUTable is split into two arrays, but works otherwise much like
 *   the toUTable. The array is partitioned into sections like collation
 *   contraction tables and toUTable.
 *   A row in the table consists of same-index entries in fromUTableUChars[]
 *   and fromUTableValues[].
 *
 *   Interpret a value as follows:
 *     if(value==0) {
 *       no match, see below
 *     } else if(value<=0xffffff) { (bits 31..24 are 0)
 *       partial match - use value as index to the next fromUTable section
 *       and match the next unit; (value indexes fromUTable[value])
 *     } else {
 *       if(value==0x80000001) {
 *         return no mapping, but request for <subchar1>;
 *       }
 *       if(bit 31 set) {
 *         roundtrip;
 *       } else {
 *         fallback;
 *       }
 *       // bits 30..29 reserved, 0
 *       length=(value>>24)&0x1f; (bits 28..24)
 *       if(length==1..3) {
 *         bits 23..0 contain 1..3 bytes, padded with 00s on the left;
 *       } else {
 *         bits 23..0 (value&0xffffff) is an index to
 *           the result bytes in fromUBytes[]; (0 indexes fromUBytes[0])
 *       }
 *     }
 *
 *   The first pair in a section contains the number of following pairs in the
 *   UChar position (16 bits, number=1..0xffff).
 *   The value of the initial pair is used when the current UChar is not found
 *   in this section.
 *   If the value is not 0, then it represents a result as above.
 *   If the value is 0, then the search has to return a shorter match with an
 *   earlier default value as the result, or result in "unmappable" even for the
 *   initial UChars.
 *
 *   If the from Unicode trie is present, then the from Unicode search tables
 *   are not used for initial code points.
 *   In this case, the first entries (index 0) in the tables are not used
 *   (reserved, set to 0) because a value of 0 is used in trie results
 *   to indicate no mapping.
 *
 *
 * uint16_t fromUStage12[];
 *
 *   Stages 1 & 2 of a trie that maps an initial code point.
 *   Indexes in stage 1 are all offset by the length of stage 1 so that the
 *   same array pointer can be used for both stages.
 *   If (c>>10)>=(length of stage 1) then c does not start any mapping.
 *   Same bit distribution as for regular conversion tries.
 *
 *
 * uint16_t fromUStage3[];
 * uint32_t fromUStage3b[];
 *
 *   Stage 3 of the trie. The first array simply contains indexes to the second,
 *   which contains words in the same format as fromUTableValues[].
 *   Use a stage 3 granularity of 4, which allows for 256k stage 3 entries,
 *   and 16-bit entries in stage 3 allow for 64k stage 3b entries.
 *   The stage 3 granularity means that the stage 2 entry needs to be left-shifted.
 *
 *   Two arrays are used because it is expected that more than half of the stage 3
 *   entries will be zero. The 16-bit index stage 3 array saves space even
 *   considering storing a total of 6 bytes per non-zero entry in both arrays
 *   together.
 *   Using a stage 3 granularity of >1 diminishes the compactability in that stage
 *   but provides a larger effective addressing space in stage 2.
 *   All but the final result stage use 16-bit entries to save space.
 *
 *   fromUStage3b[] contains a zero for "no mapping" at its index 0,
 *   and may contain UCNV_EXT_FROM_U_SUBCHAR1 at index 1 for "<subchar1> SUB mapping"
 *   (i.e., "no mapping" with preference for <subchar1> rather than <subchar>),
 *   and all other items are unique non-zero results.
 *
 *   The default value of a fromUTableValues[] section that is referenced
 *   _directly_ from a fromUStage3b[] item may also be UCNV_EXT_FROM_U_SUBCHAR1,
 *   but this value must not occur anywhere else in fromUTableValues[]
 *   because "no mapping" is always a property of a single code point,
 *   never of multiple.
 *
 *
 * char fromUBytes[];
 *
 *   Contains fromUnicode mapping results, stored as sequences of chars.
 *   Indexes and lengths stored in the fromUTableValues[].
 */

final class UConverterDataReader {
    //private final static boolean debug = ICUDebug.enabled("UConverterDataReader");

    private static final class IsAcceptable implements ICUBinary.Authenticate {
        // @Override when we switch to Java 6
        @Override
        public boolean isDataVersionAcceptable(byte formatVersion[]) {
            return formatVersion[0] == 6;
        }
    }
    private static final IsAcceptable IS_ACCEPTABLE = new IsAcceptable();

    /*
     *  UConverterDataReader(UConverterDataReader r)
        {
            byteBuffer = ICUBinary.getByteBufferFromInputStreamAndCloseStream(r.byteBuffer);
            unicodeVersion = r.unicodeVersion;
        }
        */
    /** The buffer position after the static data. */
    private int posAfterStaticData;

   /**
    * <p>Protected constructor.</p>
    * @param bytes ICU conversion data file
    * @exception IOException throw if data file fails authentication
    */
    protected UConverterDataReader(ByteBuffer bytes)
                                        throws IOException{
        //if(debug) System.out.println("Bytes in buffer " + bytes.remaining());

        byteBuffer = bytes;
        /*unicodeVersion = */ICUBinary.readHeader(byteBuffer, DATA_FORMAT_ID, IS_ACCEPTABLE);

        //if(debug) System.out.println("Bytes left in byteBuffer " + byteBuffer.remaining());
    }

    // protected methods -------------------------------------------------

    protected void readStaticData(UConverterStaticData sd) throws IOException
    {
        sd.structSize = byteBuffer.getInt();
        byte[] name = new byte[UConverterConstants.MAX_CONVERTER_NAME_LENGTH];
        byteBuffer.get(name);
        sd.name = new String(name, "US-ASCII");
        sd.codepage = byteBuffer.getInt();
        sd.platform = byteBuffer.get();
        sd.conversionType = byteBuffer.get();
        sd.minBytesPerChar = byteBuffer.get();
        sd.maxBytesPerChar = byteBuffer.get();
        byteBuffer.get(sd.subChar);
        sd.subCharLen = byteBuffer.get();
        sd.hasToUnicodeFallback = byteBuffer.get();
        sd.hasFromUnicodeFallback = byteBuffer.get();
        sd.unicodeMask = (short)(byteBuffer.get() & 0xff);
        sd.subChar1 = byteBuffer.get();
        byteBuffer.get(sd.reserved);
        posAfterStaticData = byteBuffer.position();
    }

    int bytesReadAfterStaticData() {
        return byteBuffer.position() - posAfterStaticData;
    }

    protected void readMBCSHeader(CharsetMBCS.MBCSHeader h) throws IOException
    {
        byteBuffer.get(h.version);
        h.countStates = byteBuffer.getInt();
        h.countToUFallbacks = byteBuffer.getInt();
        h.offsetToUCodeUnits = byteBuffer.getInt();
        h.offsetFromUTable = byteBuffer.getInt();
        h.offsetFromUBytes = byteBuffer.getInt();
        h.flags = byteBuffer.getInt();
        h.fromUBytesLength = byteBuffer.getInt();
        if (h.version[0] == 5 && h.version[1] >= 3) {
            h.options = byteBuffer.getInt();
            if ((h.options & CharsetMBCS.MBCS_OPT_NO_FROM_U) != 0) {
                h.fullStage2Length = byteBuffer.getInt();
            }
        }
    }

    protected void readMBCSTable(MBCSHeader header, UConverterMBCSTable mbcsTable) throws IOException
    {
        IntBuffer intBuffer = byteBuffer.asIntBuffer();
        mbcsTable.countStates = (byte) header.countStates;
        mbcsTable.stateTable = new int[header.countStates][256];
        int i;
        for(i = 0; i < header.countStates; ++i) {
            intBuffer.get(mbcsTable.stateTable[i]);
        }

        mbcsTable.countToUFallbacks = header.countToUFallbacks;
        mbcsTable.toUFallbacks = new MBCSToUFallback[header.countToUFallbacks];
        for(i = 0; i < header.countToUFallbacks; ++i) {
            int offset = intBuffer.get();
            int codePoint = intBuffer.get();
            mbcsTable.toUFallbacks[i] = new MBCSToUFallback(offset, codePoint);
        }
        // Skip as many bytes as we have read from the IntBuffer.
        int length = intBuffer.position() * 4;
        ICUBinary.skipBytes(byteBuffer, length);

        // Consider leaving some large arrays as CharBuffer/IntBuffer rather than
        // reading them into Java arrays, to reduce initialization time and memory usage,
        // at the cost of some performance.
        // For example: unicodeCodeUnits, fromUnicodeTable, fromUnicodeInts.
        // Take care not to modify the buffer contents for swaplfnl.
        CharBuffer charBuffer = byteBuffer.asCharBuffer();
        length = header.offsetFromUTable - header.offsetToUCodeUnits;
        assert (length & 1) == 0;
        mbcsTable.unicodeCodeUnits = new char[length / 2];
        charBuffer.get(mbcsTable.unicodeCodeUnits);
        // Skip as many bytes as we have read from the CharBuffer.
        ICUBinary.skipBytes(byteBuffer, length);

        length = header.offsetFromUBytes - header.offsetFromUTable;
        assert (length & 1) == 0;
        int fromUTableCharsLength;
        if (mbcsTable.outputType == CharsetMBCS.MBCS_OUTPUT_1) {
            // single-byte table stage1 + stage2
            fromUTableCharsLength = length / 2;
        } else if (mbcsTable.hasSupplementary()) {
            // stage1 for Unicode limit 0x110000 >> 10
            fromUTableCharsLength = 0x440;
        } else {
            // stage1 for BMP limit 0x10000 >> 10
            fromUTableCharsLength = 0x40;
        }
        mbcsTable.fromUnicodeTable = new char[fromUTableCharsLength];
        charBuffer.get(mbcsTable.fromUnicodeTable);
        if (mbcsTable.outputType != CharsetMBCS.MBCS_OUTPUT_1) {
            // Read both stage1 and stage2 together into an int[] array.
            // Keeping the short stage1 in the array avoids offsetting at runtime.
            // The stage1 part of this array will not be used.
            assert (length & 3) == 0;
            mbcsTable.fromUnicodeTableInts = new int[length / 4];
            byteBuffer.asIntBuffer().get(mbcsTable.fromUnicodeTableInts);
        }
        // Skip as many bytes as are in stage1 + stage2.
        ICUBinary.skipBytes(byteBuffer, length);

        mbcsTable.fromUBytesLength = header.fromUBytesLength;
        boolean noFromU = ((header.options & CharsetMBCS.MBCS_OPT_NO_FROM_U) != 0);
        if (!noFromU) {
            switch (mbcsTable.outputType) {
            case CharsetMBCS.MBCS_OUTPUT_1:
            case CharsetMBCS.MBCS_OUTPUT_2:
            case CharsetMBCS.MBCS_OUTPUT_2_SISO:
            case CharsetMBCS.MBCS_OUTPUT_3_EUC:
                mbcsTable.fromUnicodeChars = ICUBinary.getChars(
                        byteBuffer, header.fromUBytesLength / 2, 0);
                break;
            case CharsetMBCS.MBCS_OUTPUT_3:
            case CharsetMBCS.MBCS_OUTPUT_4_EUC:
                mbcsTable.fromUnicodeBytes = new byte[header.fromUBytesLength];
                byteBuffer.get(mbcsTable.fromUnicodeBytes);
                break;
            case CharsetMBCS.MBCS_OUTPUT_4:
                mbcsTable.fromUnicodeInts = ICUBinary.getInts(
                        byteBuffer, header.fromUBytesLength / 4, 0);
                break;
            default:
                // Cannot occur, caller checked already.
                assert false;
            }
        } else {
            // Optional utf8Friendly mbcsIndex -- _MBCSHeader.version 4.3 (ICU 3.8) and higher.
            // Needed for reconstituting omitted data.
            mbcsTable.mbcsIndex = byteBuffer.asCharBuffer();
        }
    }

    protected String readBaseTableName() throws IOException
    {
        char c;
        StringBuilder name = new StringBuilder();
        while((c = (char)byteBuffer.get()) !=  0){
            name.append(c);
        }
        return name.toString();
    }

    //protected int[] readExtIndexes(int skip) throws IOException
    protected ByteBuffer readExtIndexes(int skip) throws IOException, InvalidFormatException
    {
        ICUBinary.skipBytes(byteBuffer, skip);
        ByteBuffer b = ICUBinary.sliceWithOrder(byteBuffer);
        int lengthOfIndexes = b.getInt(0);
        if (lengthOfIndexes < 32) {
            throw new InvalidFormatException();
        }
        int numBytesExtensionStructure = b.getInt(31 * 4);
        b.limit(numBytesExtensionStructure);
        ICUBinary.skipBytes(byteBuffer, numBytesExtensionStructure);
        return b;
    }

    /**
     * Data formatVersion 6.1 and higher has a unicodeMask.
     */
    boolean dataFormatHasUnicodeMask() {
        int formatVersion0 = byteBuffer.get(16) & 0xff;
        return formatVersion0 > 6 || (formatVersion0 == 6 && byteBuffer.get(17) != 0);
    }

    // private data members -------------------------------------------------

    /**
    * ICU data file input stream
    */
    private ByteBuffer byteBuffer;

//    private VersionInfo unicodeVersion;

    /**
    * File format version that this class understands.
    * No guarantees are made if a older version is used
    * see store.c of gennorm for more information and values
    */
    // DATA_FORMAT_ID_ values taken from icu4c isCnvAcceptable (ucnv_bld.c)
    private static final int DATA_FORMAT_ID = 0x636e7674; // dataFormat="cnvt"
}
