LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/generic - ogr_miattrind.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 231
Code covered: 76.2 % Executed lines: 176

       1                 : /******************************************************************************
       2                 :  * $Id: ogr_miattrind.cpp 19745 2010-05-21 21:41:30Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements interface to MapInfo .ID files used as attribute
       6                 :  *           indexes.  
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2003, Frank Warmerdam
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "ogr_attrind.h"
      32                 : #include "mitab/mitab_priv.h"
      33                 : #include "cpl_minixml.h"
      34                 : 
      35                 : CPL_CVSID("$Id: ogr_miattrind.cpp 19745 2010-05-21 21:41:30Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                            OGRMIAttrIndex                            */
      39                 : /*                                                                      */
      40                 : /*      MapInfo .ID implementation of access to one fields              */
      41                 : /*      indexing.                                                       */
      42                 : /************************************************************************/
      43                 : 
      44                 : class OGRMILayerAttrIndex;
      45                 : 
      46                 : class OGRMIAttrIndex : public OGRAttrIndex
      47                 : {
      48                 : public:
      49                 :     int         iIndex;
      50                 :     TABINDFile  *poINDFile;
      51                 :     OGRMILayerAttrIndex *poLIndex;
      52                 :     OGRFieldDefn *poFldDefn;
      53                 : 
      54                 :     int         iField;
      55                 : 
      56                 :                 OGRMIAttrIndex( OGRMILayerAttrIndex *, int iIndex, int iField);
      57                 :                ~OGRMIAttrIndex();
      58                 : 
      59                 :     GByte      *BuildKey( OGRField *psKey );
      60                 :     long        GetFirstMatch( OGRField *psKey );
      61                 :     long       *GetAllMatches( OGRField *psKey );
      62                 : 
      63                 :     OGRErr      AddEntry( OGRField *psKey, long nFID );
      64                 :     OGRErr      RemoveEntry( OGRField *psKey, long nFID );
      65                 : 
      66                 :     OGRErr      Clear();
      67                 : };
      68                 : 
      69                 : /************************************************************************/
      70                 : /* ==================================================================== */
      71                 : /*                         OGRMILayerAttrIndex                          */
      72                 : /*                                                                      */
      73                 : /*      MapInfo .ID specific implementation of a layer attribute        */
      74                 : /*      index.                                                          */
      75                 : /* ==================================================================== */
      76                 : /************************************************************************/
      77                 : 
      78                 : class OGRMILayerAttrIndex : public OGRLayerAttrIndex
      79                 : {
      80                 : public:
      81                 :     TABINDFile  *poINDFile;
      82                 : 
      83                 :     int         nIndexCount;
      84                 :     OGRMIAttrIndex **papoIndexList;
      85                 : 
      86                 :     char        *pszMetadataFilename;
      87                 :     char        *pszMIINDFilename;
      88                 : 
      89                 :     int         bINDAsReadOnly;
      90                 :     int         bUnlinkINDFile;
      91                 : 
      92                 :                 OGRMILayerAttrIndex();
      93                 :     virtual     ~OGRMILayerAttrIndex();
      94                 : 
      95                 :     /* base class virtual methods */
      96                 :     OGRErr      Initialize( const char *pszIndexPath, OGRLayer * );
      97                 :     OGRErr      CreateIndex( int iField );
      98                 :     OGRErr      DropIndex( int iField );
      99                 :     OGRErr      IndexAllFeatures( int iField = -1 );
     100                 : 
     101                 :     OGRErr      AddToIndex( OGRFeature *poFeature, int iField = -1 );
     102                 :     OGRErr      RemoveFromIndex( OGRFeature *poFeature );
     103                 : 
     104                 :     OGRAttrIndex *GetFieldIndex( int iField );
     105                 : 
     106                 :     /* custom to OGRMILayerAttrIndex */
     107                 :     OGRErr      SaveConfigToXML();
     108                 :     OGRErr      LoadConfigFromXML();
     109                 :     void        AddAttrInd( int iField, int iINDIndex );
     110                 : 
     111              12 :     OGRLayer   *GetLayer() { return poLayer; }
     112                 : };
     113                 : 
     114                 : /************************************************************************/
     115                 : /*                        OGRMILayerAttrIndex()                         */
     116                 : /************************************************************************/
     117                 : 
     118            1023 : OGRMILayerAttrIndex::OGRMILayerAttrIndex()
     119                 : 
     120                 : {
     121            1023 :     poINDFile = NULL;
     122            1023 :     nIndexCount = 0;
     123            1023 :     papoIndexList = NULL;
     124            1023 :     bUnlinkINDFile = FALSE;
     125            1023 :     bINDAsReadOnly = TRUE;
     126            1023 : }
     127                 : 
     128                 : /************************************************************************/
     129                 : /*                        ~OGRMILayerAttrIndex()                        */
     130                 : /************************************************************************/
     131                 : 
     132            1023 : OGRMILayerAttrIndex::~OGRMILayerAttrIndex()
     133                 : 
     134                 : {
     135            1023 :     if( poINDFile != NULL )
     136                 :     {
     137               9 :         poINDFile->Close();
     138               9 :         delete poINDFile;
     139               9 :         poINDFile = NULL;
     140                 :     }
     141                 : 
     142            1023 :     if (bUnlinkINDFile)
     143               1 :         VSIUnlink( pszMIINDFilename );
     144                 : 
     145            1033 :     for( int i = 0; i < nIndexCount; i++ )
     146              10 :         delete papoIndexList[i];
     147            1023 :     CPLFree( papoIndexList );
     148                 : 
     149            1023 :     CPLFree( pszMIINDFilename );
     150            1023 :     CPLFree( pszMetadataFilename );
     151            1023 : }
     152                 : 
     153                 : /************************************************************************/
     154                 : /*                             Initialize()                             */
     155                 : /************************************************************************/
     156                 : 
     157                 : OGRErr OGRMILayerAttrIndex::Initialize( const char *pszIndexPathIn, 
     158            1023 :                                         OGRLayer *poLayerIn )
     159                 : 
     160                 : {
     161            1023 :     if( poLayerIn == poLayer )
     162               0 :         return OGRERR_NONE;
     163                 : 
     164                 : /* -------------------------------------------------------------------- */
     165                 : /*      Capture input information and form static pathnames.            */
     166                 : /* -------------------------------------------------------------------- */
     167            1023 :     poLayer = poLayerIn;
     168                 : 
     169            1023 :     pszIndexPath = CPLStrdup( pszIndexPathIn );
     170                 :     
     171                 :     pszMetadataFilename = CPLStrdup(
     172            1023 :         CPLResetExtension( pszIndexPathIn, "idm" ) );
     173                 :     
     174            1023 :     pszMIINDFilename = CPLStrdup(CPLResetExtension( pszIndexPathIn, "ind" ));
     175                 : 
     176                 : /* -------------------------------------------------------------------- */
     177                 : /*      If a metadata file already exists, load it.                     */
     178                 : /* -------------------------------------------------------------------- */
     179                 :     OGRErr eErr;
     180                 :     VSIStatBuf sStat;
     181                 : 
     182            1023 :     if( VSIStat( pszMetadataFilename, &sStat ) == 0 )
     183                 :     {
     184               7 :         eErr = LoadConfigFromXML();
     185               7 :         if( eErr != OGRERR_NONE )
     186               0 :             return eErr;
     187                 :     }
     188                 : 
     189            1023 :     return OGRERR_NONE;
     190                 : }
     191                 : 
     192                 : /************************************************************************/
     193                 : /*                         LoadConfigFromXML()                          */
     194                 : /************************************************************************/
     195                 : 
     196               7 : OGRErr OGRMILayerAttrIndex::LoadConfigFromXML()
     197                 : 
     198                 : {
     199                 :     FILE *fp;
     200                 :     int  nXMLSize;
     201                 :     char *pszRawXML;
     202                 : 
     203               7 :     CPLAssert( poINDFile == NULL );
     204                 : 
     205                 : /* -------------------------------------------------------------------- */
     206                 : /*      Read the XML file.                                              */
     207                 : /* -------------------------------------------------------------------- */
     208               7 :     fp = VSIFOpen( pszMetadataFilename, "rb" );
     209               7 :     if( fp == NULL )
     210               0 :         return OGRERR_NONE;
     211                 : 
     212               7 :     VSIFSeek( fp, 0, SEEK_END );
     213               7 :     nXMLSize = VSIFTell( fp );
     214               7 :     VSIFSeek( fp, 0, SEEK_SET );
     215                 : 
     216               7 :     pszRawXML = (char *) CPLMalloc(nXMLSize+1);
     217               7 :     pszRawXML[nXMLSize] = '\0';
     218               7 :     VSIFRead( pszRawXML, nXMLSize, 1, fp );
     219                 : 
     220               7 :     VSIFClose( fp );
     221                 : 
     222                 : /* -------------------------------------------------------------------- */
     223                 : /*      Parse the XML.                                                  */
     224                 : /* -------------------------------------------------------------------- */
     225               7 :     CPLXMLNode *psRoot = CPLParseXMLString( pszRawXML );
     226               7 :     CPLFree( pszRawXML );
     227                 : 
     228               7 :     if( psRoot == NULL )
     229               0 :         return OGRERR_FAILURE;
     230                 : 
     231                 : /* -------------------------------------------------------------------- */
     232                 : /*      Open the index file.                                            */
     233                 : /* -------------------------------------------------------------------- */
     234               7 :     poINDFile = new TABINDFile();
     235                 : 
     236                 :     /* NOTE: Replaced r+ with r according to explanation in Ticket #1620.
     237                 :      * This change has to be observed if it doesn't cause any
     238                 :      * problems in future. (mloskot)
     239                 :      */
     240               7 :     if( poINDFile->Open( pszMetadataFilename, "r" ) != 0 )
     241                 :     {
     242               0 :         CPLDestroyXMLNode( psRoot );
     243                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     244                 :                   "Failed to open index file %s.", 
     245               0 :                   pszMIINDFilename );
     246               0 :         return OGRERR_FAILURE;
     247                 :     }
     248                 : 
     249                 : /* -------------------------------------------------------------------- */
     250                 : /*      Process each attrindex.                                         */
     251                 : /* -------------------------------------------------------------------- */
     252                 :     CPLXMLNode *psAttrIndex;
     253                 : 
     254              22 :     for( psAttrIndex = psRoot->psChild; 
     255                 :          psAttrIndex != NULL; 
     256                 :          psAttrIndex = psAttrIndex->psNext )
     257                 :     {
     258                 :         int iField, iIndexIndex;
     259                 : 
     260              15 :         if( psAttrIndex->eType != CXT_Element 
     261                 :             || !EQUAL(psAttrIndex->pszValue,"OGRMIAttrIndex") )
     262               7 :             continue;
     263                 : 
     264               8 :         iField = atoi(CPLGetXMLValue(psAttrIndex,"FieldIndex","-1"));
     265               8 :         iIndexIndex = atoi(CPLGetXMLValue(psAttrIndex,"IndexIndex","-1"));
     266                 : 
     267               8 :         if( iField == -1 || iIndexIndex == -1 )
     268                 :         {
     269                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     270               0 :                       "Skipping corrupt OGRMIAttrIndex entry." );
     271               0 :             continue;
     272                 :         }
     273                 : 
     274               8 :         AddAttrInd( iField, iIndexIndex );
     275                 :     }
     276                 : 
     277               7 :     CPLDestroyXMLNode( psRoot );
     278                 : 
     279                 :     CPLDebug( "OGR", "Restored %d field indexes for layer %s from %s on %s.",
     280                 :               nIndexCount, poLayer->GetLayerDefn()->GetName(), 
     281               7 :               pszMetadataFilename, pszMIINDFilename );
     282                 : 
     283               7 :     return OGRERR_NONE;
     284                 : }
     285                 : 
     286                 : /************************************************************************/
     287                 : /*                          SaveConfigToXML()                           */
     288                 : /************************************************************************/
     289                 : 
     290               5 : OGRErr OGRMILayerAttrIndex::SaveConfigToXML()
     291                 : 
     292                 : {
     293               5 :     if( nIndexCount == 0 )
     294               0 :         return OGRERR_NONE;
     295                 : 
     296                 : /* -------------------------------------------------------------------- */
     297                 : /*      Create the XML tree corresponding to this layer.                */
     298                 : /* -------------------------------------------------------------------- */
     299                 :     CPLXMLNode *psRoot;
     300                 : 
     301               5 :     psRoot = CPLCreateXMLNode( NULL, CXT_Element, "OGRMILayerAttrIndex" );
     302                 : 
     303                 :     CPLCreateXMLElementAndValue( psRoot, "MIIDFilename", 
     304               5 :                                  CPLGetFilename( pszMIINDFilename ) );
     305                 :     
     306              12 :     for( int i = 0; i < nIndexCount; i++ )
     307                 :     {
     308               7 :         OGRMIAttrIndex *poAI = papoIndexList[i];
     309                 :         CPLXMLNode *psIndex;
     310                 : 
     311               7 :         psIndex = CPLCreateXMLNode( psRoot, CXT_Element, "OGRMIAttrIndex" );
     312                 : 
     313                 :         CPLCreateXMLElementAndValue( psIndex, "FieldIndex", 
     314               7 :                                      CPLSPrintf( "%d", poAI->iField ) );
     315                 :                                      
     316                 :         CPLCreateXMLElementAndValue( psIndex, "FieldName", 
     317               7 :                                      poLayer->GetLayerDefn()->GetFieldDefn(poAI->iField)->GetNameRef() );
     318                 : 
     319                 :                                      
     320                 :         CPLCreateXMLElementAndValue( psIndex, "IndexIndex", 
     321               7 :                                      CPLSPrintf( "%d", poAI->iIndex ) );
     322                 :     }
     323                 : 
     324                 : /* -------------------------------------------------------------------- */
     325                 : /*      Save it.                                                        */
     326                 : /* -------------------------------------------------------------------- */
     327               5 :     char *pszRawXML = CPLSerializeXMLTree( psRoot );
     328                 :     FILE *fp;
     329                 : 
     330               5 :     CPLDestroyXMLNode( psRoot );
     331                 : 
     332               5 :     fp = VSIFOpen( pszMetadataFilename, "wb" );
     333               5 :     if( fp == NULL )
     334                 :     {
     335                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     336                 :                   "Failed to pen `%s' for write.", 
     337               0 :                   pszMetadataFilename );
     338               0 :         CPLFree( pszRawXML );
     339               0 :         return OGRERR_FAILURE;
     340                 :     }
     341                 : 
     342               5 :     VSIFWrite( pszRawXML, 1, strlen(pszRawXML), fp );
     343               5 :     VSIFClose( fp );
     344                 : 
     345               5 :     CPLFree( pszRawXML );
     346                 :     
     347               5 :     return OGRERR_NONE;
     348                 : }
     349                 : 
     350                 : /************************************************************************/
     351                 : /*                          IndexAllFeatures()                          */
     352                 : /************************************************************************/
     353                 : 
     354               4 : OGRErr OGRMILayerAttrIndex::IndexAllFeatures( int iField )
     355                 : 
     356                 : {
     357                 :     OGRFeature *poFeature;
     358                 : 
     359               4 :     poLayer->ResetReading();
     360                 :     
     361               4 :     while( (poFeature = poLayer->GetNextFeature()) != NULL )
     362                 :     {
     363              80 :         OGRErr eErr = AddToIndex( poFeature, iField );
     364                 :         
     365              80 :         delete poFeature;
     366                 : 
     367              80 :         if( eErr != CE_None )
     368               0 :             return eErr;
     369                 :     }
     370                 : 
     371               4 :     poLayer->ResetReading();
     372                 : 
     373               4 :     return OGRERR_NONE;
     374                 : }
     375                 : 
     376                 : /************************************************************************/
     377                 : /*                            CreateIndex()                             */
     378                 : /*                                                                      */
     379                 : /*      Create an index corresponding to the indicated field, but do    */
     380                 : /*      not populate it.  Use IndexAllFeatures() for that.              */
     381                 : /************************************************************************/
     382                 : 
     383               4 : OGRErr OGRMILayerAttrIndex::CreateIndex( int iField )
     384                 : 
     385                 : {
     386                 : /* -------------------------------------------------------------------- */
     387                 : /*      Do we have an open .ID file yet?  If not, create it now.        */
     388                 : /* -------------------------------------------------------------------- */
     389               4 :     if( poINDFile == NULL )
     390                 :     {
     391               2 :         poINDFile = new TABINDFile();
     392               2 :         if( poINDFile->Open( pszMIINDFilename, "w+" ) != 0 )
     393                 :         {
     394               0 :             delete poINDFile;
     395               0 :             poINDFile = NULL;
     396                 :             
     397                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     398                 :                       "Failed to create %s.",
     399               0 :                       pszMIINDFilename );
     400               0 :             return OGRERR_FAILURE;
     401                 :         }
     402                 :     }
     403               2 :     else if (bINDAsReadOnly)
     404                 :     {
     405               2 :         poINDFile->Close();
     406               2 :         if( poINDFile->Open( pszMIINDFilename, "r+" ) != 0 )
     407                 :         {
     408                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     409                 :                       "Failed to open %s as write-only.",
     410               0 :                       pszMIINDFilename );
     411                 : 
     412               0 :             if( poINDFile->Open( pszMIINDFilename, "r" ) != 0 )
     413                 :             {
     414                 :                 CPLError( CE_Failure, CPLE_OpenFailed, 
     415                 :                       "Cannot re-open %s as read-only.",
     416               0 :                       pszMIINDFilename );
     417               0 :                 delete poINDFile;
     418               0 :                 poINDFile = NULL;
     419                 :             }
     420                 : 
     421               0 :             return OGRERR_FAILURE;
     422                 :         }
     423                 :         else
     424                 :         {
     425               2 :             bINDAsReadOnly = FALSE;
     426                 :         }
     427                 :     }
     428                 : 
     429                 : /* -------------------------------------------------------------------- */
     430                 : /*      Do we have this field indexed already?                          */
     431                 : /* -------------------------------------------------------------------- */
     432                 :     int i;
     433               4 :     OGRFieldDefn *poFldDefn=poLayer->GetLayerDefn()->GetFieldDefn(iField);
     434                 : 
     435               6 :     for( i = 0; i < nIndexCount; i++ )
     436                 :     {
     437               2 :         if( papoIndexList[i]->iField == iField )
     438                 :         {
     439                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     440                 :                       "It seems we already have an index for field %d/%s\n"
     441                 :                       "of layer %s.", 
     442                 :                       iField, poFldDefn->GetNameRef(),
     443               0 :                       poLayer->GetLayerDefn()->GetName() );
     444               0 :             return OGRERR_FAILURE;
     445                 :         }
     446                 :     }
     447                 : 
     448                 : /* -------------------------------------------------------------------- */
     449                 : /*      What is the corresponding field type in TAB?  Note that we      */
     450                 : /*      don't allow indexing of any of the list types.                  */
     451                 : /* -------------------------------------------------------------------- */
     452                 :     TABFieldType eTABFT;
     453               4 :     int           nFieldWidth = 0;
     454                 : 
     455               4 :     switch( poFldDefn->GetType() )
     456                 :     {
     457                 :       case OFTInteger:
     458               0 :         eTABFT = TABFInteger;
     459               0 :         break;
     460                 : 
     461                 :       case OFTReal:
     462               2 :         eTABFT = TABFFloat;
     463               2 :         break;
     464                 : 
     465                 :       case OFTString:
     466               2 :         eTABFT = TABFChar;
     467               2 :         if( poFldDefn->GetWidth() > 0 )
     468               2 :             nFieldWidth = poFldDefn->GetWidth();
     469                 :         else
     470               0 :             nFieldWidth = 64;
     471               2 :         break;
     472                 : 
     473                 :       default:
     474                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     475                 :                   "Indexing not support for the field type of field %s.",
     476               0 :                   poFldDefn->GetNameRef() );
     477               0 :         return OGRERR_FAILURE;
     478                 :     }
     479                 : 
     480                 : /* -------------------------------------------------------------------- */
     481                 : /*      Create the index.                                               */
     482                 : /* -------------------------------------------------------------------- */
     483                 :     int iINDIndex;
     484                 : 
     485               4 :     iINDIndex = poINDFile->CreateIndex( eTABFT, nFieldWidth );
     486                 : 
     487                 :     // CreateIndex() reports it's own errors.
     488               4 :     if( iINDIndex < 0 )
     489               0 :         return OGRERR_FAILURE;
     490                 : 
     491               4 :     AddAttrInd( iField, iINDIndex );
     492                 : 
     493               4 :     bUnlinkINDFile = FALSE;
     494                 : 
     495                 : /* -------------------------------------------------------------------- */
     496                 : /*      Save the new configuration.                                     */
     497                 : /* -------------------------------------------------------------------- */
     498               4 :     return SaveConfigToXML();
     499                 : }
     500                 : 
     501                 : /************************************************************************/
     502                 : /*                             DropIndex()                              */
     503                 : /*                                                                      */
     504                 : /*      For now we don't have any capability to remove index data       */
     505                 : /*      from the MapInfo index file, so we just limit ourselves to      */
     506                 : /*      ignoring it from now on.                                        */
     507                 : /************************************************************************/
     508                 : 
     509               2 : OGRErr OGRMILayerAttrIndex::DropIndex( int iField )
     510                 : 
     511                 : {
     512                 : /* -------------------------------------------------------------------- */
     513                 : /*      Do we have this field indexed already?                          */
     514                 : /* -------------------------------------------------------------------- */
     515                 :     int i;
     516               2 :     OGRFieldDefn *poFldDefn=poLayer->GetLayerDefn()->GetFieldDefn(iField);
     517                 : 
     518               2 :     for( i = 0; i < nIndexCount; i++ )
     519                 :     {
     520               2 :         if( papoIndexList[i]->iField == iField )
     521               2 :             break;
     522                 : 
     523                 :     }
     524                 : 
     525               2 :     if( i == nIndexCount )
     526                 :     {
     527                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     528                 :                   "DROP INDEX on field (%s) that doesn't have an index.",
     529               0 :                   poFldDefn->GetNameRef() );
     530               0 :         return OGRERR_FAILURE;
     531                 :     }
     532                 : 
     533                 : /* -------------------------------------------------------------------- */
     534                 : /*      Remove from the list.                                           */
     535                 : /* -------------------------------------------------------------------- */
     536               2 :     OGRMIAttrIndex *poAI = papoIndexList[i];
     537                 : 
     538                 :     memmove( papoIndexList + i, papoIndexList + i + 1, 
     539               2 :              sizeof(void*) * (nIndexCount - i - 1) );
     540                 : 
     541               2 :     delete poAI;
     542                 : 
     543               2 :     nIndexCount--;
     544                 :              
     545                 : /* -------------------------------------------------------------------- */
     546                 : /*      Save the new configuration, or if there is nothing left try     */
     547                 : /*      to clean up the index files.                                    */
     548                 : /* -------------------------------------------------------------------- */
     549                 : 
     550               2 :     if( nIndexCount > 0 )
     551               1 :         return SaveConfigToXML();
     552                 :     else
     553                 :     {
     554               1 :         bUnlinkINDFile = TRUE;
     555               1 :         VSIUnlink( pszMetadataFilename );
     556                 : 
     557               1 :         return OGRERR_NONE;
     558                 :     }
     559                 : }
     560                 : 
     561                 : /************************************************************************/
     562                 : /*                             AddAttrInd()                             */
     563                 : /************************************************************************/
     564                 : 
     565              12 : void OGRMILayerAttrIndex::AddAttrInd( int iField, int iINDIndex )
     566                 : 
     567                 : {
     568              12 :     OGRMIAttrIndex *poAttrInd = new OGRMIAttrIndex( this, iINDIndex, iField);
     569                 : 
     570              12 :     nIndexCount++;
     571                 :     papoIndexList = (OGRMIAttrIndex **) 
     572              12 :         CPLRealloc(papoIndexList, sizeof(void*) * nIndexCount);
     573                 :     
     574              12 :     papoIndexList[nIndexCount-1] = poAttrInd;
     575              12 : }
     576                 : 
     577                 : /************************************************************************/
     578                 : /*                         GetFieldAttrIndex()                          */
     579                 : /************************************************************************/
     580                 : 
     581              84 : OGRAttrIndex *OGRMILayerAttrIndex::GetFieldIndex( int iField )
     582                 : 
     583                 : {
     584              91 :     for( int i = 0; i < nIndexCount; i++ )
     585                 :     {
     586              17 :         if( papoIndexList[i]->iField == iField )
     587              10 :             return papoIndexList[i];
     588                 :     }
     589                 : 
     590              74 :     return NULL;
     591                 : }
     592                 : 
     593                 : /************************************************************************/
     594                 : /*                             AddToIndex()                             */
     595                 : /************************************************************************/
     596                 : 
     597                 : OGRErr OGRMILayerAttrIndex::AddToIndex( OGRFeature *poFeature,
     598              80 :                                         int iTargetField )
     599                 : 
     600                 : {
     601              80 :     OGRErr eErr = OGRERR_NONE;
     602                 : 
     603              80 :     if( poFeature->GetFID() == OGRNullFID )
     604                 :     {
     605                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     606               0 :                   "Attempt to index feature with no FID." );
     607               0 :         return OGRERR_FAILURE;
     608                 :     }
     609                 : 
     610             200 :     for( int i = 0; i < nIndexCount && eErr == OGRERR_NONE; i++ )
     611                 :     {
     612             120 :         int iField = papoIndexList[i]->iField;
     613                 : 
     614             120 :         if( iTargetField != -1 && iTargetField != iField )
     615              40 :             continue;
     616                 : 
     617              80 :         if( !poFeature->IsFieldSet( iField ) )
     618               0 :             continue;
     619                 : 
     620                 :         eErr = 
     621                 :             papoIndexList[i]->AddEntry( poFeature->GetRawFieldRef( iField ),
     622              80 :                                         poFeature->GetFID() );
     623                 :     }
     624                 : 
     625              80 :     return eErr;
     626                 : }
     627                 : 
     628                 : /************************************************************************/
     629                 : /*                          RemoveFromIndex()                           */
     630                 : /************************************************************************/
     631                 : 
     632               0 : OGRErr OGRMILayerAttrIndex::RemoveFromIndex( OGRFeature * /*poFeature*/ )
     633                 : 
     634                 : {
     635               0 :     return OGRERR_UNSUPPORTED_OPERATION;
     636                 : }
     637                 : 
     638                 : /************************************************************************/
     639                 : /*                     OGRCreateDefaultLayerIndex()                     */
     640                 : /************************************************************************/
     641                 : 
     642            1023 : OGRLayerAttrIndex *OGRCreateDefaultLayerIndex()
     643                 : 
     644                 : {
     645            1023 :     return new OGRMILayerAttrIndex();
     646                 : }
     647                 : 
     648                 : /************************************************************************/
     649                 : /* ==================================================================== */
     650                 : /*                            OGRMIAttrIndex                            */
     651                 : /* ==================================================================== */
     652                 : /************************************************************************/
     653                 : 
     654                 : /* class declared at top of file */
     655                 : 
     656                 : /************************************************************************/
     657                 : /*                           OGRMIAttrIndex()                           */
     658                 : /************************************************************************/
     659                 : 
     660                 : OGRMIAttrIndex::OGRMIAttrIndex( OGRMILayerAttrIndex *poLayerIndex, 
     661              12 :                                 int iIndexIn, int iFieldIn )
     662                 : 
     663                 : {
     664              12 :     iIndex = iIndexIn;
     665              12 :     iField = iFieldIn;
     666              12 :     poLIndex = poLayerIndex;
     667              12 :     poINDFile = poLayerIndex->poINDFile;
     668                 : 
     669              12 :     poFldDefn = poLayerIndex->GetLayer()->GetLayerDefn()->GetFieldDefn(iField);
     670              12 : }
     671                 : 
     672                 : /************************************************************************/
     673                 : /*                          ~OGRMIAttrIndex()                           */
     674                 : /************************************************************************/
     675                 : 
     676              12 : OGRMIAttrIndex::~OGRMIAttrIndex()
     677                 : {
     678              12 : }
     679                 : 
     680                 : /************************************************************************/
     681                 : /*                              AddEntry()                              */
     682                 : /************************************************************************/
     683                 : 
     684              80 : OGRErr OGRMIAttrIndex::AddEntry( OGRField *psKey, long nFID )
     685                 : 
     686                 : {
     687              80 :     GByte *pabyKey = BuildKey( psKey );
     688                 : 
     689              80 :     if( psKey == NULL )
     690               0 :         return OGRERR_FAILURE;
     691                 : 
     692              80 :     if( poINDFile->AddEntry( iIndex, pabyKey, nFID+1 ) != 0 )
     693               0 :         return OGRERR_FAILURE;
     694                 :     else
     695              80 :         return OGRERR_NONE;
     696                 : }
     697                 : 
     698                 : /************************************************************************/
     699                 : /*                            RemoveEntry()                             */
     700                 : /************************************************************************/
     701                 : 
     702               0 : OGRErr OGRMIAttrIndex::RemoveEntry( OGRField * /*psKey*/, long /*nFID*/ )
     703                 : 
     704                 : {
     705               0 :     return OGRERR_UNSUPPORTED_OPERATION;
     706                 : }
     707                 : 
     708                 : /************************************************************************/
     709                 : /*                              BuildKey()                              */
     710                 : /************************************************************************/
     711                 : 
     712              90 : GByte *OGRMIAttrIndex::BuildKey( OGRField *psKey )
     713                 : 
     714                 : {
     715              90 :     switch( poFldDefn->GetType() )
     716                 :     {
     717                 :       case OFTInteger:
     718               2 :         return poINDFile->BuildKey( iIndex, psKey->Integer );
     719                 :         break;
     720                 : 
     721                 :       case OFTReal:
     722              47 :         return poINDFile->BuildKey( iIndex, psKey->Real );
     723                 :         break;
     724                 : 
     725                 :       case OFTString:
     726              41 :         return poINDFile->BuildKey( iIndex, psKey->String );
     727                 :         break;
     728                 : 
     729                 :       default:
     730               0 :         CPLAssert( FALSE );
     731                 : 
     732               0 :         return NULL;
     733                 :     }
     734                 : }
     735                 : 
     736                 : /************************************************************************/
     737                 : /*                           GetFirstMatch()                            */
     738                 : /************************************************************************/
     739                 : 
     740               0 : long OGRMIAttrIndex::GetFirstMatch( OGRField *psKey )
     741                 : 
     742                 : {
     743               0 :     GByte *pabyKey = BuildKey( psKey );
     744                 :     long nFID;
     745                 : 
     746               0 :     nFID = poINDFile->FindFirst( iIndex, pabyKey );
     747               0 :     if( nFID < 1 )
     748               0 :         return OGRNullFID;
     749                 :     else
     750               0 :         return nFID - 1;
     751                 : }
     752                 : 
     753                 : /************************************************************************/
     754                 : /*                           GetAllMatches()                            */
     755                 : /************************************************************************/
     756                 : 
     757              10 : long *OGRMIAttrIndex::GetAllMatches( OGRField *psKey )
     758                 : 
     759                 : {
     760              10 :     GByte *pabyKey = BuildKey( psKey );
     761              10 :     long  *panFIDList = NULL, nFID;
     762              10 :     int   nFIDCount=0, nFIDMax=2;
     763                 : 
     764              10 :     panFIDList = (long *) CPLMalloc(sizeof(long) * 2);
     765                 : 
     766              10 :     nFID = poINDFile->FindFirst( iIndex, pabyKey );
     767              30 :     while( nFID > 0 )
     768                 :     {
     769              10 :         if( nFIDCount >= nFIDMax-1 )
     770                 :         {
     771               0 :             nFIDMax = nFIDMax * 2 + 10;
     772               0 :             panFIDList = (long *) CPLRealloc(panFIDList, sizeof(long)*nFIDMax);
     773                 :         }
     774              10 :         panFIDList[nFIDCount++] = nFID - 1;
     775                 :         
     776              10 :         nFID = poINDFile->FindNext( iIndex, pabyKey );
     777                 :     }
     778                 : 
     779              10 :     panFIDList[nFIDCount] = OGRNullFID;
     780                 :     
     781              10 :     return panFIDList;
     782                 : }
     783                 : 
     784                 : /************************************************************************/
     785                 : /*                               Clear()                                */
     786                 : /************************************************************************/
     787                 : 
     788               0 : OGRErr OGRMIAttrIndex::Clear()
     789                 : 
     790                 : {
     791               0 :     return OGRERR_UNSUPPORTED_OPERATION;
     792                 : }

Generated by: LTP GCOV extension version 1.5