Coverage Report

Created: 2026-08-14 09:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/jsonfg/ogrjsonfgstreamedlayer.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Implementation of OGC Features and Geometries JSON (JSON-FG)
5
 * Author:   Even Rouault <even.rouault at spatialys.com>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2023, Even Rouault <even.rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "ogr_jsonfg.h"
14
15
/************************************************************************/
16
/*           OGRJSONFGStreamedLayer::OGRJSONFGStreamedLayer()           */
17
/************************************************************************/
18
19
OGRJSONFGStreamedLayer::OGRJSONFGStreamedLayer(GDALDataset *poDS,
20
                                               const char *pszName,
21
                                               OGRSpatialReference *poSRS,
22
                                               OGRwkbGeometryType eGType)
23
15
    : m_poDS(poDS), poFeatureDefn_(new OGRFeatureDefn(pszName))
24
15
{
25
26
15
    poFeatureDefn_->Reference();
27
28
15
    SetDescription(poFeatureDefn_->GetName());
29
15
    poFeatureDefn_->SetGeomType(eGType);
30
31
15
    if (eGType != wkbNone && poSRS != nullptr)
32
13
    {
33
13
        OGRSpatialReference *poSRSClone = poSRS->Clone();
34
13
        poFeatureDefn_->GetGeomFieldDefn(0)->SetSpatialRef(poSRSClone);
35
13
        poSRSClone->Release();
36
13
    }
37
38
15
    poFeatureDefn_->Seal(/* bSealFields = */ true);
39
15
}
40
41
/************************************************************************/
42
/*          OGRJSONFGStreamedLayer::~OGRJSONFGStreamedLayer()           */
43
/************************************************************************/
44
45
OGRJSONFGStreamedLayer::~OGRJSONFGStreamedLayer()
46
15
{
47
15
    poFeatureDefn_->Release();
48
15
}
49
50
/************************************************************************/
51
/*                              SetFile()                               */
52
/************************************************************************/
53
54
void OGRJSONFGStreamedLayer::SetFile(VSIVirtualHandleUniquePtr &&poFile)
55
15
{
56
15
    poFile_ = std::move(poFile);
57
15
    poFile_->Seek(0, SEEK_SET);
58
15
}
59
60
/************************************************************************/
61
/*                         SetStreamingParser()                         */
62
/************************************************************************/
63
64
void OGRJSONFGStreamedLayer::SetStreamingParser(
65
    std::unique_ptr<OGRJSONFGStreamingParser> &&poStreamingParser)
66
15
{
67
15
    poStreamingParser_ = std::move(poStreamingParser);
68
15
    poStreamingParser_->SetRequestedLayer(GetName());
69
15
}
70
71
/************************************************************************/
72
/*                            ResetReading()                            */
73
/************************************************************************/
74
75
void OGRJSONFGStreamedLayer::ResetReading()
76
0
{
77
0
    CPLAssert(poFile_);
78
0
    CPLAssert(poStreamingParser_);
79
0
    poStreamingParser_ = poStreamingParser_->Clone();
80
0
    poFile_->Seek(0, SEEK_SET);
81
0
    oSetUsedFIDs_.clear();
82
0
}
83
84
/************************************************************************/
85
/*                          EnsureUniqueFID()                           */
86
/************************************************************************/
87
88
OGRFeature *OGRJSONFGStreamedLayer::EnsureUniqueFID(OGRFeature *poFeat)
89
28
{
90
28
    GIntBig nFID = poFeat->GetFID();
91
28
    if (nFID == OGRNullFID)
92
7
    {
93
7
        nFID = static_cast<GIntBig>(oSetUsedFIDs_.size());
94
7
        while (oSetUsedFIDs_.find(nFID) != oSetUsedFIDs_.end())
95
0
        {
96
0
            ++nFID;
97
0
        }
98
7
    }
99
21
    else if (oSetUsedFIDs_.find(nFID) != oSetUsedFIDs_.end())
100
4
    {
101
4
        if (!bOriginalIdModified_)
102
4
        {
103
4
            CPLError(CE_Warning, CPLE_AppDefined,
104
4
                     "Several features with id = " CPL_FRMT_GIB " have "
105
4
                     "been found. Altering it to be unique. "
106
4
                     "This warning will not be emitted anymore for "
107
4
                     "this layer",
108
4
                     nFID);
109
4
            bOriginalIdModified_ = true;
110
4
        }
111
4
        nFID = static_cast<GIntBig>(oSetUsedFIDs_.size());
112
7
        while (oSetUsedFIDs_.find(nFID) != oSetUsedFIDs_.end())
113
3
        {
114
3
            ++nFID;
115
3
        }
116
4
    }
117
28
    oSetUsedFIDs_.insert(nFID);
118
28
    poFeat->SetFID(nFID);
119
28
    return poFeat;
120
28
}
121
122
/************************************************************************/
123
/*                         GetNextRawFeature()                          */
124
/************************************************************************/
125
126
OGRFeature *OGRJSONFGStreamedLayer::GetNextRawFeature()
127
43
{
128
43
    CPLAssert(poFile_);
129
43
    CPLAssert(poStreamingParser_);
130
131
43
    auto poFeatAndLayer = poStreamingParser_->GetNextFeature();
132
43
    if (poFeatAndLayer.first)
133
13
    {
134
13
        return EnsureUniqueFID(poFeatAndLayer.first.release());
135
13
    }
136
137
30
    std::vector<GByte> abyBuffer;
138
30
    abyBuffer.resize(4096 * 10);
139
30
    while (true)
140
30
    {
141
30
        size_t nRead = poFile_->Read(abyBuffer.data(), 1, abyBuffer.size());
142
30
        const bool bFinished = nRead < abyBuffer.size();
143
30
        if (!poStreamingParser_->Parse(
144
30
                std::string_view(
145
30
                    reinterpret_cast<const char *>(abyBuffer.data()), nRead),
146
30
                bFinished) ||
147
30
            poStreamingParser_->ExceptionOccurred())
148
0
        {
149
0
            break;
150
0
        }
151
152
30
        poFeatAndLayer = poStreamingParser_->GetNextFeature();
153
30
        if (poFeatAndLayer.first)
154
15
        {
155
15
            return EnsureUniqueFID(poFeatAndLayer.first.release());
156
15
        }
157
15
        if (bFinished)
158
15
            break;
159
15
    }
160
161
15
    return nullptr;
162
30
}
163
164
/************************************************************************/
165
/*                           TestCapability()                           */
166
/************************************************************************/
167
168
int OGRJSONFGStreamedLayer::TestCapability(const char *pszCap) const
169
170
0
{
171
0
    if (EQUAL(pszCap, OLCFastFeatureCount))
172
0
        return !m_poFilterGeom && !m_poAttrQuery && nFeatureCount_ >= 0;
173
174
0
    else if (EQUAL(pszCap, OLCStringsAsUTF8))
175
0
        return TRUE;
176
177
0
    else if (EQUAL(pszCap, OLCZGeometries) ||
178
0
             EQUAL(pszCap, OLCMeasuredGeometries) ||
179
0
             EQUAL(pszCap, OLCCurveGeometries))
180
0
    {
181
0
        return TRUE;
182
0
    }
183
184
0
    return FALSE;
185
0
}
186
187
/************************************************************************/
188
/*                          GetFeatureCount()                           */
189
/************************************************************************/
190
191
GIntBig OGRJSONFGStreamedLayer::GetFeatureCount(int bForce)
192
0
{
193
0
    if (!m_poFilterGeom && !m_poAttrQuery && nFeatureCount_ >= 0)
194
0
        return nFeatureCount_;
195
0
    return OGRLayer::GetFeatureCount(bForce);
196
0
}