LCOV - code coverage report
Current view: top level - frmts/iso8211 - ddfrecordindex.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 60 68 88.2 %
Date: 2026-05-07 23:23:29 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  ISO 8211 Access
       4             :  * Purpose:  Implements DDFRecordIndex class.  This class is used to cache
       5             :  *           ISO8211 records for spatial objects so they can be efficiently
       6             :  *           assembled later as features.
       7             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8             :  *
       9             :  ******************************************************************************
      10             :  * Copyright (c) 1999, 2001, Frank Warmerdam
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #include "cpl_conv.h"
      16             : #include "ddfrecordindex.h"
      17             : 
      18             : #include <algorithm>
      19             : 
      20             : /************************************************************************/
      21             : /*                           DDFRecordIndex()                           */
      22             : /************************************************************************/
      23             : 
      24             : DDFRecordIndex::DDFRecordIndex() = default;
      25             : 
      26             : /************************************************************************/
      27             : /*                          ~DDFRecordIndex()                           */
      28             : /************************************************************************/
      29             : 
      30        2680 : DDFRecordIndex::~DDFRecordIndex()
      31             : 
      32             : {
      33        2680 :     Clear();
      34        2680 : }
      35             : 
      36             : /************************************************************************/
      37             : /*                               Clear()                                */
      38             : /*                                                                      */
      39             : /*      Clear all entries from the index and deallocate all index       */
      40             : /*      resources.                                                      */
      41             : /************************************************************************/
      42             : 
      43        2875 : void DDFRecordIndex::Clear()
      44             : 
      45             : {
      46        2875 :     bSorted = false;
      47        2875 :     asRecords.clear();
      48        2875 :     oMapKeyToRecord.clear();
      49        2875 : }
      50             : 
      51             : /************************************************************************/
      52             : /*                             AddRecord()                              */
      53             : /*                                                                      */
      54             : /*      Add a record to the index.  The index will assume ownership     */
      55             : /*      of the record.  If passing a record just read from a            */
      56             : /*      DDFModule it is imperative that the caller Clone()'s the        */
      57             : /*      record first.                                                   */
      58             : /************************************************************************/
      59             : 
      60       29095 : void DDFRecordIndex::AddRecord(int nKey, std::unique_ptr<DDFRecord> poRecord)
      61             : 
      62             : {
      63       29095 :     DDFIndexedRecord indexRec;
      64       29095 :     indexRec.nKey = nKey;
      65       29095 :     indexRec.poRecord = std::move(poRecord);
      66       29095 :     asRecords.push_back(std::move(indexRec));
      67       29095 :     oMapKeyToRecord[nKey] = asRecords.back().poRecord.get();
      68       29095 :     bSorted = false;
      69       29095 : }
      70             : 
      71             : /************************************************************************/
      72             : /*                             FindRecord()                             */
      73             : /*                                                                      */
      74             : /*      Though the returned pointer is not const, it should not         */
      75             : /*      be freed by application code.                                   */
      76             : /************************************************************************/
      77             : 
      78      124338 : DDFRecord *DDFRecordIndex::FindRecord(int nKey) const
      79             : 
      80             : {
      81      124338 :     auto oIter = oMapKeyToRecord.find(nKey);
      82      124338 :     if (oIter == oMapKeyToRecord.end())
      83        1552 :         return nullptr;
      84      122786 :     return oIter->second;
      85             : }
      86             : 
      87             : /************************************************************************/
      88             : /*                            RemoveRecord()                            */
      89             : /************************************************************************/
      90             : 
      91          18 : bool DDFRecordIndex::RemoveRecord(int nKey)
      92             : 
      93             : {
      94          18 :     if (!bSorted)
      95           8 :         Sort();
      96             : 
      97          18 :     if (asRecords.empty() || nKey < asRecords[0].nKey)
      98           0 :         return false;
      99             : 
     100             :     /* -------------------------------------------------------------------- */
     101             :     /*      Do a binary search based on the key to find the desired record. */
     102             :     /* -------------------------------------------------------------------- */
     103          18 :     size_t nMinIndex = 0;
     104          18 :     size_t nMaxIndex = asRecords.size() - 1;
     105          18 :     size_t nTestIndex = 0;
     106             : 
     107         145 :     while (nMinIndex <= nMaxIndex)
     108             :     {
     109         145 :         nTestIndex = (nMaxIndex + nMinIndex) / 2;
     110             : 
     111         145 :         if (asRecords[nTestIndex].nKey < nKey)
     112         110 :             nMinIndex = nTestIndex + 1;
     113          35 :         else if (asRecords[nTestIndex].nKey > nKey)
     114          17 :             nMaxIndex = nTestIndex - 1;
     115             :         else
     116          18 :             break;
     117             :     }
     118             : 
     119          18 :     if (nMinIndex > nMaxIndex)
     120           0 :         return false;
     121             : 
     122             :     /* -------------------------------------------------------------------- */
     123             :     /*      Delete this record.                                             */
     124             :     /* -------------------------------------------------------------------- */
     125          18 :     asRecords.erase(asRecords.begin() + nTestIndex);
     126             : 
     127          18 :     auto oIter = oMapKeyToRecord.find(nKey);
     128          18 :     CPLAssert(oIter != oMapKeyToRecord.end());
     129          18 :     oMapKeyToRecord.erase(oIter);
     130             : 
     131          18 :     return true;
     132             : }
     133             : 
     134             : /************************************************************************/
     135             : /*                                Sort()                                */
     136             : /*                                                                      */
     137             : /*      Sort the records based on the key.                              */
     138             : /************************************************************************/
     139             : 
     140         715 : void DDFRecordIndex::Sort() const
     141             : 
     142             : {
     143         715 :     if (bSorted)
     144           0 :         return;
     145             : 
     146         715 :     std::sort(asRecords.begin(), asRecords.end(),
     147      214231 :               [](const DDFIndexedRecord &a, const DDFIndexedRecord &b)
     148      214231 :               { return a.nKey < b.nKey; });
     149             : 
     150         715 :     bSorted = true;
     151             : }
     152             : 
     153             : /************************************************************************/
     154             : /*                             GetByIndex()                             */
     155             : /************************************************************************/
     156             : 
     157       34485 : const DDFRecord *DDFRecordIndex::GetByIndex(int nIndex) const
     158             : 
     159             : {
     160       34485 :     if (!bSorted)
     161         707 :         Sort();
     162             : 
     163       34485 :     if (nIndex < 0 || nIndex >= GetCount())
     164           0 :         return nullptr;
     165             : 
     166       34485 :     return asRecords[nIndex].poRecord.get();
     167             : }
     168             : 
     169             : /************************************************************************/
     170             : /*                        GetClientInfoByIndex()                        */
     171             : /************************************************************************/
     172             : 
     173      331300 : const void *DDFRecordIndex::GetClientInfoByIndex(int nIndex) const
     174             : 
     175             : {
     176      331300 :     if (!bSorted)
     177           0 :         Sort();
     178             : 
     179      331300 :     if (nIndex < 0 || nIndex >= GetCount())
     180           0 :         return nullptr;
     181             : 
     182      331300 :     return asRecords[nIndex].pClientData;
     183             : }
     184             : 
     185             : /************************************************************************/
     186             : /*                        SetClientInfoByIndex()                        */
     187             : /************************************************************************/
     188             : 
     189        7207 : void DDFRecordIndex::SetClientInfoByIndex(int nIndex, const void *pClientData)
     190             : 
     191             : {
     192        7207 :     if (!bSorted)
     193           0 :         Sort();
     194             : 
     195        7207 :     if (nIndex < 0 || nIndex >= GetCount())
     196           0 :         return;
     197             : 
     198        7207 :     asRecords[nIndex].pClientData = pClientData;
     199             : }

Generated by: LCOV version 1.14