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_memory_stream::DoWrite (const void *data, uint32 count, uint64 offset) { DoSetLength (Max_uint64 (fMemoryStreamLength, offset + count)); 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 = ((const uint8 *) data) + (uint32) (offset - baseOffset); uint8 *dPtr = fPageList [pageIndex]->Buffer_uint8 () + pageOffset; DoCopyBytes (sPtr, dPtr, blockCount); offset += blockCount; count -= blockCount; } }
dng_opcode_MapTable::dng_opcode_MapTable (dng_host &host, const dng_area_spec &areaSpec, const uint16 *table, uint32 count) : dng_inplace_opcode (dngOpcode_MapTable, dngVersion_1_3_0_0, kFlag_None) , fAreaSpec (areaSpec) , fTable () , fCount (count) { if (count == 0 || count > 0x10000) { ThrowProgramError (); } fTable.Reset (host.Allocate (0x10000 * sizeof (uint16))); DoCopyBytes (table, fTable->Buffer (), count * sizeof (uint16)); ReplicateLastEntry (); }
void dng_memory_stream::DoSetLength (uint64 length) { while (length > fPageCount * (uint64) fPageSize) { if (fPageCount == fPagesAllocated) { uint32 newSize = Max_uint32 (fPagesAllocated + 32, fPagesAllocated * 2); dng_memory_block **list = (dng_memory_block **) malloc (newSize * sizeof (dng_memory_block *)); if (!list) { ThrowMemoryFull (); } if (fPageCount) { DoCopyBytes (fPageList, list, fPageCount * (uint32) sizeof (dng_memory_block *)); } if (fPageList) { free (fPageList); } fPageList = list; fPagesAllocated = newSize; } fPageList [fPageCount] = fAllocator.Allocate (fPageSize); fPageCount++; } fMemoryStreamLength = length; }
void dng_string_list::Allocate (uint32 minSize) { if (fAllocated < minSize) { uint32 newSize = Max_uint32 (minSize, fAllocated * 2); dng_string **list = (dng_string **) malloc (newSize * sizeof (dng_string *)); if (!list) { ThrowMemoryFull (); } if (fCount) { DoCopyBytes (fList, list, fCount * sizeof (dng_string *)); } if (fList) { free (fList); } fList = list; fAllocated = newSize; } }
void dng_stream::Put (const void *data, uint32 count) { // See if we can replace or append to the existing buffer. uint64 endPosition = fPosition + count; if (fBufferDirty && fPosition >= fBufferStart && fPosition <= fBufferEnd && endPosition <= fBufferLimit) { DoCopyBytes (data, fBuffer + (uint32) (fPosition - fBufferStart), count); if (fBufferEnd < endPosition) fBufferEnd = endPosition; } // Else we need to write to the file. else { // Write existing buffer. Flush (); // Write large blocks unbuffered. if (count >= fBufferSize) { dng_abort_sniffer::SniffForAbort (fSniffer); DoWrite (data, count, fPosition); } // Start a new buffer with small blocks. else { fBufferDirty = true; fBufferStart = fPosition; fBufferEnd = endPosition; fBufferLimit = fBufferStart + fBufferSize; DoCopyBytes (data, fBuffer, count); } } fPosition = endPosition; fLength = Max_uint64 (Length (), fPosition); }
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); } }