Coverage Report

Created: 2025-11-15 08:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  Interlis 1 Translator
4
 * Purpose:  Implements OGRILI1DataSource class.
5
 * Author:   Pirmin Kalberer, Sourcepole AG
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
9
 * Copyright (c) 2007-2008, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "cpl_conv.h"
15
#include "cpl_string.h"
16
17
#include "ili1reader.h"
18
#include "ogr_ili1.h"
19
20
#include <string>
21
22
/************************************************************************/
23
/*                         OGRILI1DataSource()                         */
24
/************************************************************************/
25
26
OGRILI1DataSource::OGRILI1DataSource()
27
19.8k
    : poImdReader(new ImdReader(1)), poReader(nullptr), nLayers(0),
28
19.8k
      papoLayers(nullptr)
29
19.8k
{
30
19.8k
}
31
32
/************************************************************************/
33
/*                        ~OGRILI1DataSource()                         */
34
/************************************************************************/
35
36
OGRILI1DataSource::~OGRILI1DataSource()
37
38
19.8k
{
39
19.8k
    for (int i = 0; i < nLayers; i++)
40
0
    {
41
0
        delete papoLayers[i];
42
0
    }
43
19.8k
    CPLFree(papoLayers);
44
45
19.8k
    DestroyILI1Reader(poReader);
46
19.8k
    delete poImdReader;
47
19.8k
}
48
49
/************************************************************************/
50
/*                                Open()                                */
51
/************************************************************************/
52
53
int OGRILI1DataSource::Open(const char *pszNewName, char **papszOpenOptionsIn,
54
                            int bTestOpen)
55
56
19.8k
{
57
19.8k
    if (strlen(pszNewName) == 0)
58
0
    {
59
0
        return FALSE;
60
0
    }
61
62
19.8k
    std::string osBasename;
63
19.8k
    std::string osModelFilename;
64
19.8k
    if (CSLFetchNameValue(papszOpenOptionsIn, "MODEL") != nullptr)
65
0
    {
66
0
        osBasename = pszNewName;
67
0
        osModelFilename = CSLFetchNameValue(papszOpenOptionsIn, "MODEL");
68
0
    }
69
19.8k
    else
70
19.8k
    {
71
19.8k
        char **filenames = CSLTokenizeString2(pszNewName, ",", 0);
72
19.8k
        int nCount = CSLCount(filenames);
73
19.8k
        if (nCount == 0)
74
1
        {
75
1
            CSLDestroy(filenames);
76
1
            return FALSE;
77
1
        }
78
19.8k
        osBasename = filenames[0];
79
80
19.8k
        if (nCount > 1)
81
10.8k
            osModelFilename = filenames[1];
82
83
19.8k
        CSLDestroy(filenames);
84
19.8k
    }
85
86
    /* -------------------------------------------------------------------- */
87
    /*      Open the source file.                                           */
88
    /* -------------------------------------------------------------------- */
89
19.8k
    VSILFILE *fp = VSIFOpenL(osBasename.c_str(), "r");
90
19.8k
    if (fp == nullptr)
91
10.4k
    {
92
10.4k
        if (!bTestOpen)
93
0
            CPLError(CE_Failure, CPLE_OpenFailed,
94
0
                     "Failed to open ILI1 file `%s'.", pszNewName);
95
96
10.4k
        return FALSE;
97
10.4k
    }
98
99
    /* -------------------------------------------------------------------- */
100
    /*      If we aren't sure it is ILI1, load a header chunk and check      */
101
    /*      for signs it is ILI1                                             */
102
    /* -------------------------------------------------------------------- */
103
9.37k
    char szHeader[1000];
104
105
9.37k
    if (bTestOpen)
106
9.37k
    {
107
9.37k
        int nLen = (int)VSIFReadL(szHeader, 1, sizeof(szHeader), fp);
108
9.37k
        if (nLen == sizeof(szHeader))
109
7.05k
            szHeader[sizeof(szHeader) - 1] = '\0';
110
2.32k
        else
111
2.32k
            szHeader[nLen] = '\0';
112
113
9.37k
        if (strstr(szHeader, "SCNT") == nullptr)
114
1.25k
        {
115
1.25k
            VSIFCloseL(fp);
116
1.25k
            return FALSE;
117
1.25k
        }
118
9.37k
    }
119
120
    /* -------------------------------------------------------------------- */
121
    /*      We assume now that it is ILI1.  Close and instantiate a          */
122
    /*      ILI1Reader on it.                                                */
123
    /* -------------------------------------------------------------------- */
124
8.12k
    VSIFCloseL(fp);
125
126
8.12k
    poReader = CreateILI1Reader();
127
8.12k
    if (poReader == nullptr)
128
0
    {
129
0
        CPLError(CE_Failure, CPLE_AppDefined,
130
0
                 "File %s appears to be ILI1 but the ILI1 reader cannot\n"
131
0
                 "be instantiated, likely because Xerces support was not\n"
132
0
                 "configured in.",
133
0
                 pszNewName);
134
0
        return FALSE;
135
0
    }
136
137
8.12k
    poReader->OpenFile(osBasename.c_str());
138
139
8.12k
    if (osModelFilename.length() > 0)
140
0
        poReader->ReadModel(poImdReader, osModelFilename.c_str(), this);
141
142
8.12k
    CPLConfigOptionSetter oSetter("OGR_ARC_STEPSIZE", "0.96",
143
8.12k
                                  /* bSetOnlyIfUndefined = */ true);
144
145
    // Parse model and read data - without surface join and area polygonizing.
146
8.12k
    poReader->ReadFeatures();
147
148
8.12k
    return TRUE;
149
8.12k
}
150
151
/************************************************************************/
152
/*                           TestCapability()                           */
153
/************************************************************************/
154
155
int OGRILI1DataSource::TestCapability(const char *pszCap) const
156
157
0
{
158
0
    if (EQUAL(pszCap, ODsCCurveGeometries))
159
0
        return TRUE;
160
0
    else if (EQUAL(pszCap, ODsCZGeometries))
161
0
        return TRUE;
162
163
0
    return FALSE;
164
0
}
165
166
/************************************************************************/
167
/*                              GetLayer()                              */
168
/************************************************************************/
169
170
const OGRLayer *OGRILI1DataSource::GetLayer(int iLayer) const
171
4.64k
{
172
4.64k
    if (!poReader)
173
0
    {
174
0
        if (iLayer < 0 || iLayer >= nLayers)
175
0
            return nullptr;
176
0
        return papoLayers[iLayer];
177
0
    }
178
4.64k
    return poReader->GetLayer(iLayer);
179
4.64k
}
180
181
/************************************************************************/
182
/*                              GetLayerByName()                              */
183
/************************************************************************/
184
185
OGRILI1Layer *OGRILI1DataSource::GetLayerByName(const char *pszLayerName)
186
925
{
187
925
    if (!poReader)
188
0
    {
189
0
        return cpl::down_cast<OGRILI1Layer *>(
190
0
            GDALDataset::GetLayerByName(pszLayerName));
191
0
    }
192
193
925
    return cpl::down_cast<OGRILI1Layer *>(
194
925
        poReader->GetLayerByName(pszLayerName));
195
925
}