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 = StreamUtilities.ReadFully(stream, 2); int readLen = EndianUtilities.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 (StreamUtilities.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 = StreamUtilities.ReadFully(zlibStream, block.Data, 0, MetadataBufferSize); } } else { block.Available = StreamUtilities.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)); } 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)); } 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)); } 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); }