📄 mitab_tabseamless.cpp
字号:
/********************************************************************** * $Id: mitab_tabseamless.cpp,v 1.6 2004/06/30 20:29:04 dmorissette Exp $ * * Name: mitab_tabseamless.cpp * Project: MapInfo TAB Read/Write library * Language: C++ * Purpose: Implementation of the TABSeamless class, used to handle seamless * .TAB datasets. * Author: Daniel Morissette, dmorissette@dmsolutions.ca * ********************************************************************** * Copyright (c) 1999-2004, Daniel Morissette * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ********************************************************************** * * $Log: mitab_tabseamless.cpp,v $ * Revision 1.6 2004/06/30 20:29:04 dmorissette * Fixed refs to old address danmo@videotron.ca * * Revision 1.5 2004/03/12 16:29:05 dmorissette * Fixed 2 memory leaks (bug 283) * * Revision 1.4 2002/06/28 18:32:37 julien * Add SetSpatialFilter() in TABSeamless class (Bug 164, MapServer) * Use double for comparison in Coordsys2Int() in mitab_mapheaderblock.cpp * * Revision 1.3 2001/09/19 14:21:36 daniel * On Unix: replace '\\' in file path read from tab index with '/' * * Revision 1.2 2001/03/15 03:57:51 daniel * Added implementation for new OGRLayer::GetExtent(), returning data MBR. * * Revision 1.1 2001/03/09 04:38:04 danmo * Update from master - version 1.1.0 * * Revision 1.1 2001/03/09 04:16:02 daniel * Added TABSeamless for reading seamless TAB files * **********************************************************************/#include "mitab.h"#include "mitab_utils.h"#include <ctype.h> /* isspace() *//*===================================================================== * class TABSeamless * * Support for seamless vector datasets. * * The current implementation has some limitations (base assumptions): * - Read-only * - Base tables can only be of type TABFile * - Feature Ids are build using the id of the base table in the main * index table and the actual feature id of each object inside the base * tables. Since we are limited to 32 bits for feature ids, this implies * a limit on the (number of base tables) * (features/table) * The current implementation can support up to 2047 (0x7ff) base tables * and a max of 1048575 (0xfffff) features per base table. * - Only relative paths are supported for base tables names. * *====================================================================*//********************************************************************** * 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, GBool bTestOpenNoError /*= FALSE*/ ){ char nStatus = 0; if (m_poIndexTable) { CPLError(CE_Failure, CPLE_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 { CPLError(CE_Failure, CPLE_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, 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(*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; } /*----------------------------------------------------------------- * 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) CPLError(CE_Failure, CPLE_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) CPLErrorReset(); Close(); return -1; } CPLAssert(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; CPLFree(m_pszFname); m_pszFname = NULL; CPLFree(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, GBool bTestOpenNoError /*=FALSE*/){ CPLAssert(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 = CPLStrdup(CPLSPrintf("%s%s", m_pszPath, pszName));#ifndef _WIN32 // 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) CPLErrorReset(); delete m_poCurBaseTable; m_poCurBaseTable = NULL; CPLFree(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; CPLFree(pszFname); return 0;}/********************************************************************** * 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -