LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/generic - ogr_miattrind.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 217 169 77.9 %
Date: 2010-01-09 Functions: 24 20 83.3 %

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

Generated by: LCOV version 1.7