⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ogr_miattrind.cpp

📁 mitab,读取MapInfo的地图文件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
 * $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 + -