/********************************************************************** * TABRawBinBlock::GotoByteInFile() * * Move the block pointer to the specified position relative to the * beginning of the file. * * In read access, the current block may be reloaded to contain a right * block of binary data if necessary. * * In write mode, the current block may automagically be committed to * disk and a new block initialized if necessary. * * Returns 0 if succesful or -1 if an error happened, in which case * CPLError() will have been called. **********************************************************************/ int TABRawBinBlock::GotoByteInFile(int nOffset) { int nNewBlockPtr; if (nOffset < 0) { CPLError(CE_Failure, CPLE_AppDefined, "GotoByteInFile(): Attempt to go before start of file."); return -1; } nNewBlockPtr = ( (nOffset-m_nFirstBlockPtr)/m_nBlockSize)*m_nBlockSize + m_nFirstBlockPtr; if (m_eAccess == TABRead) { if ( (nOffset<m_nFileOffset || nOffset>=m_nFileOffset+m_nSizeUsed) && ReadFromFile(m_fp, nNewBlockPtr, m_nBlockSize) != 0) { // Failed reading new block... error has already been reported. return -1; } } else if (m_eAccess == TABWrite) { if ( (nOffset<m_nFileOffset || nOffset>=m_nFileOffset+m_nBlockSize) && (CommitToFile() != 0 || InitNewBlock(m_fp, m_nBlockSize, nNewBlockPtr) != 0) ) { // Failed reading new block... error has already been reported. return -1; } } else { CPLError(CE_Failure, CPLE_NotSupported, "Access mode not supported yet!"); return -1; } m_nCurPos = nOffset-m_nFileOffset; m_nSizeUsed = MAX(m_nSizeUsed, m_nCurPos); return 0; }
/********************************************************************** * TABMAPToolBlock::WriteBytes() * * Cover function for TABRawBinBlock::WriteBytes() that will automagically * CommitToFile() the current block and create a new one if we are at * the end of the current block. * * Then the control is passed to TABRawBinBlock::WriteBytes() to finish the * work. * * Passing pabySrcBuf = NULL will only move the write pointer by the * specified number of bytes as if the copy had happened... but it * won't crash. * * Returns 0 if successful or -1 if an error happened, in which case * CPLError() will have been called. **********************************************************************/ int TABMAPToolBlock::WriteBytes(int nBytesToWrite, const GByte *pabySrcBuf) { if (m_eAccess == TABWrite && m_poBlockManagerRef && (m_nBlockSize - m_nCurPos) < nBytesToWrite) { int nNewBlockOffset = m_poBlockManagerRef->AllocNewBlock("TOOL"); SetNextToolBlock(nNewBlockOffset); if (CommitToFile() != 0 || InitNewBlock(m_fp, m_nBlockSize, nNewBlockOffset) != 0) { // An error message should have already been reported. return -1; } m_numBlocksInChain ++; } return TABRawBinBlock::WriteBytes(nBytesToWrite, pabySrcBuf); }
/********************************************************************** * TABMAPToolBlock::CheckAvailableSpace() * * Check if an object of the specified type can fit in * current block. If it can't fit then force committing current block * and allocating a new one. * * Returns 0 if successful or -1 if an error happened, in which case * CPLError() will have been called. **********************************************************************/ int TABMAPToolBlock::CheckAvailableSpace(int nToolType) { int nBytesToWrite = 0; switch(nToolType) { case TABMAP_TOOL_PEN: nBytesToWrite = 11; break; case TABMAP_TOOL_BRUSH: nBytesToWrite = 13; break; case TABMAP_TOOL_FONT: nBytesToWrite = 37; break; case TABMAP_TOOL_SYMBOL: nBytesToWrite = 13; break; default: CPLAssert(false); } if (GetNumUnusedBytes() < nBytesToWrite) { int nNewBlockOffset = m_poBlockManagerRef->AllocNewBlock("TOOL"); SetNextToolBlock(nNewBlockOffset); if (CommitToFile() != 0 || InitNewBlock(m_fp, m_nBlockSize, nNewBlockOffset) != 0) { // An error message should have already been reported. return -1; } m_numBlocksInChain ++; } return 0; }
/********************************************************************** * TABRawBinBlock::GotoByteInFile() * * Move the block pointer to the specified position relative to the * beginning of the file. * * In read access, the current block may be reloaded to contain a right * block of binary data if necessary. * * In write mode, the current block may automagically be committed to * disk and a new block initialized if necessary. * * bForceReadFromFile is used in write mode to read the new block data from * file instead of creating an empty block. (Useful for TABCollection * or other cases that need to do random access in the file in write mode.) * * bOffsetIsEndOfData is set to TRUE to indicate that the nOffset * to which we are attempting to go is the end of the used data in this * block (we are positioning ourselves to append data), so if the nOffset * corresponds to the beginning of a block then we should really * be positioning ourselves at the end of the block that ends at this * address instead of at the beginning of the blocks that starts at this * address. This case can happen when going back and forth to write collection * objects to a Coordblock and is documented in bug 1657. * * Returns 0 if successful or -1 if an error happened, in which case * CPLError() will have been called. **********************************************************************/ int TABRawBinBlock::GotoByteInFile(int nOffset, GBool bForceReadFromFile /*=FALSE*/, GBool bOffsetIsEndOfData /*=FALSE*/) { if (nOffset < 0) { CPLError(CE_Failure, CPLE_AppDefined, "GotoByteInFile(): Attempt to go before start of file."); return -1; } int nNewBlockPtr = ( (nOffset-m_nFirstBlockPtr)/m_nBlockSize)*m_nBlockSize + m_nFirstBlockPtr; if (m_eAccess == TABRead) { if ( (nOffset<m_nFileOffset || nOffset>=m_nFileOffset+m_nSizeUsed) && ReadFromFile(m_fp, nNewBlockPtr, m_nBlockSize) != 0) { // Failed reading new block... error has already been reported. return -1; } } else if (m_eAccess == TABWrite) { if ( (nOffset<m_nFileOffset || nOffset>=m_nFileOffset+m_nBlockSize) && (CommitToFile() != 0 || InitNewBlock(m_fp, m_nBlockSize, nNewBlockPtr) != 0 ) ) { // Failed reading new block... error has already been reported. return -1; } } else if (m_eAccess == TABReadWrite) { // TODO: THIS IS NOT REAL read/write access (it's more extended write) // Currently we try to read from file only if explicitly requested. // If we ever want true read/write mode we should implement // more smarts to detect whether the caller wants an existing block to // be read, or a new one to be created from scratch. // CommitToFile() should only be called only if something changed. // if (bOffsetIsEndOfData && nOffset%m_nBlockSize == 0) { /* We're trying to go byte m_nBlockSize of a block that's full of data. * In this case it's okay to place the m_nCurPos at byte m_nBlockSize * which is past the end of the block. */ /* Make sure we request the block that ends with requested * address and not the following block that doesn't exist * yet on disk */ nNewBlockPtr -= m_nBlockSize; if ( (nOffset < m_nFileOffset || nOffset > m_nFileOffset+m_nBlockSize) && (CommitToFile() != 0 || (!bForceReadFromFile && InitNewBlock(m_fp, m_nBlockSize, nNewBlockPtr) != 0) || (bForceReadFromFile && ReadFromFile(m_fp, nNewBlockPtr, m_nBlockSize) != 0) ) ) { // Failed reading new block... error has already been reported. return -1; } } else { if( !bForceReadFromFile && m_nFileSize > 0 && nOffset < m_nFileSize ) { bForceReadFromFile = TRUE; if ( !(nOffset < m_nFileOffset || nOffset >= m_nFileOffset+m_nBlockSize) ) { if ( (nOffset<m_nFileOffset || nOffset>=m_nFileOffset+m_nSizeUsed) && (CommitToFile() != 0 || ReadFromFile(m_fp, nNewBlockPtr, m_nBlockSize) != 0) ) { // Failed reading new block... error has already been reported. return -1; } } } if ( (nOffset < m_nFileOffset || nOffset >= m_nFileOffset+m_nBlockSize) && (CommitToFile() != 0 || (!bForceReadFromFile && InitNewBlock(m_fp, m_nBlockSize, nNewBlockPtr) != 0) || (bForceReadFromFile && ReadFromFile(m_fp, nNewBlockPtr, m_nBlockSize) != 0) ) ) { // Failed reading new block... error has already been reported. return -1; } } } else { CPLError(CE_Failure, CPLE_NotSupported, "Access mode not supported yet!"); return -1; } m_nCurPos = nOffset-m_nFileOffset; m_nSizeUsed = MAX(m_nSizeUsed, m_nCurPos); return 0; }