Coverage Report

Created: 2025-07-23 09:13

/src/gdal/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
Line
Count
Source (jump to first uncovered line)
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
17.4k
    : poImdReader(new ImdReader(1)), poReader(nullptr), nLayers(0),
28
17.4k
      papoLayers(nullptr)
29
17.4k
{
30
17.4k
}
31
32
/************************************************************************/
33
/*                        ~OGRILI1DataSource()                         */
34
/************************************************************************/
35
36
OGRILI1DataSource::~OGRILI1DataSource()
37
38
17.4k
{
39
17.4k
    for (int i = 0; i < nLayers; i++)
40
0
    {
41
0
        delete papoLayers[i];
42
0
    }
43
17.4k
    CPLFree(papoLayers);
44
45
17.4k
    DestroyILI1Reader(poReader);
46
17.4k
    delete poImdReader;
47
17.4k
}
48
49
/************************************************************************/
50
/*                                Open()                                */
51
/************************************************************************/
52
53
int OGRILI1DataSource::Open(const char *pszNewName, char **papszOpenOptionsIn,
54
                            int bTestOpen)
55
56
17.4k
{
57
17.4k
    if (strlen(pszNewName) == 0)
58
0
    {
59
0
        return FALSE;
60
0
    }
61
62
17.4k
    std::string osBasename;
63
17.4k
    std::string osModelFilename;
64
17.4k
    if (CSLFetchNameValue(papszOpenOptionsIn, "MODEL") != nullptr)
65
0
    {
66
0
        osBasename = pszNewName;
67
0
        osModelFilename = CSLFetchNameValue(papszOpenOptionsIn, "MODEL");
68
0
    }
69
17.4k
    else
70
17.4k
    {
71
17.4k
        char **filenames = CSLTokenizeString2(pszNewName, ",", 0);
72
17.4k
        int nCount = CSLCount(filenames);
73
17.4k
        if (nCount == 0)
74
0
        {
75
0
            CSLDestroy(filenames);
76
0
            return FALSE;
77
0
        }
78
17.4k
        osBasename = filenames[0];
79
80
17.4k
        if (nCount > 1)
81
8.89k
            osModelFilename = filenames[1];
82
83
17.4k
        CSLDestroy(filenames);
84
17.4k
    }
85
86
    /* -------------------------------------------------------------------- */
87
    /*      Open the source file.                                           */
88
    /* -------------------------------------------------------------------- */
89
17.4k
    VSILFILE *fp = VSIFOpenL(osBasename.c_str(), "r");
90
17.4k
    if (fp == nullptr)
91
8.48k
    {
92
8.48k
        if (!bTestOpen)
93
0
            CPLError(CE_Failure, CPLE_OpenFailed,
94
0
                     "Failed to open ILI1 file `%s'.", pszNewName);
95
96
8.48k
        return FALSE;
97
8.48k
    }
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
8.93k
    char szHeader[1000];
104
105
8.93k
    if (bTestOpen)
106
8.93k
    {
107
8.93k
        int nLen = (int)VSIFReadL(szHeader, 1, sizeof(szHeader), fp);
108
8.93k
        if (nLen == sizeof(szHeader))
109
6.62k
            szHeader[sizeof(szHeader) - 1] = '\0';
110
2.30k
        else
111
2.30k
            szHeader[nLen] = '\0';
112
113
8.93k
        if (strstr(szHeader, "SCNT") == nullptr)
114
1.24k
        {
115
1.24k
            VSIFCloseL(fp);
116
1.24k
            return FALSE;
117
1.24k
        }
118
8.93k
    }
119
120
    /* -------------------------------------------------------------------- */
121
    /*      We assume now that it is ILI1.  Close and instantiate a          */
122
    /*      ILI1Reader on it.                                                */
123
    /* -------------------------------------------------------------------- */
124
7.69k
    VSIFCloseL(fp);
125
126
7.69k
    poReader = CreateILI1Reader();
127
7.69k
    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
7.69k
    poReader->OpenFile(osBasename.c_str());
138
139
7.69k
    if (osModelFilename.length() > 0)
140
0
        poReader->ReadModel(poImdReader, osModelFilename.c_str(), this);
141
142
7.69k
    CPLConfigOptionSetter oSetter("OGR_ARC_STEPSIZE", "0.96",
143
7.69k
                                  /* bSetOnlyIfUndefined = */ true);
144
145
    // Parse model and read data - without surface join and area polygonizing.
146
7.69k
    poReader->ReadFeatures();
147
148
7.69k
    return TRUE;
149
7.69k
}
150
151
/************************************************************************/
152
/*                           TestCapability()                           */
153
/************************************************************************/
154
155
int OGRILI1DataSource::TestCapability(const char *pszCap)
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
OGRLayer *OGRILI1DataSource::GetLayer(int iLayer)
171
4.58k
{
172
4.58k
    if (!poReader)
173
0
    {
174
0
        if (iLayer < 0 || iLayer >= nLayers)
175
0
            return nullptr;
176
0
        return papoLayers[iLayer];
177
0
    }
178
4.58k
    return poReader->GetLayer(iLayer);
179
4.58k
}
180
181
/************************************************************************/
182
/*                              GetLayerByName()                              */
183
/************************************************************************/
184
185
OGRILI1Layer *OGRILI1DataSource::GetLayerByName(const char *pszLayerName)
186
1.06k
{
187
1.06k
    if (!poReader)
188
0
    {
189
0
        return cpl::down_cast<OGRILI1Layer *>(
190
0
            GDALDataset::GetLayerByName(pszLayerName));
191
0
    }
192
193
1.06k
    return cpl::down_cast<OGRILI1Layer *>(
194
1.06k
        poReader->GetLayerByName(pszLayerName));
195
1.06k
}