LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/s57 - ddfrecordindex.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 102 79 77.5 %
Date: 2012-04-28 Functions: 14 11 78.6 %

       1                 : /******************************************************************************
       2                 :  * $Id: ddfrecordindex.cpp 10645 2007-01-18 02:22:39Z warmerdam $
       3                 :  *
       4                 :  * Project:  S-57 Translator
       5                 :  * Purpose:  Implements DDFRecordIndex class.  This class is used to cache
       6                 :  *           ISO8211 records for spatial objects so they can be efficiently
       7                 :  *           assembled later as features.
       8                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       9                 :  *
      10                 :  ******************************************************************************
      11                 :  * Copyright (c) 1999, 2001, Frank Warmerdam
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "s57.h"
      33                 : #include "cpl_conv.h"
      34                 : 
      35                 : CPL_CVSID("$Id: ddfrecordindex.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                           DDFRecordIndex()                           */
      39                 : /************************************************************************/
      40                 : 
      41              60 : DDFRecordIndex::DDFRecordIndex()
      42                 : 
      43                 : {
      44              60 :     bSorted = FALSE;
      45                 : 
      46              60 :     nRecordCount = 0;
      47              60 :     nRecordMax = 0;
      48              60 :     pasRecords = NULL;
      49                 : 
      50              60 :     nLastObjlPos = 0;             /* rjensen. added for FindRecordByObjl() */
      51              60 :     nLastObjl    = 0;             /* rjensen. added for FindRecordByObjl() */
      52              60 : }
      53                 : 
      54                 : /************************************************************************/
      55                 : /*                          ~DDFRecordIndex()                           */
      56                 : /************************************************************************/
      57                 : 
      58              60 : DDFRecordIndex::~DDFRecordIndex()
      59                 : 
      60                 : {
      61              60 :     Clear();
      62              60 : }
      63                 : 
      64                 : /************************************************************************/
      65                 : /*                               Clear()                                */
      66                 : /*                                                                      */
      67                 : /*      Clear all entries from the index and deallocate all index       */
      68                 : /*      resources.                                                      */
      69                 : /************************************************************************/
      70                 : 
      71             120 : void DDFRecordIndex::Clear()
      72                 : 
      73                 : {
      74                 :     // It turns out that deleting these records here is very expensive
      75                 :     // due to the linear search in DDFModule::RemoveClone().  For now we
      76                 :     // just leave the clones depending on DDFModule::~DDFModule() to clean
      77                 :     // them up eventually.
      78                 : 
      79                 :     //for( int i = 0; i < nRecordCount; i++ )
      80                 :     //  delete pasRecords[i].poRecord;
      81                 : 
      82             120 :     CPLFree( pasRecords );
      83             120 :     pasRecords = NULL;
      84                 : 
      85             120 :     nRecordCount = 0;
      86             120 :     nRecordMax = 0;
      87                 : 
      88             120 :     nLastObjlPos = 0;             /* rjensen. added for FindRecordByObjl() */
      89             120 :     nLastObjl      = 0;             /* rjensen. added for FindRecordByObjl() */
      90                 : 
      91             120 :     bSorted = FALSE;
      92             120 : }
      93                 : 
      94                 : /************************************************************************/
      95                 : /*                             AddRecord()                              */
      96                 : /*                                                                      */
      97                 : /*      Add a record to the index.  The index will assume ownership     */
      98                 : /*      of the record.  If passing a record just read from a            */
      99                 : /*      DDFModule it is imperitive that the caller Clone()'s the        */
     100                 : /*      record first.                                                   */
     101                 : /************************************************************************/
     102                 : 
     103           47170 : void DDFRecordIndex::AddRecord( int nKey, DDFRecord * poRecord )
     104                 : 
     105                 : {
     106           47170 :     if( nRecordCount == nRecordMax )
     107                 :     {
     108             174 :         nRecordMax = (int) (nRecordCount * 1.3 + 100);
     109                 :         pasRecords = (DDFIndexedRecord *)
     110             174 :             CPLRealloc( pasRecords, sizeof(DDFIndexedRecord)*nRecordMax );
     111                 :     }
     112                 : 
     113           47170 :     bSorted = FALSE;
     114                 : 
     115           47170 :     pasRecords[nRecordCount].nKey = nKey;
     116           47170 :     pasRecords[nRecordCount].poRecord = poRecord;
     117           47170 :     pasRecords[nRecordCount].pClientData = NULL;
     118                 : 
     119           47170 :     nRecordCount++;
     120           47170 : }
     121                 : 
     122                 : /************************************************************************/
     123                 : /*                             FindRecord()                             */
     124                 : /*                                                                      */
     125                 : /*      Though the returned pointer is not const, it should be          */
     126                 : /*      considered internal to the index and not modified or freed      */
     127                 : /*      by application code.                                            */
     128                 : /************************************************************************/
     129                 : 
     130             202 : DDFRecord * DDFRecordIndex::FindRecord( int nKey )
     131                 : 
     132                 : {
     133             202 :     if( !bSorted )
     134              26 :         Sort();
     135                 : 
     136                 : /* -------------------------------------------------------------------- */
     137                 : /*      Do a binary search based on the key to find the desired record. */
     138                 : /* -------------------------------------------------------------------- */
     139             202 :     int         nMinIndex = 0, nMaxIndex = nRecordCount-1;
     140                 : 
     141            1276 :     while( nMinIndex <= nMaxIndex )
     142                 :     {
     143            1074 :         int     nTestIndex = (nMaxIndex + nMinIndex) / 2;
     144                 : 
     145            1074 :         if( pasRecords[nTestIndex].nKey < nKey )
     146             468 :             nMinIndex = nTestIndex + 1;
     147             606 :         else if( pasRecords[nTestIndex].nKey > nKey )
     148             404 :             nMaxIndex = nTestIndex - 1;
     149                 :         else
     150             202 :             return pasRecords[nTestIndex].poRecord;
     151                 :     }
     152                 : 
     153               0 :     return NULL;
     154                 : }
     155                 : 
     156                 : /************************************************************************/
     157                 : /*                       FindRecordByObjl()                             */
     158                 : /*      Rodney Jensen                                                   */
     159                 : /*      Though the returned pointer is not const, it should be          */
     160                 : /*      considered internal to the index and not modified or freed      */
     161                 : /*      by application code.                                            */
     162                 : /************************************************************************/
     163                 : 
     164               0 : DDFRecord * DDFRecordIndex::FindRecordByObjl( int nObjl )
     165                 : {
     166               0 :     if( !bSorted )
     167               0 :         Sort();
     168                 : 
     169                 : /* -------------------------------------------------------------------- */
     170                 : /*      Do a linear search based on the nObjl to find the desired record. */
     171                 : /* -------------------------------------------------------------------- */
     172               0 :     int nMinIndex = 0;
     173               0 :     if (nLastObjl != nObjl) nLastObjlPos=0;
     174                 : 
     175               0 :     for (nMinIndex = nLastObjlPos; nMinIndex < nRecordCount; nMinIndex++)
     176                 :     {
     177               0 :         if (nObjl == pasRecords[nMinIndex].poRecord->GetIntSubfield( "FRID", 0, "OBJL", 0 ) )
     178                 :         {
     179               0 :             nLastObjlPos=nMinIndex+1;  /* add 1, don't want to look at same again */
     180               0 :             nLastObjl=nObjl;
     181               0 :             return pasRecords[nMinIndex].poRecord;
     182                 :         }
     183                 :     }
     184                 : 
     185               0 :     nLastObjlPos=0;
     186               0 :     nLastObjl=0;
     187                 : 
     188               0 :     return NULL;
     189                 : }
     190                 : 
     191                 : /************************************************************************/
     192                 : /*                            RemoveRecord()                            */
     193                 : /************************************************************************/
     194                 : 
     195              16 : int DDFRecordIndex::RemoveRecord( int nKey )
     196                 : 
     197                 : {
     198              16 :     if( !bSorted )
     199               0 :         Sort();
     200                 : 
     201                 : /* -------------------------------------------------------------------- */
     202                 : /*      Do a binary search based on the key to find the desired record. */
     203                 : /* -------------------------------------------------------------------- */
     204              16 :     int         nMinIndex = 0, nMaxIndex = nRecordCount-1;
     205              16 :     int         nTestIndex = 0;
     206                 : 
     207             116 :     while( nMinIndex <= nMaxIndex )
     208                 :     {
     209             100 :         nTestIndex = (nMaxIndex + nMinIndex) / 2;
     210                 : 
     211             100 :         if( pasRecords[nTestIndex].nKey < nKey )
     212              52 :             nMinIndex = nTestIndex + 1;
     213              48 :         else if( pasRecords[nTestIndex].nKey > nKey )
     214              32 :             nMaxIndex = nTestIndex - 1;
     215                 :         else
     216              16 :             break;
     217                 :     }
     218                 : 
     219              16 :     if( nMinIndex > nMaxIndex )
     220               0 :         return FALSE;
     221                 : 
     222                 : /* -------------------------------------------------------------------- */
     223                 : /*      Delete this record.                                             */
     224                 : /* -------------------------------------------------------------------- */
     225              16 :     delete pasRecords[nTestIndex].poRecord;
     226                 : 
     227                 : /* -------------------------------------------------------------------- */
     228                 : /*      Move all the list entries back one to fill the hole, and        */
     229                 : /*      update the total count.                                         */
     230                 : /* -------------------------------------------------------------------- */
     231                 :     memmove( pasRecords + nTestIndex,
     232                 :              pasRecords + nTestIndex + 1,
     233              16 :              (nRecordCount - nTestIndex - 1) * sizeof(DDFIndexedRecord) );
     234                 : 
     235              16 :     nRecordCount--;
     236                 : 
     237              16 :     return TRUE;
     238                 : }
     239                 : 
     240                 : /************************************************************************/
     241                 : /*                             DDFCompare()                             */
     242                 : /*                                                                      */
     243                 : /*      Compare two DDFIndexedRecord objects for qsort().               */
     244                 : /************************************************************************/
     245                 : 
     246          283326 : static int DDFCompare( const void *pRec1, const void *pRec2 )
     247                 : 
     248                 : {
     249          283326 :     if( ((const DDFIndexedRecord *) pRec1)->nKey
     250                 :         == ((const DDFIndexedRecord *) pRec2)->nKey )
     251               0 :         return 0;
     252          283326 :     else if( ((const DDFIndexedRecord *) pRec1)->nKey
     253                 :              < ((const DDFIndexedRecord *) pRec2)->nKey )
     254          230332 :         return -1;
     255                 :     else
     256           52994 :         return 1;
     257                 : }
     258                 : 
     259                 : /************************************************************************/
     260                 : /*                                Sort()                                */
     261                 : /*                                                                      */
     262                 : /*      Sort the records based on the key.  This is currently           */
     263                 : /*      implemented as a bubble sort, and could gain in efficiency      */
     264                 : /*      by reimplementing as a quick sort; however, I believe that      */
     265                 : /*      the keys will always be in order so a bubble sort should        */
     266                 : /*      only require one pass to verify this.                           */
     267                 : /************************************************************************/
     268                 : 
     269              38 : void DDFRecordIndex::Sort()
     270                 : 
     271                 : {
     272              38 :     if( bSorted )
     273               0 :         return;
     274                 : 
     275              38 :     qsort( pasRecords, nRecordCount, sizeof(DDFIndexedRecord), DDFCompare );
     276                 : 
     277              38 :     bSorted = TRUE;
     278                 : }
     279                 : 
     280                 : /************************************************************************/
     281                 : /*                             GetByIndex()                             */
     282                 : /************************************************************************/
     283                 : 
     284           16782 : DDFRecord * DDFRecordIndex::GetByIndex( int nIndex )
     285                 : 
     286                 : {
     287           16782 :     if( !bSorted )
     288              12 :         Sort();
     289                 : 
     290           16782 :     if( nIndex < 0 || nIndex >= nRecordCount )
     291               0 :         return NULL;
     292                 :     else
     293           16782 :         return pasRecords[nIndex].poRecord;
     294                 : }
     295                 : 
     296                 : /************************************************************************/
     297                 : /*                        GetClientInfoByIndex()                        */
     298                 : /************************************************************************/
     299                 : 
     300            2428 : void * DDFRecordIndex::GetClientInfoByIndex( int nIndex )
     301                 : 
     302                 : {
     303            2428 :     if( !bSorted )
     304               0 :         Sort();
     305                 : 
     306            2428 :     if( nIndex < 0 || nIndex >= nRecordCount )
     307               0 :         return NULL;
     308                 :     else
     309            2428 :         return pasRecords[nIndex].pClientData;
     310                 : }
     311                 : 
     312                 : /************************************************************************/
     313                 : /*                        SetClientInfoByIndex()                        */
     314                 : /************************************************************************/
     315                 : 
     316            2356 : void DDFRecordIndex::SetClientInfoByIndex( int nIndex, void *pClientData )
     317                 : 
     318                 : {
     319            2356 :     if( !bSorted )
     320               0 :         Sort();
     321                 : 
     322            2356 :     if( nIndex < 0 || nIndex >= nRecordCount )
     323               0 :         return;
     324                 :     else
     325            2356 :         pasRecords[nIndex].pClientData = pClientData;
     326                 : }
     327                 : 

Generated by: LCOV version 1.7