OGRFeature *OGRNTFLayer::GetNextFeature() { OGRFeature *poFeature = NULL; /* -------------------------------------------------------------------- */ /* Have we processed all features already? */ /* -------------------------------------------------------------------- */ if( iCurrentReader == poDS->GetFileCount() ) return NULL; /* -------------------------------------------------------------------- */ /* Do we need to open a file? */ /* -------------------------------------------------------------------- */ if( iCurrentReader == -1 ) { iCurrentReader++; nCurrentPos = -1; } NTFFileReader *poCurrentReader = poDS->GetFileReader(iCurrentReader); if( poCurrentReader->GetFP() == NULL ) { poCurrentReader->Open(); } /* -------------------------------------------------------------------- */ /* Ensure we are reading on from the same point we were reading */ /* from for the last feature, even if some other access */ /* mechanism has moved the file pointer. */ /* -------------------------------------------------------------------- */ if( nCurrentPos != -1 ) poCurrentReader->SetFPPos( nCurrentPos, nCurrentFID ); else poCurrentReader->Reset(); /* -------------------------------------------------------------------- */ /* Read features till we find one that satisfies our current */ /* spatial criteria. */ /* -------------------------------------------------------------------- */ while( TRUE ) { poFeature = poCurrentReader->ReadOGRFeature( this ); if( poFeature == NULL ) break; m_nFeaturesRead++; if( (m_poFilterGeom == NULL || poFeature->GetGeometryRef() == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) ) break; delete poFeature; } /* -------------------------------------------------------------------- */ /* If we get NULL the file must be all consumed, advance to the */ /* next file that contains features for this layer. */ /* -------------------------------------------------------------------- */ if( poFeature == NULL ) { poCurrentReader->Close(); if( poDS->GetOption("CACHING") != NULL && EQUAL(poDS->GetOption("CACHING"),"OFF") ) { poCurrentReader->DestroyIndex(); } do { iCurrentReader++; } while( iCurrentReader < poDS->GetFileCount() && !poDS->GetFileReader(iCurrentReader)->TestForLayer(this) ); nCurrentPos = -1; nCurrentFID = 1; poFeature = GetNextFeature(); } else { poCurrentReader->GetFPPos(&nCurrentPos, &nCurrentFID); } return poFeature; }
int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen, char ** papszLimitedFileList ) { VSIStatBuf stat; char **papszFileList = NULL; pszName = CPLStrdup( pszFilename ); /* -------------------------------------------------------------------- */ /* Is the given path a directory or a regular file? */ /* -------------------------------------------------------------------- */ if( CPLStat( pszFilename, &stat ) != 0 || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) ) { if( !bTestOpen ) CPLError( CE_Failure, CPLE_AppDefined, "%s is neither a file or directory, NTF access failed.\n", pszFilename ); return FALSE; } /* -------------------------------------------------------------------- */ /* Build a list of filenames we figure are NTF files. */ /* -------------------------------------------------------------------- */ if( VSI_ISREG(stat.st_mode) ) { papszFileList = CSLAddString( NULL, pszFilename ); } else { char **candidateFileList = CPLReadDir( pszFilename ); int i; for( i = 0; candidateFileList != NULL && candidateFileList[i] != NULL; i++ ) { if( papszLimitedFileList != NULL && CSLFindString(papszLimitedFileList, candidateFileList[i]) == -1 ) { continue; } if( strlen(candidateFileList[i]) > 4 && EQUALN(candidateFileList[i] + strlen(candidateFileList[i])-4, ".ntf",4) ) { char fullFilename[2048]; sprintf( fullFilename, "%s%c%s", pszFilename, #ifdef WIN32 '\\', #else '/', #endif candidateFileList[i] ); papszFileList = CSLAddString( papszFileList, fullFilename ); } } CSLDestroy( candidateFileList ); if( CSLCount(papszFileList) == 0 ) { if( !bTestOpen ) CPLError( CE_Failure, CPLE_OpenFailed, "No candidate NTF files (.ntf) found in\n" "directory: %s", pszFilename ); return FALSE; } } /* -------------------------------------------------------------------- */ /* Loop over all these files trying to open them. In testopen */ /* mode we first read the first 80 characters, to verify that */ /* it looks like an NTF file. Note that we don't keep the file */ /* open ... we don't want to occupy alot of file handles when */ /* handling a whole directory. */ /* -------------------------------------------------------------------- */ int i; papoNTFFileReader = (NTFFileReader **) CPLCalloc(sizeof(void*), CSLCount(papszFileList)); for( i = 0; papszFileList[i] != NULL; i++ ) { if( bTestOpen ) { char szHeader[80]; FILE *fp; int j; fp = VSIFOpen( papszFileList[i], "rb" ); if( fp == NULL ) continue; if( VSIFRead( szHeader, 80, 1, fp ) < 1 ) { VSIFClose( fp ); continue; } VSIFClose( fp ); if( !EQUALN(szHeader,"01",2) ) continue; for( j = 0; j < 80; j++ ) { if( szHeader[j] == 10 || szHeader[j] == 13 ) break; } if( j == 80 || szHeader[j-1] != '%' ) continue; } NTFFileReader *poFR; poFR = new NTFFileReader( this ); if( !poFR->Open( papszFileList[i] ) ) { delete poFR; CSLDestroy( papszFileList ); return FALSE; } poFR->SetBaseFID( nNTFFileCount * 1000000 + 1 ); poFR->Close(); EnsureTileNameUnique( poFR ); papoNTFFileReader[nNTFFileCount++] = poFR; } CSLDestroy( papszFileList ); if( nNTFFileCount == 0 ) return FALSE; /* -------------------------------------------------------------------- */ /* Establish generic layers. */ /* -------------------------------------------------------------------- */ EstablishGenericLayers(); /* -------------------------------------------------------------------- */ /* Loop over all the files, collecting a unique feature class */ /* listing. */ /* -------------------------------------------------------------------- */ for( int iSrcFile = 0; iSrcFile < nNTFFileCount; iSrcFile++ ) { NTFFileReader *poSrcReader = papoNTFFileReader[iSrcFile]; for( int iSrcFC = 0; iSrcFC < poSrcReader->GetFCCount(); iSrcFC++ ) { int iDstFC; char *pszSrcFCName, *pszSrcFCNum; poSrcReader->GetFeatureClass( iSrcFC, &pszSrcFCNum, &pszSrcFCName); for( iDstFC = 0; iDstFC < nFCCount; iDstFC++ ) { if( EQUAL(pszSrcFCNum,papszFCNum[iDstFC]) ) break; } if( iDstFC >= nFCCount ) { nFCCount++; papszFCNum = CSLAddString(papszFCNum,pszSrcFCNum); papszFCName = CSLAddString(papszFCName,pszSrcFCName); } } } /* -------------------------------------------------------------------- */ /* Create a new layer specifically for feature classes. */ /* -------------------------------------------------------------------- */ if( nFCCount > 0 ) poFCLayer = new OGRNTFFeatureClassLayer( this ); else poFCLayer = NULL; return TRUE; }