📄 mitab_tabseamless.cpp
字号:
/**********************************************************************
* $Id: mitab_tabseamless.cpp,v 1.7 2007/06/21 14:00:23 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.7 2007/06/21 14:00:23 dmorissette
* Added missing cast in isspace() calls to avoid failed assertion on Windows
* (MITAB bug 1737, GDAL ticket 1678))
*
* 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((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;
}
/*-----------------------------------------------------------------
* 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -