Exemple #1
0
        private Metablock ReadMetaBlock(long pos)
        {
            Metablock block = _metablockCache.GetBlock(pos);

            if (block.Available >= 0)
            {
                return(block);
            }

            Stream stream = _context.RawStream;

            stream.Position = pos;

            byte[] buffer = Utilities.ReadFully(stream, 2);

            int  readLen      = Utilities.ToUInt16LittleEndian(buffer, 0);
            bool isCompressed = (readLen & 0x8000) == 0;

            readLen &= 0x7FFF;
            if (readLen == 0)
            {
                readLen = 0x8000;
            }

            block.NextBlockStart = pos + readLen + 2;

            if (isCompressed)
            {
                if (_ioBuffer == null || readLen > _ioBuffer.Length)
                {
                    _ioBuffer = new byte[readLen];
                }

                if (Utilities.ReadFully(stream, _ioBuffer, 0, readLen) != readLen)
                {
                    throw new IOException("Truncated stream reading compressed metadata");
                }

                using (ZlibStream zlibStream = new ZlibStream(new MemoryStream(_ioBuffer, 0, readLen, false), CompressionMode.Decompress, true))
                {
                    block.Available = Utilities.ReadFully(zlibStream, block.Data, 0, MetadataBufferSize);
                }
            }
            else
            {
                block.Available = Utilities.ReadFully(stream, block.Data, 0, readLen);
            }

            return(block);
        }
        public string ReadString(int len)
        {
            Metablock block = _context.ReadMetaBlock(_start + _currentBlockStart);

            if (block.Available - _currentOffset < len)
            {
                byte[] buffer = new byte[len];
                Read(buffer, 0, len);
                return(Utilities.BytesToString(buffer, 0, len));
            }
            else
            {
                string result = Utilities.BytesToString(block.Data, _currentOffset, len);
                _currentOffset += len;
                return(result);
            }
        }
        public short ReadShort()
        {
            Metablock block = _context.ReadMetaBlock(_start + _currentBlockStart);

            if (block.Available - _currentOffset < 2)
            {
                byte[] buffer = new byte[2];
                Read(buffer, 0, 2);
                return(Utilities.ToInt16LittleEndian(buffer, 0));
            }
            else
            {
                short result = Utilities.ToInt16LittleEndian(block.Data, _currentOffset);
                _currentOffset += 2;
                return(result);
            }
        }
        public int ReadInt()
        {
            Metablock block = _context.ReadMetaBlock(_start + _currentBlockStart);

            if (block.Available - _currentOffset < 4)
            {
                byte[] buffer = new byte[4];
                Read(buffer, 0, 4);
                return(Utilities.ToInt32LittleEndian(buffer, 0));
            }
            else
            {
                int result = Utilities.ToInt32LittleEndian(block.Data, _currentOffset);
                _currentOffset += 4;
                return(result);
            }
        }
        public void Skip(int count)
        {
            Metablock block = _context.ReadMetaBlock(_start + _currentBlockStart);

            int totalSkipped = 0;

            while (totalSkipped < count)
            {
                if (_currentOffset >= block.Available)
                {
                    int oldAvailable = block.Available;
                    block = _context.ReadMetaBlock(block.NextBlockStart);
                    _currentBlockStart = block.Position - _start;
                    _currentOffset    -= oldAvailable;
                }

                int toSkip = Math.Min(count - totalSkipped, block.Available - _currentOffset);
                totalSkipped   += toSkip;
                _currentOffset += toSkip;
            }
        }
        public int Read(byte[] buffer, int offset, int count)
        {
            Metablock block = _context.ReadMetaBlock(_start + _currentBlockStart);

            int totalRead = 0;

            while (totalRead < count)
            {
                if (_currentOffset >= block.Available)
                {
                    int oldAvailable = block.Available;
                    block = _context.ReadMetaBlock(block.NextBlockStart);
                    _currentBlockStart = block.Position - _start;
                    _currentOffset    -= oldAvailable;
                }

                int toRead = Math.Min(count - totalRead, block.Available - _currentOffset);
                Array.Copy(block.Data, _currentOffset, buffer, offset + totalRead, toRead);
                totalRead      += toRead;
                _currentOffset += toRead;
            }

            return(totalRead);
        }