📄 tabseamless.cpp
字号:
// tabseamless.cpp: implementation of the TABSeamless class.////////////////////////////////////////////////////////////////////////#include "tabseamless.h"#include "ugk_errhandle.h"#include "ugk_memopr.h"#include "ugk_string.h"/********************************************************************** * TABSeamless::TABSeamless() * * Constructor. **********************************************************************/TABSeamless::TABSeamless(){ m_pszFname = NULL; m_pszPath = NULL; m_eAccessMode = TABRead; m_poFeatureDefnRef = NULL; m_poCurFeature = NULL; m_nCurFeatureId = -1; m_poIndexTable = NULL; m_nTableNameField = -1; m_nCurBaseTableId = -1; m_poCurBaseTable = NULL; m_bEOF = FALSE;}/********************************************************************** * TABSeamless::~TABSeamless() * * Destructor. **********************************************************************/TABSeamless::~TABSeamless(){ Close();}void TABSeamless::ResetReading(){ if (m_poIndexTable) OpenBaseTable(-1); // Asking for first table resets everything}/********************************************************************** * TABSeamless::Open() * * Open a seamless .TAB dataset and initialize the structures to be ready * to read features from it. * * Seamless .TAB files are composed of a main .TAB file in which each * feature is the MBR of a base table. * * Set bTestOpenNoError=TRUE to silently return -1 with no error message * if the file cannot be opened. This is intended to be used in the * context of a TestOpen() function. The default value is FALSE which * means that an error is reported if the file cannot be opened. * * Returns 0 on success, -1 on error. **********************************************************************/int TABSeamless::Open(const char *pszFname, const char *pszAccess, UGKBool bTestOpenNoError /*= FALSE*/ ){ char nStatus = 0; if (m_poIndexTable) { UGKError(ET_Failure, UGKErr_AssertionFailed, "Open() failed: object already contains an open file"); return -1; } /*----------------------------------------------------------------- * Validate access mode and call the right open method *----------------------------------------------------------------*/ if (EQUALN(pszAccess, "r", 1)) { m_eAccessMode = TABRead; nStatus = OpenForRead(pszFname, bTestOpenNoError); } else { UGKError(ET_Failure, UGKErr_NotSupported, "Open() failed: access mode \"%s\" not supported", pszAccess); return -1; } return nStatus;}/********************************************************************** * TABSeamless::OpenForRead() * * Open for reading * * Returns 0 on success, -1 on error. **********************************************************************/int TABSeamless::OpenForRead(const char *pszFname, UGKBool bTestOpenNoError /*= FALSE*/ ){ int nFnameLen = 0; m_eAccessMode = TABRead; /*----------------------------------------------------------------- * Read main .TAB (text) file *----------------------------------------------------------------*/ m_pszFname = UGKStrdup(pszFname);#ifndef WIN32APP /*----------------------------------------------------------------- * 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 = LoadFileToList(m_pszFname); if (papszTABFile == NULL) { if (!bTestOpenNoError) { UGKError(ET_Failure, UGKErr_FileIO, "Failed opening %s.", m_pszFname); } UGK_Free(m_pszFname); FreeStrList(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. *------------------------------------------------------------*/ UGKBool bSeamlessFound = FALSE; for (int i=0; !bSeamlessFound && papszTABFile && papszTABFile[i]; i++) { const char *pszStr = papszTABFile[i]; while(*pszStr != '\0' && isspace(*pszStr)) pszStr++; if (EQUALN(pszStr, "\"\\IsSeamless\" = \"TRUE\"", 21)) bSeamlessFound = TRUE; } FreeStrList(papszTABFile); if ( !bSeamlessFound ) { if (!bTestOpenNoError) UGKError(ET_Failure, UGKErr_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 UGKErrorReset(); UGK_Free(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 = UGKStrdup(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) UGKErrorReset(); Close(); return -1; } UGKFeatureDefn *poDefn = m_poIndexTable->GetLayerDefn(); if (poDefn == NULL || (m_nTableNameField = poDefn->GetFieldIndex("Table")) == -1) { if (!bTestOpenNoError) UGKError(ET_Failure, UGKErr_NotSupported, "Open Failed: Field 'Table' not found in Seamless " "Dataset '%s'. This is type of file not currently " "supported.", m_pszFname); Close(); return -1; } /*----------------------------------------------------------------- * Check number of features in index table to make sure we won't * overflow the number of bytes used for table ids in the encoded * feature ids. We currently use 12 bits for table id + 20 bits for FID *----------------------------------------------------------------*/ if (m_poIndexTable->GetFeatureCount(FALSE) > 0x7ff) { if (!bTestOpenNoError) UGKError(ET_Failure, UGKErr_NotSupported, "Open Failed: The current implementation is limited " "to 2047 base tables. The seamless file '%s' contains " "%d tables and cannot be opened.", m_pszFname, m_poIndexTable->GetFeatureCount(FALSE)); Close(); return -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) UGKErrorReset(); Close(); return -1; } assert(m_poCurBaseTable); m_poFeatureDefnRef = m_poCurBaseTable->GetLayerDefn(); m_poFeatureDefnRef->Reference(); return 0;}/********************************************************************** * TABSeamless::Close() * * Close current file, and release all memory used. * * Returns 0 on success, -1 on error. **********************************************************************/int TABSeamless::Close(){ if (m_poIndexTable) delete m_poIndexTable; // Automatically closes. m_poIndexTable = NULL; if (m_poFeatureDefnRef && m_poFeatureDefnRef->Dereference() == 0) delete m_poFeatureDefnRef; m_poFeatureDefnRef = NULL; if (m_poCurFeature) delete m_poCurFeature; m_poCurFeature = NULL; m_nCurFeatureId = -1; UGK_Free(m_pszFname); m_pszFname = NULL; UGK_Free(m_pszPath); m_pszPath = NULL; m_nTableNameField = -1; m_nCurBaseTableId = -1; if (m_poCurBaseTable) delete m_poCurBaseTable; m_poCurBaseTable = NULL; return 0;}/********************************************************************** * TABSeamless::OpenBaseTable() * * Open the base table for specified IndexFeature. * * Returns 0 on success, -1 on error. **********************************************************************/int TABSeamless::OpenBaseTable(TABFeature *poIndexFeature, UGKBool bTestOpenNoError /*=FALSE*/){ assert(poIndexFeature); /*----------------------------------------------------------------- * Fetch table id. We actually use the index feature's ids as the * base table ids. *----------------------------------------------------------------*/ int nTableId = poIndexFeature->GetFID(); if (m_nCurBaseTableId == nTableId && m_poCurBaseTable != NULL) { // The right table is already opened. Not much to do! m_poCurBaseTable->ResetReading(); return 0; } // Close current base table if (m_poCurBaseTable) delete m_poCurBaseTable; m_nCurBaseTableId = -1; m_bEOF = FALSE; /*----------------------------------------------------------------- * Build full path to the table and open it. * __TODO__ For now we assume that all table filename paths are relative * but we may have to deal with absolute filenames as well. *----------------------------------------------------------------*/ const char *pszName = poIndexFeature->GetFieldAsString(m_nTableNameField); char *pszFname = UGKStrdup(UGKSPrintf("%s%s", m_pszPath, pszName));#ifndef WIN32APP // On Unix, replace any '\\' in path with '/' char *pszPtr = pszFname; while((pszPtr = strchr(pszPtr, '\\')) != NULL) { *pszPtr = '/'; pszPtr++; }#endif m_poCurBaseTable = new TABFile; if (m_poCurBaseTable->Open(pszFname, "rb", bTestOpenNoError) != 0) { // Open Failed... an error has already been reported, just return. if (bTestOpenNoError) UGKErrorReset(); delete m_poCurBaseTable; m_poCurBaseTable = NULL; UGK_Free(pszFname); return -1; } // Set the spatial filter to the new table if( m_poFilterGeom != NULL && m_poCurBaseTable ) { m_poCurBaseTable->SetSpatialFilter( m_poFilterGeom ); } m_nCurBaseTableId = nTableId; UGK_Free(pszFname); return 0;}/********************************************************************** * TABSeamless::OpenBaseTable() * * Open the base table for specified IndexFeature. * * Returns 0 on success, -1 on error. **********************************************************************/int TABSeamless::OpenBaseTable(int nTableId, UGKBool 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) UGKErrorReset(); 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -