void dng_memory_stream::DoRead (void *data, uint32 count, uint64 offset) { if (offset + count > fMemoryStreamLength) { ThrowEndOfFile (); } uint64 baseOffset = offset; while (count) { uint32 pageIndex = (uint32) (offset / fPageSize); uint32 pageOffset = (uint32) (offset % fPageSize); uint32 blockCount = Min_uint32 (fPageSize - pageOffset, count); const uint8 *sPtr = fPageList [pageIndex]->Buffer_uint8 () + pageOffset; uint8 *dPtr = ((uint8 *) data) + (uint32) (offset - baseOffset); DoCopyBytes (sPtr, dPtr, blockCount); offset += blockCount; count -= blockCount; } }
void dng_stream::SetReadPosition (uint64 offset) { fPosition = offset; if (fPosition > Length ()) { ThrowEndOfFile (); } }
void dng_memory_stream::CopyToStream (dng_stream &dstStream, uint64 count) { if (count < kBigBufferSize) { dng_stream::CopyToStream (dstStream, count); } else { Flush (); uint64 offset = Position (); if (offset + count > Length ()) { ThrowEndOfFile (); } while (count) { uint32 pageIndex = (uint32) (offset / fPageSize); uint32 pageOffset = (uint32) (offset % fPageSize); uint32 blockCount = (uint32) Min_uint64 (fPageSize - pageOffset, count); const uint8 *sPtr = fPageList [pageIndex]->Buffer_uint8 () + pageOffset; dstStream.Put (sPtr, blockCount); offset += blockCount; count -= blockCount; } SetReadPosition (offset); } }
void dng_stream::Get (void *data, uint32 count) { while (count) { // See if the request is totally inside buffer. if (fPosition >= fBufferStart && fPosition + count <= fBufferEnd) { DoCopyBytes (fBuffer + (uint32) (fPosition - fBufferStart), data, count); fPosition += count; return; } // See if first part of request is inside buffer. if (fPosition >= fBufferStart && fPosition < fBufferEnd) { uint32 block = (uint32) (fBufferEnd - fPosition); DoCopyBytes (fBuffer + (fPosition - fBufferStart), data, block); count -= block; data = (void *) (((char *) data) + block); fPosition += block; } // Flush buffer if dirty. Flush (); // Do large reads unbuffered. if (count > fBufferSize) { if (fPosition + count > Length ()) { ThrowEndOfFile (); } DoRead (data, count, fPosition); fPosition += count; return; } // Figure out new buffer range. fBufferStart = fPosition; if (fBufferSize >= 4096) { // Align to a 4K file block. fBufferStart &= (uint64) ~((int64) 4095); } fBufferEnd = Min_uint64 (fBufferStart + fBufferSize, Length ()); if (fBufferEnd <= fPosition) { ThrowEndOfFile (); } // Read data into buffer. dng_abort_sniffer::SniffForAbort (fSniffer); DoRead (fBuffer, (uint32) (fBufferEnd - fBufferStart), fBufferStart); } }