Coverage Report

Created: 2026-02-14 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/lvbag/ogrlvbagdatasource.cpp
Line
Count
Source
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
OGRLVBAGDataSource::OGRLVBAGDataSource()
25
24.3k
    : poPool{new OGRLayerPool{}}, papoLayers{OGRLVBAG::LayerVector{}}
26
24.3k
{
27
24.3k
    const int nMaxSimultaneouslyOpened =
28
24.3k
        std::max(atoi(CPLGetConfigOption("OGR_LVBAG_MAX_OPENED", "100")), 1);
29
24.3k
    if (poPool->GetMaxSimultaneouslyOpened() != nMaxSimultaneouslyOpened)
30
0
    {
31
0
        poPool.reset(new OGRLayerPool(nMaxSimultaneouslyOpened));
32
0
    }
33
24.3k
}
34
35
/************************************************************************/
36
/*                                Open()                                */
37
/************************************************************************/
38
39
int OGRLVBAGDataSource::Open(const char *pszFilename, char **papszOpenOptionsIn)
40
18.8k
{
41
18.8k
    auto poLayer = std::unique_ptr<OGRLVBAGLayer>{
42
18.8k
        new OGRLVBAGLayer{pszFilename, poPool.get(), papszOpenOptionsIn}};
43
18.8k
    if (poLayer && !poLayer->TouchLayer())
44
0
    {
45
0
        return FALSE;
46
0
    }
47
48
18.8k
    papoLayers.push_back({OGRLVBAG::LayerType::LYR_RAW, std::move(poLayer)});
49
50
18.8k
    if ((static_cast<int>(papoLayers.size()) + 1) %
51
18.8k
                poPool->GetMaxSimultaneouslyOpened() ==
52
18.8k
            0 &&
53
0
        poPool->GetSize() > 0)
54
0
    {
55
0
        TryCoalesceLayers();
56
0
    }
57
58
18.8k
    return TRUE;
59
18.8k
}
60
61
/************************************************************************/
62
/*                         TryCoalesceLayers()                          */
63
/************************************************************************/
64
65
void OGRLVBAGDataSource::TryCoalesceLayers()
66
43.2k
{
67
43.2k
    std::vector<int> paGroup = {};
68
43.2k
    std::map<int, std::vector<int>> paMergeVector = {};
69
70
    // FUTURE: This can be optimized
71
    // Find similar layers by doing a triangular matrix
72
    // comparison across all layers currently enlisted.
73
80.8k
    for (size_t i = 0; i < papoLayers.size(); ++i)
74
37.6k
    {
75
37.6k
        std::vector<int> paVector = {};
76
75.2k
        for (size_t j = 0; j < papoLayers.size(); ++j)
77
37.6k
        {
78
37.6k
            if (std::find(paGroup.cbegin(), paGroup.cend(),
79
37.6k
                          static_cast<int>(j)) != paGroup.cend())
80
0
            {
81
0
                continue;
82
0
            }
83
84
37.6k
            OGRLayer *poLayerLHS = papoLayers[i].second.get();
85
37.6k
            OGRLayer *poLayerRHS = papoLayers[j].second.get();
86
87
37.6k
            if (j > i && EQUAL(poLayerLHS->GetName(), poLayerRHS->GetName()))
88
0
            {
89
0
                if (poLayerLHS->GetGeomType() == poLayerRHS->GetGeomType() &&
90
0
                    poLayerLHS->GetLayerDefn()->IsSame(
91
0
                        poLayerRHS->GetLayerDefn()))
92
0
                {
93
0
                    paVector.push_back(static_cast<int>(j));
94
0
                    paGroup.push_back(static_cast<int>(j));
95
0
                }
96
0
            }
97
37.6k
        }
98
37.6k
        if (!paVector.empty())
99
0
        {
100
0
            paMergeVector.insert({static_cast<int>(i), paVector});
101
0
        }
102
37.6k
    }
103
104
43.2k
    if (paMergeVector.empty())
105
43.2k
    {
106
43.2k
        return;
107
43.2k
    }
108
109
0
    for (const auto &mergeLayer : paMergeVector)
110
0
    {
111
0
        const int baseLayerIdx = mergeLayer.first;
112
0
        const std::vector<int> papoLayersIdx = mergeLayer.second;
113
114
0
        int nSrcLayers = static_cast<int>(papoLayersIdx.size()) + 1;
115
0
        OGRLayer **papoSrcLayers = static_cast<OGRLayer **>(
116
0
            CPLRealloc(nullptr, sizeof(OGRLayer *) * nSrcLayers));
117
118
0
        CPLAssert(papoLayers[baseLayerIdx].second);
119
120
0
        int idx = 0;
121
0
        papoSrcLayers[idx++] = papoLayers[baseLayerIdx].second.release();
122
0
        for (const auto &poLayerIdx : papoLayersIdx)
123
0
        {
124
0
            papoSrcLayers[idx++] = papoLayers[poLayerIdx].second.release();
125
0
        }
126
127
0
        OGRLayer *poBaseLayer = papoSrcLayers[0];
128
129
0
        auto poLayer = std::make_unique<OGRUnionLayer>(
130
0
            poBaseLayer->GetName(), nSrcLayers, papoSrcLayers, TRUE);
131
132
0
        OGRFeatureDefn *poBaseLayerDefn = poBaseLayer->GetLayerDefn();
133
134
0
        poLayer->SetFields(FIELD_FROM_FIRST_LAYER, poBaseLayerDefn);
135
136
0
        papoLayers.push_back({OGRLVBAG::LayerType::LYR_RAW,
137
0
                              OGRLayerUniquePtr{poLayer.release()}});
138
0
    }
139
140
    // Erase all released pointers
141
0
    auto it = papoLayers.begin();
142
0
    while (it != papoLayers.end())
143
0
    {
144
0
        if (!it->second)
145
0
        {
146
0
            it = papoLayers.erase(it);
147
0
        }
148
0
        else
149
0
        {
150
0
            ++it;
151
0
        }
152
0
    }
153
0
}
154
155
/************************************************************************/
156
/*                              GetLayer()                              */
157
/************************************************************************/
158
159
const OGRLayer *OGRLVBAGDataSource::GetLayer(int iLayer) const
160
18.8k
{
161
18.8k
    if (iLayer < 0 || iLayer >= GetLayerCount())
162
0
    {
163
0
        return nullptr;
164
0
    }
165
18.8k
    return papoLayers[iLayer].second.get();
166
18.8k
}
167
168
/************************************************************************/
169
/*                           GetLayerCount()                            */
170
/************************************************************************/
171
172
int OGRLVBAGDataSource::GetLayerCount() const
173
43.2k
{
174
43.2k
    const_cast<OGRLVBAGDataSource *>(this)->TryCoalesceLayers();
175
43.2k
    return static_cast<int>(papoLayers.size());
176
43.2k
}
177
178
/************************************************************************/
179
/*                           TestCapability()                           */
180
/************************************************************************/
181
182
int OGRLVBAGDataSource::TestCapability(const char * /* pszCap */) const
183
0
{
184
0
    return FALSE;
185
0
}