예제 #1
0
        public PackIndexV2(Stream fd)
        {
            var fanoutRaw = new byte[4 * FANOUT];

            IO.ReadFully(fd, fanoutRaw, 0, fanoutRaw.Length);
            _fanoutTable = new long[FANOUT];
            for (int k = 0; k < FANOUT; k++)
            {
                _fanoutTable[k] = NB.DecodeUInt32(fanoutRaw, k * 4);
            }
            ObjectCount = _fanoutTable[FANOUT - 1];

            _names    = new int[FANOUT][];
            _offset32 = new byte[FANOUT][];
            _crc32    = new byte[FANOUT][];

            // object name table. The size we can permit per fan-out bucket
            // is limited to Java's 2 GB per byte array limitation. That is
            // no more than 107,374,182 objects per fan-out.
            //
            for (int k = 0; k < FANOUT; k++)
            {
                long bucketCnt;
                if (k == 0)
                {
                    bucketCnt = _fanoutTable[k];
                }
                else
                {
                    bucketCnt = _fanoutTable[k] - _fanoutTable[k - 1];
                }

                if (bucketCnt == 0)
                {
                    _names[k]    = NoInts;
                    _offset32[k] = NoBytes;
                    _crc32[k]    = NoBytes;
                    continue;
                }

                long nameLen = bucketCnt * Constants.OBJECT_ID_LENGTH;
                if (nameLen > int.MaxValue)
                {
                    throw new IOException("Index file is too large");
                }

                var intNameLen = (int)nameLen;
                var raw        = new byte[intNameLen];
                var bin        = new int[intNameLen >> 2];
                IO.ReadFully(fd, raw, 0, raw.Length);
                for (int i = 0; i < bin.Length; i++)
                {
                    bin[i] = NB.DecodeInt32(raw, i << 2);
                }

                _names[k]    = bin;
                _offset32[k] = new byte[(int)(bucketCnt * 4)];
                _crc32[k]    = new byte[(int)(bucketCnt * 4)];
            }

            // CRC32 table.
            for (int k = 0; k < FANOUT; k++)
            {
                IO.ReadFully(fd, _crc32[k], 0, _crc32[k].Length);
            }

            // 32 bit offset table. Any entries with the most significant bit
            // set require a 64 bit offset entry in another table.
            //
            int o64cnt = 0;

            for (int k = 0; k < FANOUT; k++)
            {
                byte[] ofs = _offset32[k];
                IO.ReadFully(fd, ofs, 0, ofs.Length);
                for (int p = 0; p < ofs.Length; p += 4)
                {
                    if (NB.ConvertUnsignedByteToSigned(ofs[p]) < 0)
                    {
                        o64cnt++;
                    }
                }
            }

            // 64 bit offset table. Most objects should not require an entry.
            //
            if (o64cnt > 0)
            {
                _offset64 = new byte[o64cnt * 8];
                IO.ReadFully(fd, _offset64, 0, _offset64.Length);
            }
            else
            {
                _offset64 = NoBytes;
            }

            PackChecksum = new byte[20];
            IO.ReadFully(fd, PackChecksum, 0, PackChecksum.Length);
        }