LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/lvbag - ogrlvbagdatasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 78 82 95.1 %
Date: 2024-11-21 22:18:42 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  LV BAG Translator
       4             :  * Purpose:  Implements OGRLVBAGDataSource.
       5             :  * Author:   Laixer B.V., info at laixer dot com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2020, Laixer B.V. <info at laixer dot com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "ogr_lvbag.h"
      14             : #include "ogrsf_frmts.h"
      15             : #include "ogrunionlayer.h"
      16             : #include "ogrlayerpool.h"
      17             : 
      18             : #include <algorithm>
      19             : 
      20             : /************************************************************************/
      21             : /*                          OGRLVBAGDataSource()                        */
      22             : /************************************************************************/
      23             : 
      24         591 : OGRLVBAGDataSource::OGRLVBAGDataSource()
      25         591 :     : poPool{new OGRLayerPool{}}, papoLayers{OGRLVBAG::LayerVector{}}
      26             : {
      27             :     const int nMaxSimultaneouslyOpened =
      28         591 :         std::max(atoi(CPLGetConfigOption("OGR_LVBAG_MAX_OPENED", "100")), 1);
      29         591 :     if (poPool->GetMaxSimultaneouslyOpened() != nMaxSimultaneouslyOpened)
      30           0 :         poPool.reset(new OGRLayerPool(nMaxSimultaneouslyOpened));
      31         591 : }
      32             : 
      33             : /************************************************************************/
      34             : /*                                Open()                                */
      35             : /************************************************************************/
      36             : 
      37          29 : int OGRLVBAGDataSource::Open(const char *pszFilename, char **papszOpenOptionsIn)
      38             : {
      39             :     auto poLayer = std::unique_ptr<OGRLVBAGLayer>{
      40          58 :         new OGRLVBAGLayer{pszFilename, poPool.get(), papszOpenOptionsIn}};
      41          29 :     if (poLayer && !poLayer->TouchLayer())
      42           0 :         return FALSE;
      43             : 
      44          29 :     papoLayers.push_back({OGRLVBAG::LayerType::LYR_RAW, std::move(poLayer)});
      45             : 
      46          29 :     if ((static_cast<int>(papoLayers.size()) + 1) %
      47          29 :                 poPool->GetMaxSimultaneouslyOpened() ==
      48          29 :             0 &&
      49           0 :         poPool->GetSize() > 0)
      50           0 :         TryCoalesceLayers();
      51             : 
      52          29 :     return TRUE;
      53             : }
      54             : 
      55             : /************************************************************************/
      56             : /*                          TryCoalesceLayers()                         */
      57             : /************************************************************************/
      58             : 
      59         769 : void OGRLVBAGDataSource::TryCoalesceLayers()
      60             : {
      61         769 :     std::vector<int> paGroup = {};
      62         769 :     std::map<int, std::vector<int>> paMergeVector = {};
      63             : 
      64             :     // FUTURE: This can be optimized
      65             :     // Find similar layers by doing a triangular matrix
      66             :     // comparison across all layers currently enlisted.
      67         979 :     for (size_t i = 0; i < papoLayers.size(); ++i)
      68             :     {
      69         420 :         std::vector<int> paVector = {};
      70         434 :         for (size_t j = 0; j < papoLayers.size(); ++j)
      71             :         {
      72         227 :             if (std::find(paGroup.cbegin(), paGroup.cend(),
      73         224 :                           static_cast<int>(j)) != paGroup.cend())
      74           3 :                 continue;
      75             : 
      76         221 :             OGRLayer *poLayerLHS = papoLayers[i].second.get();
      77         221 :             OGRLayer *poLayerRHS = papoLayers[j].second.get();
      78             : 
      79         221 :             if (j > i && EQUAL(poLayerLHS->GetName(), poLayerRHS->GetName()))
      80             :             {
      81           4 :                 if (poLayerLHS->GetGeomType() == poLayerRHS->GetGeomType() &&
      82           4 :                     poLayerLHS->GetLayerDefn()->IsSame(
      83           2 :                         poLayerRHS->GetLayerDefn()))
      84             :                 {
      85           2 :                     paVector.push_back(static_cast<int>(j));
      86           2 :                     paGroup.push_back(static_cast<int>(j));
      87             :                 }
      88             :             }
      89             :         }
      90         210 :         if (!paVector.empty())
      91           2 :             paMergeVector.insert({static_cast<int>(i), paVector});
      92             :     }
      93             : 
      94         769 :     if (paMergeVector.empty())
      95         767 :         return;
      96             : 
      97           4 :     for (const auto &mergeLayer : paMergeVector)
      98             :     {
      99           2 :         const int baseLayerIdx = mergeLayer.first;
     100           4 :         const std::vector<int> papoLayersIdx = mergeLayer.second;
     101             : 
     102           2 :         int nSrcLayers = static_cast<int>(papoLayersIdx.size()) + 1;
     103             :         OGRLayer **papoSrcLayers = static_cast<OGRLayer **>(
     104           2 :             CPLRealloc(nullptr, sizeof(OGRLayer *) * nSrcLayers));
     105             : 
     106           2 :         CPLAssert(papoLayers[baseLayerIdx].second);
     107             : 
     108           2 :         int idx = 0;
     109           2 :         papoSrcLayers[idx++] = papoLayers[baseLayerIdx].second.release();
     110           4 :         for (const auto &poLayerIdx : papoLayersIdx)
     111           2 :             papoSrcLayers[idx++] = papoLayers[poLayerIdx].second.release();
     112             : 
     113           2 :         OGRLayer *poBaseLayer = papoSrcLayers[0];
     114             : 
     115             :         auto poLayer = std::unique_ptr<OGRUnionLayer>{new OGRUnionLayer{
     116           2 :             poBaseLayer->GetName(), nSrcLayers, papoSrcLayers, TRUE}};
     117             : 
     118           2 :         OGRFeatureDefn *poBaseLayerDefn = poBaseLayer->GetLayerDefn();
     119             : 
     120           2 :         const int nFields = poBaseLayerDefn->GetFieldCount();
     121             :         OGRFieldDefn **papoFields = static_cast<OGRFieldDefn **>(
     122           2 :             CPLRealloc(nullptr, sizeof(OGRFieldDefn *) * nFields));
     123          34 :         for (int i = 0; i < nFields; ++i)
     124          32 :             papoFields[i] = poBaseLayerDefn->GetFieldDefn(i);
     125             : 
     126           2 :         const int nGeomFields = poBaseLayerDefn->GetGeomFieldCount();
     127             :         OGRUnionLayerGeomFieldDefn **papoGeomFields =
     128           4 :             static_cast<OGRUnionLayerGeomFieldDefn **>(CPLRealloc(
     129           2 :                 nullptr, sizeof(OGRUnionLayerGeomFieldDefn *) * nGeomFields));
     130           4 :         for (int i = 0; i < nGeomFields; ++i)
     131           2 :             papoGeomFields[i] = new OGRUnionLayerGeomFieldDefn(
     132           2 :                 poBaseLayerDefn->GetGeomFieldDefn(i));
     133             : 
     134           2 :         poLayer->SetFields(FIELD_FROM_FIRST_LAYER, nFields, papoFields,
     135             :                            nGeomFields, papoGeomFields);
     136             : 
     137           4 :         for (int i = 0; i < nGeomFields; ++i)
     138           2 :             delete papoGeomFields[i];
     139           2 :         CPLFree(papoGeomFields);
     140           2 :         CPLFree(papoFields);
     141             : 
     142           2 :         papoLayers.push_back({OGRLVBAG::LayerType::LYR_RAW,
     143           4 :                               OGRLayerUniquePtr{poLayer.release()}});
     144             :     }
     145             : 
     146             :     // Erase all released pointers
     147           2 :     auto it = papoLayers.begin();
     148           9 :     while (it != papoLayers.end())
     149             :     {
     150           7 :         if (!it->second)
     151           4 :             it = papoLayers.erase(it);
     152             :         else
     153           3 :             ++it;
     154             :     }
     155             : }
     156             : 
     157             : /************************************************************************/
     158             : /*                              GetLayer()                              */
     159             : /************************************************************************/
     160             : 
     161          96 : OGRLayer *OGRLVBAGDataSource::GetLayer(int iLayer)
     162             : {
     163          96 :     if (iLayer < 0 || iLayer >= GetLayerCount())
     164           7 :         return nullptr;
     165          89 :     return papoLayers[iLayer].second.get();
     166             : }
     167             : 
     168             : /************************************************************************/
     169             : /*                           GetLayerCount()                            */
     170             : /************************************************************************/
     171             : 
     172         769 : int OGRLVBAGDataSource::GetLayerCount()
     173             : {
     174         769 :     TryCoalesceLayers();
     175         769 :     return static_cast<int>(papoLayers.size());
     176             : }
     177             : 
     178             : /************************************************************************/
     179             : /*                           TestCapability()                           */
     180             : /************************************************************************/
     181             : 
     182          19 : int OGRLVBAGDataSource::TestCapability(const char * /* pszCap */)
     183             : {
     184          19 :     return FALSE;
     185             : }

Generated by: LCOV version 1.14