📄 ogr_miattrind.cpp
字号:
/******************************************************************************
* $Id: ogr_miattrind.cpp 12519 2007-10-23 15:28:53Z mloskot $
*
* Project: OpenGIS Simple Features Reference Implementation
* Purpose: Implements interface to MapInfo .ID files used as attribute
* indexes.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 2003, Frank Warmerdam
*
* 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.
****************************************************************************/
#include "ogr_attrind.h"
#include "mitab_priv.h"
#include "cpl_minixml.h"
CPL_CVSID("$Id: ogr_miattrind.cpp 12519 2007-10-23 15:28:53Z mloskot $");
/************************************************************************/
/* OGRMIAttrIndex */
/* */
/* MapInfo .ID implementation of access to one fields */
/* indexing. */
/************************************************************************/
class OGRMILayerAttrIndex;
class OGRMIAttrIndex : public OGRAttrIndex
{
public:
int iIndex;
TABINDFile *poINDFile;
OGRMILayerAttrIndex *poLIndex;
OGRFieldDefn *poFldDefn;
int iField;
OGRMIAttrIndex( OGRMILayerAttrIndex *, int iIndex, int iField);
~OGRMIAttrIndex();
GByte *BuildKey( OGRField *psKey );
long GetFirstMatch( OGRField *psKey );
long *GetAllMatches( OGRField *psKey );
OGRErr AddEntry( OGRField *psKey, long nFID );
OGRErr RemoveEntry( OGRField *psKey, long nFID );
OGRErr Clear();
};
/************************************************************************/
/* ==================================================================== */
/* OGRMILayerAttrIndex */
/* */
/* MapInfo .ID specific implementation of a layer attribute */
/* index. */
/* ==================================================================== */
/************************************************************************/
class OGRMILayerAttrIndex : public OGRLayerAttrIndex
{
public:
TABINDFile *poINDFile;
int nIndexCount;
OGRMIAttrIndex **papoIndexList;
char *pszMetadataFilename;
char *pszMIINDFilename;
OGRMILayerAttrIndex();
virtual ~OGRMILayerAttrIndex();
/* base class virtual methods */
OGRErr Initialize( const char *pszIndexPath, OGRLayer * );
OGRErr CreateIndex( int iField );
OGRErr DropIndex( int iField );
OGRErr IndexAllFeatures( int iField = -1 );
OGRErr AddToIndex( OGRFeature *poFeature, int iField = -1 );
OGRErr RemoveFromIndex( OGRFeature *poFeature );
OGRAttrIndex *GetFieldIndex( int iField );
/* custom to OGRMILayerAttrIndex */
OGRErr SaveConfigToXML();
OGRErr LoadConfigFromXML();
void AddAttrInd( int iField, int iINDIndex );
OGRLayer *GetLayer() { return poLayer; }
};
/************************************************************************/
/* OGRMILayerAttrIndex() */
/************************************************************************/
OGRMILayerAttrIndex::OGRMILayerAttrIndex()
{
poINDFile = NULL;
nIndexCount = 0;
papoIndexList = NULL;
}
/************************************************************************/
/* ~OGRMILayerAttrIndex() */
/************************************************************************/
OGRMILayerAttrIndex::~OGRMILayerAttrIndex()
{
if( poINDFile != NULL )
{
poINDFile->Close();
delete poINDFile;
poINDFile = NULL;
}
for( int i = 0; i < nIndexCount; i++ )
delete papoIndexList[i];
CPLFree( papoIndexList );
CPLFree( pszMIINDFilename );
CPLFree( pszMetadataFilename );
}
/************************************************************************/
/* Initialize() */
/************************************************************************/
OGRErr OGRMILayerAttrIndex::Initialize( const char *pszIndexPathIn,
OGRLayer *poLayerIn )
{
if( poLayerIn == poLayer )
return OGRERR_NONE;
/* -------------------------------------------------------------------- */
/* Capture input information and form static pathnames. */
/* -------------------------------------------------------------------- */
poLayer = poLayerIn;
pszIndexPath = CPLStrdup( pszIndexPathIn );
pszMetadataFilename = CPLStrdup(
CPLResetExtension( pszIndexPathIn, "idm" ) );
pszMIINDFilename = CPLStrdup(CPLResetExtension( pszIndexPathIn, "ind" ));
/* -------------------------------------------------------------------- */
/* If a metadata file already exists, load it. */
/* -------------------------------------------------------------------- */
OGRErr eErr;
VSIStatBuf sStat;
if( VSIStat( pszMetadataFilename, &sStat ) == 0 )
{
eErr = LoadConfigFromXML();
if( eErr != OGRERR_NONE )
return eErr;
}
return OGRERR_NONE;
}
/************************************************************************/
/* LoadConfigFromXML() */
/************************************************************************/
OGRErr OGRMILayerAttrIndex::LoadConfigFromXML()
{
FILE *fp;
int nXMLSize;
char *pszRawXML;
CPLAssert( poINDFile == NULL );
/* -------------------------------------------------------------------- */
/* Read the XML file. */
/* -------------------------------------------------------------------- */
fp = VSIFOpen( pszMetadataFilename, "rb" );
if( fp == NULL )
return OGRERR_NONE;
VSIFSeek( fp, 0, SEEK_END );
nXMLSize = VSIFTell( fp );
VSIFSeek( fp, 0, SEEK_SET );
pszRawXML = (char *) CPLMalloc(nXMLSize+1);
pszRawXML[nXMLSize] = '\0';
VSIFRead( pszRawXML, nXMLSize, 1, fp );
VSIFClose( fp );
/* -------------------------------------------------------------------- */
/* Parse the XML. */
/* -------------------------------------------------------------------- */
CPLXMLNode *psRoot = CPLParseXMLString( pszRawXML );
CPLFree( pszRawXML );
if( psRoot == NULL )
return OGRERR_FAILURE;
/* -------------------------------------------------------------------- */
/* Open the index file. */
/* -------------------------------------------------------------------- */
poINDFile = new TABINDFile();
/* NOTE: Replaced r+ with r according to explanation in Ticket #1620.
* This change has to be observed if it doesn't cause any
* problems in future. (mloskot)
*/
if( poINDFile->Open( pszMetadataFilename, "r" ) != 0 )
{
CPLDestroyXMLNode( psRoot );
CPLError( CE_Failure, CPLE_OpenFailed,
"Failed to open index file %s.",
pszMIINDFilename );
return OGRERR_FAILURE;
}
/* -------------------------------------------------------------------- */
/* Process each attrindex. */
/* -------------------------------------------------------------------- */
CPLXMLNode *psAttrIndex;
for( psAttrIndex = psRoot->psChild;
psAttrIndex != NULL;
psAttrIndex = psAttrIndex->psNext )
{
int iField, iIndexIndex;
if( psAttrIndex->eType != CXT_Element
|| !EQUAL(psAttrIndex->pszValue,"OGRMIAttrIndex") )
continue;
iField = atoi(CPLGetXMLValue(psAttrIndex,"FieldIndex","-1"));
iIndexIndex = atoi(CPLGetXMLValue(psAttrIndex,"IndexIndex","-1"));
if( iField == -1 || iIndexIndex == -1 )
{
CPLError( CE_Warning, CPLE_AppDefined,
"Skipping corrupt OGRMIAttrIndex entry." );
continue;
}
AddAttrInd( iField, iIndexIndex );
}
CPLDestroyXMLNode( psRoot );
CPLDebug( "OGR", "Restored %d field indexes for layer %s from %s on %s.",
nIndexCount, poLayer->GetLayerDefn()->GetName(),
pszMetadataFilename, pszMIINDFilename );
return OGRERR_NONE;
}
/************************************************************************/
/* SaveConfigToXML() */
/************************************************************************/
OGRErr OGRMILayerAttrIndex::SaveConfigToXML()
{
if( nIndexCount == 0 )
return OGRERR_NONE;
/* -------------------------------------------------------------------- */
/* Create the XML tree corresponding to this layer. */
/* -------------------------------------------------------------------- */
CPLXMLNode *psRoot;
psRoot = CPLCreateXMLNode( NULL, CXT_Element, "OGRMILayerAttrIndex" );
CPLCreateXMLElementAndValue( psRoot, "MIIDFilename",
CPLGetFilename( pszMIINDFilename ) );
for( int i = 0; i < nIndexCount; i++ )
{
OGRMIAttrIndex *poAI = papoIndexList[i];
CPLXMLNode *psIndex;
psIndex = CPLCreateXMLNode( psRoot, CXT_Element, "OGRMIAttrIndex" );
CPLCreateXMLElementAndValue( psIndex, "FieldIndex",
CPLSPrintf( "%d", poAI->iField ) );
CPLCreateXMLElementAndValue( psIndex, "FieldName",
poLayer->GetLayerDefn()->GetFieldDefn(poAI->iField)->GetNameRef() );
CPLCreateXMLElementAndValue( psIndex, "IndexIndex",
CPLSPrintf( "%d", poAI->iIndex ) );
}
/* -------------------------------------------------------------------- */
/* Save it. */
/* -------------------------------------------------------------------- */
char *pszRawXML = CPLSerializeXMLTree( psRoot );
FILE *fp;
CPLDestroyXMLNode( psRoot );
fp = VSIFOpen( pszMetadataFilename, "wb" );
if( fp == NULL )
{
CPLError( CE_Failure, CPLE_OpenFailed,
"Failed to pen `%s' for write.",
pszMetadataFilename );
CPLFree( pszRawXML );
return OGRERR_FAILURE;
}
VSIFWrite( pszRawXML, 1, strlen(pszRawXML), fp );
VSIFClose( fp );
CPLFree( pszRawXML );
return OGRERR_NONE;
}
/************************************************************************/
/* IndexAllFeatures() */
/************************************************************************/
OGRErr OGRMILayerAttrIndex::IndexAllFeatures( int iField )
{
OGRFeature *poFeature;
poLayer->ResetReading();
while( (poFeature = poLayer->GetNextFeature()) != NULL )
{
OGRErr eErr = AddToIndex( poFeature, iField );
delete poFeature;
if( eErr != CE_None )
return eErr;
}
poLayer->ResetReading();
return OGRERR_NONE;
}
/************************************************************************/
/* CreateIndex() */
/* */
/* Create an index corresponding to the indicated field, but do */
/* not populate it. Use IndexAllFeatures() for that. */
/************************************************************************/
OGRErr OGRMILayerAttrIndex::CreateIndex( int iField )
{
/* -------------------------------------------------------------------- */
/* Do we have an open .ID file yet? If not, create it now. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -