Coverage Report

Created: 2026-08-11 08:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  Idrisi Translator
4
 * Purpose:  Implements OGRIdrisiDataSource class
5
 * Author:   Even Rouault, even dot rouault at spatialys.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2011-2012, Even Rouault <even dot rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "cpl_conv.h"
14
#include "cpl_string.h"
15
#include "idrisi.h"
16
#include "ogr_idrisi.h"
17
18
/************************************************************************/
19
/*                        OGRIdrisiDataSource()                         */
20
/************************************************************************/
21
22
15
OGRIdrisiDataSource::OGRIdrisiDataSource() = default;
23
24
/************************************************************************/
25
/*                        ~OGRIdrisiDataSource()                        */
26
/************************************************************************/
27
28
OGRIdrisiDataSource::~OGRIdrisiDataSource()
29
30
15
{
31
15
    for (int i = 0; i < nLayers; i++)
32
0
        delete papoLayers[i];
33
15
    CPLFree(papoLayers);
34
15
}
35
36
/************************************************************************/
37
/*                              GetLayer()                              */
38
/************************************************************************/
39
40
const OGRLayer *OGRIdrisiDataSource::GetLayer(int iLayer) const
41
42
0
{
43
0
    if (iLayer < 0 || iLayer >= nLayers)
44
0
        return nullptr;
45
46
0
    return papoLayers[iLayer];
47
0
}
48
49
/************************************************************************/
50
/*                                Open()                                */
51
/************************************************************************/
52
53
int OGRIdrisiDataSource::Open(const char *pszFilename)
54
55
15
{
56
15
    VSILFILE *fpVCT = VSIFOpenL(pszFilename, "rb");
57
15
    if (fpVCT == nullptr)
58
0
        return FALSE;
59
60
    // --------------------------------------------------------------------
61
    //      Look for .vdc file
62
    // --------------------------------------------------------------------
63
15
    std::string osVDCFilename = CPLResetExtensionSafe(pszFilename, "vdc");
64
15
    VSILFILE *fpVDC = VSIFOpenL(osVDCFilename.c_str(), "rb");
65
15
    if (fpVDC == nullptr)
66
15
    {
67
15
        osVDCFilename = CPLResetExtensionSafe(pszFilename, "VDC");
68
15
        fpVDC = VSIFOpenL(osVDCFilename.c_str(), "rb");
69
15
    }
70
71
15
    char **papszVDC = nullptr;
72
15
    if (fpVDC != nullptr)
73
0
    {
74
0
        VSIFCloseL(fpVDC);
75
0
        fpVDC = nullptr;
76
77
0
        CPLPushErrorHandler(CPLQuietErrorHandler);
78
0
        papszVDC = CSLLoad2(osVDCFilename.c_str(), 1024, 256, nullptr);
79
0
        CPLPopErrorHandler();
80
0
        CPLErrorReset();
81
0
    }
82
83
15
    OGRwkbGeometryType eType = wkbUnknown;
84
85
15
    char *pszWTKString = nullptr;
86
15
    if (papszVDC != nullptr)
87
0
    {
88
0
        CSLSetNameValueSeparator(papszVDC, ":");
89
90
0
        const char *pszVersion = CSLFetchNameValue(papszVDC, "file format");
91
92
0
        if (pszVersion == nullptr || !EQUAL(pszVersion, "IDRISI Vector A.1"))
93
0
        {
94
0
            CSLDestroy(papszVDC);
95
0
            VSIFCloseL(fpVCT);
96
0
            return FALSE;
97
0
        }
98
99
0
        const char *pszRefSystem = CSLFetchNameValue(papszVDC, "ref. system");
100
0
        const char *pszRefUnits = CSLFetchNameValue(papszVDC, "ref. units");
101
102
0
        if (pszRefSystem != nullptr && pszRefUnits != nullptr)
103
0
        {
104
0
            OGRSpatialReference oSRS;
105
0
            IdrisiGeoReference2Wkt(pszFilename, pszRefSystem, pszRefUnits,
106
0
                                   oSRS);
107
0
            if (!oSRS.IsEmpty())
108
0
            {
109
0
                oSRS.exportToWkt(&pszWTKString);
110
0
            }
111
0
        }
112
0
    }
113
114
15
    GByte chType = 0;
115
15
    if (VSIFReadL(&chType, 1, 1, fpVCT) != 1)
116
0
    {
117
0
        VSIFCloseL(fpVCT);
118
0
        CSLDestroy(papszVDC);
119
0
        CPLFree(pszWTKString);
120
0
        return FALSE;
121
0
    }
122
123
15
    if (chType == 1)
124
0
        eType = wkbPoint;
125
15
    else if (chType == 2)
126
0
        eType = wkbLineString;
127
15
    else if (chType == 3)
128
0
        eType = wkbPolygon;
129
15
    else
130
15
    {
131
15
        CPLError(CE_Failure, CPLE_AppDefined, "Unsupported geometry type : %d",
132
15
                 static_cast<int>(chType));
133
15
        VSIFCloseL(fpVCT);
134
15
        CSLDestroy(papszVDC);
135
15
        CPLFree(pszWTKString);
136
15
        return FALSE;
137
15
    }
138
139
0
    const char *pszMinX = CSLFetchNameValue(papszVDC, "min. X");
140
0
    const char *pszMaxX = CSLFetchNameValue(papszVDC, "max. X");
141
0
    const char *pszMinY = CSLFetchNameValue(papszVDC, "min. Y");
142
0
    const char *pszMaxY = CSLFetchNameValue(papszVDC, "max. Y");
143
144
0
    OGRIdrisiLayer *poLayer =
145
0
        new OGRIdrisiLayer(pszFilename, CPLGetBasenameSafe(pszFilename).c_str(),
146
0
                           fpVCT, eType, pszWTKString);
147
0
    papoLayers = static_cast<OGRLayer **>(CPLMalloc(sizeof(OGRLayer *)));
148
0
    papoLayers[nLayers++] = poLayer;
149
150
0
    if (pszMinX != nullptr && pszMaxX != nullptr && pszMinY != nullptr &&
151
0
        pszMaxY != nullptr)
152
0
    {
153
0
        poLayer->SetExtent(CPLAtof(pszMinX), CPLAtof(pszMinY), CPLAtof(pszMaxX),
154
0
                           CPLAtof(pszMaxY));
155
0
    }
156
157
0
    CPLFree(pszWTKString);
158
159
0
    CSLDestroy(papszVDC);
160
161
0
    return TRUE;
162
15
}