private int ReadObjectPart(long id, long objOffset, byte[] buffer, int off, int length)
{
// ASSERT: Read and Write position must be 64K aligned.
if (off % (64 * 1024) != 0) {
throw new Exception("Assert failed: offset is not 64k aligned.");
}
// ASSERT: Length is less than or equal to 64K
if (length > (64 * 1024)) {
throw new Exception("Assert failed: length is greater than 64K.");
}
int status;
long maxSize;
long currentSize;
long objPointer;
lock (fixedList) {
// Assert that the blob reference id given is a valid range
if (id < 0 || id >= fixedList.NodeCount) {
throw new IOException("Object ID is out of range.");
}
// Position on this record
IArea block = fixedList.GetRecord(id);
// Read the information in the fixed record
status = block.ReadInt4();
// Assert that the status is not deleted
if ((status & DeletedFlag) != 0)
throw new InvalidOperationException("Assertion failed: record is deleted!");
// Get the reference count
block.ReadInt4();
// Get the total size of the object
maxSize = block.ReadInt8();
// Get the current running size of the block
currentSize = block.ReadInt8();
// Get the blob pointer
objPointer = block.ReadInt8();
}
// Assert that the area being Read is within the bounds of the object
if (off < 0 || objOffset + length > maxSize) {
throw new IOException("Invalid Read. offset = " + objOffset + ", length = " + length + " > maxSize = " + maxSize);
}
// Open an IArea into the object
IArea area = store.GetArea(objPointer);
area.ReadInt4();
int type = area.ReadInt4();
// Convert to the page number
long pageNumber = (objOffset / (64 * 1024));
area.Position = (int)((pageNumber * 8) + 32);
long pagePointer = area.ReadInt8();
// Read the page
IArea pageArea = store.GetArea(pagePointer);
pageArea.Position = 0;
int pageType = pageArea.ReadInt4();
int pageSize = pageArea.ReadInt4();
if ((type & CompressedFlag) != 0) {
#if !PCL
// The page is compressed
byte[] pageBuf = new byte[pageSize];
int readCount = pageArea.Read(pageBuf, 0, pageSize);
using (var input = new MemoryStream(pageBuf, 0, readCount)) {
using (var output = new MemoryStream()) {
using (var deflateStream = new DeflateStream(input, CompressionMode.Decompress, false)) {
deflateStream.CopyTo(output);
output.Flush();
output.Seek(0, SeekOrigin.Begin);
var resultLenght = output.Length;
if (resultLenght != length)
throw new IOException("Uncompressed length is invalid.");
return output.Read(buffer, off, length);
}
}
}
//var deflateStream = new DeflateStream(new MemoryStream(pageBuf, 0, pageSize), CompressionMode.Decompress, false);
//try {
// int resultLength = deflateStream.Read(buffer, off, length);
// if (resultLength != length)
// throw new Exception("Assert failed: decompressed length is incorrect.");
// return readCount;
//} catch(InvalidDataException e) {
// throw new IOException("ZIP Data Format Error: " + e.Message);
//}
#else
throw new NotSupportedException("Compression not supported in PCL.");
#endif
}
// The page is not compressed
return pageArea.Read(buffer, off, length);
}