size_t VSIFReadL( void * pBuffer, size_t nSize, size_t nCount, VSILFILE * fp ) { VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp; return poFileHandle->Read( pBuffer, nSize, nCount ); }
size_t VSIFReadL( void * pBuffer, size_t nSize, size_t nCount, VSILFILE * fp ) { VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp ); return poFileHandle->Read( pBuffer, nSize, nCount ); }
int VSICachedFile::LoadBlocks( size_t nStartBlock, size_t nBlockCount, void *pBuffer, size_t nBufferSize ) { if( nBlockCount == 0 ) return 1; if( apoCache.size() < nStartBlock + nBlockCount ) apoCache.resize( nStartBlock + nBlockCount ); /* -------------------------------------------------------------------- */ /* When we want to load only one block, we can directly load it */ /* into the target buffer with no concern about intermediaries. */ /* -------------------------------------------------------------------- */ if( nBlockCount == 1 ) { poBase->Seek( nStartBlock * CHUNK_SIZE, SEEK_SET ); apoCache[nStartBlock] = new VSICacheChunk(); VSICacheChunk *poBlock = apoCache[nStartBlock]; poBlock->iBlock = nStartBlock; poBlock->nDataFilled = poBase->Read( poBlock->abyData, 1, CHUNK_SIZE ); nCacheUsed += poBlock->nDataFilled; // Merges into the LRU list. Demote( poBlock ); return 1; } /* -------------------------------------------------------------------- */ /* If the buffer is quite large but not quite large enough to */ /* hold all the blocks we will take the pain of splitting the */ /* io request in two in order to avoid allocating a large */ /* temporary buffer. */ /* -------------------------------------------------------------------- */ if( nBufferSize > CHUNK_SIZE * 20 && nBufferSize < nBlockCount * CHUNK_SIZE ) { if( !LoadBlocks( nStartBlock, 2, pBuffer, nBufferSize ) ) return 0; return LoadBlocks( nStartBlock+2, nBlockCount-2, pBuffer, nBufferSize ); } /* -------------------------------------------------------------------- */ /* Do we need to allocate our own buffer? */ /* -------------------------------------------------------------------- */ GByte *pabyWorkBuffer = (GByte *) pBuffer; if( nBufferSize < CHUNK_SIZE * nBlockCount ) pabyWorkBuffer = (GByte *) CPLMalloc(CHUNK_SIZE * nBlockCount); /* -------------------------------------------------------------------- */ /* Read the whole request into the working buffer. */ /* -------------------------------------------------------------------- */ if( poBase->Seek( nStartBlock * CHUNK_SIZE, SEEK_SET ) != 0 ) return 0; size_t nDataRead = poBase->Read( pabyWorkBuffer, 1, nBlockCount*CHUNK_SIZE); if( nBlockCount * CHUNK_SIZE > nDataRead + CHUNK_SIZE - 1 ) nBlockCount = (nDataRead + CHUNK_SIZE - 1) / CHUNK_SIZE; for( size_t i = 0; i < nBlockCount; i++ ) { VSICacheChunk *poBlock = new VSICacheChunk(); poBlock->iBlock = nStartBlock + i; CPLAssert( apoCache[i+nStartBlock] == NULL ); apoCache[i + nStartBlock] = poBlock; if( nDataRead >= (i+1) * CHUNK_SIZE ) poBlock->nDataFilled = CHUNK_SIZE; else poBlock->nDataFilled = nDataRead - i*CHUNK_SIZE; memcpy( poBlock->abyData, pabyWorkBuffer + i*CHUNK_SIZE, (size_t) poBlock->nDataFilled ); nCacheUsed += poBlock->nDataFilled; // Merges into the LRU list. Demote( poBlock ); } if( pabyWorkBuffer != pBuffer ) CPLFree( pabyWorkBuffer ); return 1; }
size_t VSIBufferedReaderHandle::Read( void *pBuffer, size_t nSize, size_t nMemb ) { const size_t nTotalToRead = nSize * nMemb; //CPLDebug( "BUFFERED", "Read(%d)", (int)nTotalToRead); if (nSize == 0) return 0; if (nBufferSize != 0 && nCurOffset >= nBufferOffset && nCurOffset <= nBufferOffset + nBufferSize) { /* We try to read from an offset located within the buffer */ const int nReadInBuffer = (int) MIN(nTotalToRead, nBufferOffset + nBufferSize - nCurOffset); memcpy(pBuffer, pabyBuffer + nCurOffset - nBufferOffset, nReadInBuffer); const int nToReadInFile = nTotalToRead - nReadInBuffer; if (nToReadInFile > 0) { /* The beginning of the the data to read is located in the buffer */ /* but the end must be read from the file */ if (bNeedBaseHandleSeek) poBaseHandle->Seek(nBufferOffset + nBufferSize, SEEK_SET); bNeedBaseHandleSeek = FALSE; //CPLAssert(poBaseHandle->Tell() == nBufferOffset + nBufferSize); const int nReadInFile = poBaseHandle->Read((GByte*)pBuffer + nReadInBuffer, 1, nToReadInFile); const int nRead = nReadInBuffer + nReadInFile; nBufferSize = MIN(nRead, MAX_BUFFER_SIZE); nBufferOffset = nCurOffset + nRead - nBufferSize; memcpy(pabyBuffer, (GByte*)pBuffer + nRead - nBufferSize, nBufferSize); nCurOffset += nRead; //CPLAssert(poBaseHandle->Tell() == nBufferOffset + nBufferSize); //CPLAssert(poBaseHandle->Tell() == nCurOffset); bEOF = poBaseHandle->Eof(); return nRead / nSize; } else { /* The data to read is completely located within the buffer */ nCurOffset += nTotalToRead; return nTotalToRead / nSize; } } else { /* We try either to read before or after the buffer, so a seek is necessary */ poBaseHandle->Seek(nCurOffset, SEEK_SET); bNeedBaseHandleSeek = FALSE; const int nReadInFile = poBaseHandle->Read(pBuffer, 1, nTotalToRead); nBufferSize = MIN(nReadInFile, MAX_BUFFER_SIZE); nBufferOffset = nCurOffset + nReadInFile - nBufferSize; memcpy(pabyBuffer, (GByte*)pBuffer + nReadInFile - nBufferSize, nBufferSize); nCurOffset += nReadInFile; //CPLAssert(poBaseHandle->Tell() == nBufferOffset + nBufferSize); //CPLAssert(poBaseHandle->Tell() == nCurOffset); bEOF = poBaseHandle->Eof(); return nReadInFile / nSize; } }