/********************************************************************** * TABSeamless::GetFeatureRef() * * Fill and return a TABFeature object for the specified feature id. * * The returned pointer is a reference to an object owned and maintained * by this TABSeamless object. It should not be altered or freed by the * caller and its contents is guaranteed to be valid only until the next * call to GetFeatureRef() or Close(). * * Returns NULL if the specified feature id does not exist of if an * error happened. In any case, CPLError() will have been called to * report the reason of the failure. **********************************************************************/ TABFeature *TABSeamless::GetFeatureRef(int nFeatureId) { if (m_poIndexTable == NULL) return NULL; // File is not opened yet if (nFeatureId == m_nCurFeatureId && m_poCurFeature) return m_poCurFeature; if (m_nCurBaseTableId != ExtractBaseTableId(nFeatureId)) { if (OpenBaseTable(ExtractBaseTableId(nFeatureId)) != 0) return NULL; } if (m_poCurBaseTable) { if (m_poCurFeature) delete m_poCurFeature; m_poCurFeature = (TABFeature*)m_poCurBaseTable->GetFeature(ExtractBaseFeatureId(nFeatureId)); m_nCurFeatureId = nFeatureId; m_poCurFeature->SetFID(nFeatureId); return m_poCurFeature; } return NULL; }
/********************************************************************** * TABSeamless::OpenNextBaseTable() * * Open the next base table in the dataset, using GetNextFeature() so that * the spatial filter is respected. * * m_bEOF will be set if there are no more base tables to read. * * Returns 0 on success, -1 on error. **********************************************************************/ int TABSeamless::OpenNextBaseTable(GBool bTestOpenNoError /*=FALSE*/) { CPLAssert(m_poIndexTable); TABFeature *poIndexFeature = (TABFeature*)m_poIndexTable->GetNextFeature(); if (poIndexFeature) { if (OpenBaseTable(poIndexFeature, bTestOpenNoError) != 0) { // Open Failed... an error has already been reported. if (bTestOpenNoError) CPLErrorReset(); delete poIndexFeature; return -1; } delete poIndexFeature; m_bEOF = FALSE; } else { // Reached EOF m_bEOF = TRUE; } return 0; }
void TABSeamless::ResetReading() { if (m_poIndexTable) OpenBaseTable(-1); // Asking for first table resets everything // Reset m_nCurFeatureId so that next pass via GetNextFeatureId() // will start from the beginning m_nCurFeatureId = -1; }
/********************************************************************** * TABSeamless::OpenBaseTable() * * Open the base table for specified IndexFeature. * * Returns 0 on success, -1 on error. **********************************************************************/ int TABSeamless::OpenBaseTable(int nTableId, GBool bTestOpenNoError /*=FALSE*/) { if (nTableId == -1) { // Open first table from dataset m_poIndexTable->ResetReading(); if (OpenNextBaseTable(bTestOpenNoError) != 0) { // Open Failed... an error has already been reported. if (bTestOpenNoError) CPLErrorReset(); return -1; } } else if (nTableId == m_nCurBaseTableId && m_poCurBaseTable != NULL) { // The right table is already opened. Not much to do! m_poCurBaseTable->ResetReading(); return 0; } else { TABFeature *poIndexFeature = m_poIndexTable->GetFeatureRef(nTableId); if (poIndexFeature) { if (OpenBaseTable(poIndexFeature, bTestOpenNoError) != 0) { // Open Failed... an error has already been reported. if (bTestOpenNoError) CPLErrorReset(); return -1; } } } return 0; }
/********************************************************************** * TABSeamless::GetNextFeatureId() * * Returns feature id that follows nPrevId, or -1 if it is the * last feature id. Pass nPrevId=-1 to fetch the first valid feature id. **********************************************************************/ GIntBig TABSeamless::GetNextFeatureId(GIntBig nPrevId) { if (m_poIndexTable == nullptr) return -1; // File is not opened yet if (nPrevId == -1 || m_nCurBaseTableId != ExtractBaseTableId(nPrevId)) { if (OpenBaseTable(ExtractBaseTableId(nPrevId)) != 0) return -1; } int nId = ExtractBaseFeatureId(nPrevId); do { nId = (int) m_poCurBaseTable->GetNextFeatureId(nId); if (nId != -1) return EncodeFeatureId(m_nCurBaseTableId, nId); // Found one! else OpenNextBaseTable(); // Skip to next tile and loop again } while (nId == -1 && !m_bEOF && m_poCurBaseTable); return -1; }
/********************************************************************** * TABSeamless::GetFeatureRef() * * Fill and return a TABFeature object for the specified feature id. * * The returned pointer is a reference to an object owned and maintained * by this TABSeamless object. It should not be altered or freed by the * caller and its contents is guaranteed to be valid only until the next * call to GetFeatureRef() or Close(). * * Returns NULL if the specified feature id does not exist of if an * error happened. In any case, CPLError() will have been called to * report the reason of the failure. **********************************************************************/ TABFeature *TABSeamless::GetFeatureRef(GIntBig nFeatureId) { if (m_poIndexTable == nullptr) return nullptr; // File is not opened yet if (nFeatureId == m_nCurFeatureId && m_poCurFeature) return m_poCurFeature; if (m_nCurBaseTableId != ExtractBaseTableId(nFeatureId)) { if (OpenBaseTable(ExtractBaseTableId(nFeatureId)) != 0) return nullptr; } if (m_poCurBaseTable) { if (m_poCurFeature) delete m_poCurFeature; m_poCurFeature = nullptr; TABFeature* poCurFeature = (TABFeature*)m_poCurBaseTable->GetFeature(ExtractBaseFeatureId(nFeatureId)); if( poCurFeature == nullptr ) return nullptr; m_poCurFeature = new TABFeature(m_poFeatureDefnRef); m_poCurFeature->SetFrom(poCurFeature); delete poCurFeature; m_nCurFeatureId = nFeatureId; m_poCurFeature->SetFID(nFeatureId); return m_poCurFeature; } return nullptr; }
/********************************************************************** * TABSeamless::OpenForRead() * * Open for reading * * Returns 0 on success, -1 on error. **********************************************************************/ int TABSeamless::OpenForRead(const char *pszFname, GBool bTestOpenNoError /*= FALSE*/ ) { int nFnameLen = 0; m_eAccessMode = TABRead; /*----------------------------------------------------------------- * Read main .TAB (text) file *----------------------------------------------------------------*/ m_pszFname = CPLStrdup(pszFname); #ifndef _WIN32 /*----------------------------------------------------------------- * On Unix, make sure extension uses the right cases * We do it even for write access because if a file with the same * extension already exists we want to overwrite it. *----------------------------------------------------------------*/ TABAdjustFilenameExtension(m_pszFname); #endif /*----------------------------------------------------------------- * Open .TAB file... since it's a small text file, we will just load * it as a stringlist in memory. *----------------------------------------------------------------*/ char **papszTABFile = TAB_CSLLoad(m_pszFname); if (papszTABFile == NULL) { if (!bTestOpenNoError) { CPLError(CE_Failure, CPLE_FileIO, "Failed opening %s.", m_pszFname); } CPLFree(m_pszFname); CSLDestroy(papszTABFile); return -1; } /*------------------------------------------------------------- * Look for a metadata line with "\IsSeamless" = "TRUE". * If there is no such line, then we may have a valid .TAB file, * but we do not support it in this class. *------------------------------------------------------------*/ GBool bSeamlessFound = FALSE; for (int i=0; !bSeamlessFound && papszTABFile && papszTABFile[i]; i++) { const char *pszStr = papszTABFile[i]; while(*pszStr != '\0' && isspace((unsigned char)*pszStr)) pszStr++; if (EQUALN(pszStr, "\"\\IsSeamless\" = \"TRUE\"", 21)) bSeamlessFound = TRUE; } CSLDestroy(papszTABFile); if ( !bSeamlessFound ) { if (!bTestOpenNoError) CPLError(CE_Failure, CPLE_NotSupported, "%s does not appear to be a Seamless TAB File. " "This type of .TAB file cannot be read by this library.", m_pszFname); else CPLErrorReset(); CPLFree(m_pszFname); return -1; } /*----------------------------------------------------------------- * OK, this appears to be a valid seamless TAB dataset... * Extract the path component from the main .TAB filename * to build the filename of the base tables *----------------------------------------------------------------*/ m_pszPath = CPLStrdup(m_pszFname); nFnameLen = strlen(m_pszPath); for( ; nFnameLen > 0; nFnameLen--) { if (m_pszPath[nFnameLen-1] == '/' || m_pszPath[nFnameLen-1] == '\\' ) { break; } m_pszPath[nFnameLen-1] = '\0'; } /*----------------------------------------------------------------- * Open the main Index table and look for the "Table" field that * should contain the path to the base table for each rectangle MBR *----------------------------------------------------------------*/ m_poIndexTable = new TABFile; if (m_poIndexTable->Open(m_pszFname, "rb", bTestOpenNoError) != 0) { // Open Failed... an error has already been reported, just return. if (bTestOpenNoError) CPLErrorReset(); Close(); return -1; } OGRFeatureDefn *poDefn = m_poIndexTable->GetLayerDefn(); if (poDefn == NULL || (m_nTableNameField = poDefn->GetFieldIndex("Table")) == -1) { if (!bTestOpenNoError) CPLError(CE_Failure, CPLE_NotSupported, "Open Failed: Field 'Table' not found in Seamless " "Dataset '%s'. This is type of file not currently " "supported.", m_pszFname); Close(); return -1; } /* Set the number of bits required to encode features for this index * table. (Based of the number of features) */ int s=0, numFeatures = m_poIndexTable->GetFeatureCount(FALSE); do s++, numFeatures>>=1; while(numFeatures); m_nIndexTableFIDBits= s+1; /*----------------------------------------------------------------- * We need to open the first table to get its FeatureDefn *----------------------------------------------------------------*/ if (OpenBaseTable(-1, bTestOpenNoError) != 0 ) { // Open Failed... an error has already been reported, just return. if (bTestOpenNoError) CPLErrorReset(); Close(); return -1; } CPLAssert(m_poCurBaseTable); m_poFeatureDefnRef = m_poCurBaseTable->GetLayerDefn(); m_poFeatureDefnRef->Reference(); return 0; }
void TABSeamless::ResetReading() { if (m_poIndexTable) OpenBaseTable(-1); // Asking for first table resets everything }