📄 ogr_miattrind.cpp
字号:
/****************************************************************************** * $Id: ogr_miattrind.cpp,v 1.4 2003/12/02 19:59:39 warmerda Exp $ * * 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. ****************************************************************************** * * $Log: ogr_miattrind.cpp,v $ * Revision 1.4 2003/12/02 19:59:39 warmerda * Support adding only specific fields to the index when re-indexing all * features. * * Revision 1.3 2003/05/21 04:54:29 warmerda * avoid warnings about unused formal parameters and possibly uninit variables * * Revision 1.2 2003/03/20 20:21:40 warmerda * implement DROP INDEX command * * Revision 1.1 2003/03/04 05:47:03 warmerda * New * */#include "ogr_attrind.h"#include "mitab/mitab_priv.h"#include "cpl_minixml.h"CPL_CVSID("$Id: ogr_miattrind.cpp,v 1.4 2003/12/02 19:59:39 warmerda Exp $");/************************************************************************//* 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(); 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. *//************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -