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/miramon/ogrmiramondriver.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Implements OGRMiraMonDriver class.
5
 * Author:   Abel Pau
6
 ******************************************************************************
7
 * Copyright (c) 2024, Xavier Pons
8
 *
9
 * SPDX-License-Identifier: MIT
10
 ****************************************************************************/
11
12
#include "ogrmiramon.h"
13
14
#include <cmath>
15
16
bool MM_IsNANDouble(double x)
17
495
{
18
495
    return std::isnan(x);
19
495
}
20
21
bool MM_IsDoubleInfinite(double x)
22
495
{
23
495
    return std::isinf(x);
24
495
}
25
26
/****************************************************************************/
27
/*                    OGRMMDriverIdentify()                                 */
28
/****************************************************************************/
29
30
static int OGRMiraMonDriverIdentify(GDALOpenInfo *poOpenInfo)
31
32
91.1k
{
33
91.1k
    if (poOpenInfo->fpL == nullptr || poOpenInfo->nHeaderBytes < 7)
34
45.5k
        return FALSE;
35
45.5k
    else if (poOpenInfo->IsExtensionEqualToCI("PNT") ||
36
45.1k
             poOpenInfo->IsExtensionEqualToCI("ARC") ||
37
45.0k
             poOpenInfo->IsExtensionEqualToCI("POL"))
38
2.91k
    {
39
        // Format
40
2.91k
        if ((poOpenInfo->pabyHeader[0] == 'P' &&
41
2.70k
             poOpenInfo->pabyHeader[1] == 'N' &&
42
388
             poOpenInfo->pabyHeader[2] == 'T') ||
43
2.52k
            (poOpenInfo->pabyHeader[0] == 'A' &&
44
180
             poOpenInfo->pabyHeader[1] == 'R' &&
45
179
             poOpenInfo->pabyHeader[2] == 'C') ||
46
2.34k
            (poOpenInfo->pabyHeader[0] == 'P' &&
47
2.31k
             poOpenInfo->pabyHeader[1] == 'O' &&
48
2.31k
             poOpenInfo->pabyHeader[2] == 'L'))
49
2.88k
        {
50
            // Version 1.1 or 2.0
51
2.88k
            if ((poOpenInfo->pabyHeader[3] == ' ' &&
52
2.88k
                 poOpenInfo->pabyHeader[4] == '1' &&
53
1.58k
                 poOpenInfo->pabyHeader[5] == '.' &&
54
1.58k
                 poOpenInfo->pabyHeader[6] == '1') ||
55
1.29k
                (poOpenInfo->pabyHeader[3] == ' ' &&
56
1.29k
                 poOpenInfo->pabyHeader[4] == '2' &&
57
1.29k
                 poOpenInfo->pabyHeader[5] == '.' &&
58
1.29k
                 poOpenInfo->pabyHeader[6] == '0'))
59
2.88k
            {
60
2.88k
                return TRUE;
61
2.88k
            }
62
2.88k
        }
63
2.91k
    }
64
65
42.7k
    return FALSE;
66
91.1k
}
67
68
/****************************************************************************/
69
/*                           OGRMiraMonDriverOpen()                         */
70
/****************************************************************************/
71
72
static GDALDataset *OGRMiraMonDriverOpen(GDALOpenInfo *poOpenInfo)
73
74
1.44k
{
75
1.44k
    if (OGRMiraMonDriverIdentify(poOpenInfo) == FALSE)
76
0
        return nullptr;
77
78
1.44k
    auto poDS = std::make_unique<OGRMiraMonDataSource>();
79
1.44k
    if (!poDS->Open(poOpenInfo->pszFilename, nullptr, nullptr,
80
1.44k
                    poOpenInfo->papszOpenOptions))
81
1.13k
    {
82
1.13k
        poDS.reset();
83
1.13k
    }
84
85
1.44k
    if (poDS && poOpenInfo->eAccess == GA_Update)
86
0
    {
87
0
        GDALDataset::ReportUpdateNotSupportedByDriver("MiraMonVector");
88
0
        return nullptr;
89
0
    }
90
91
1.44k
    return poDS.release();
92
1.44k
}
93
94
/****************************************************************************/
95
/*                         OGRMiraMonDriverCreate()                              */
96
/****************************************************************************/
97
98
static GDALDataset *
99
OGRMiraMonDriverCreate(const char *pszName, CPL_UNUSED int /*nBands*/,
100
                       CPL_UNUSED int /*nXSize*/, CPL_UNUSED int /*nYSize*/,
101
                       CPL_UNUSED GDALDataType /*eDT*/, char **papszOptions)
102
333
{
103
333
    auto poDS = std::make_unique<OGRMiraMonDataSource>();
104
105
333
    if (!poDS->Create(pszName, papszOptions))
106
0
    {
107
0
        poDS.reset();
108
0
    }
109
110
333
    return poDS.release();
111
333
}
112
113
/****************************************************************************/
114
/*                           RegisterOGRMM()                                */
115
/****************************************************************************/
116
117
void RegisterOGRMiraMon()
118
119
24
{
120
24
    if (GDALGetDriverByName("MiraMonVector") != nullptr)
121
0
        return;
122
123
24
    GDALDriver *poDriver = new GDALDriver();
124
24
    poDriver->SetDescription("MiraMonVector");
125
24
    poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
126
24
    poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
127
24
    poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
128
24
    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
129
24
                              "MiraMon Vectors (.pol, .arc, .pnt)");
130
24
    poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "pol arc pnt");
131
24
    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
132
24
                              "drivers/vector/miramon.html");
133
24
    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
134
24
    poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
135
136
24
    poDriver->SetMetadataItem(
137
24
        GDAL_DMD_OPENOPTIONLIST,
138
24
        "<OpenOptionList>"
139
24
        "  <Option name='Height' scope='vector' type='string-select' "
140
24
        "   description='Sets which of the possible heights is chosen: "
141
24
        "the first, the highest or the lowest one.'>"
142
24
        "    <Value>First</Value>"
143
24
        "    <Value>Lowest</Value>"
144
24
        "    <Value>Highest</Value>"
145
24
        "  </Option>"
146
24
        "  <Option name='MultiRecordIndex' scope='vector' type='string' "
147
24
        "   description='Sets which of the possible records is chosen: "
148
24
        "0, 1, 2,... or the Last one. Use JSON when a serialized "
149
24
        "JSON is wanted'>"
150
24
        "  </Option>"
151
24
        "  <Option name='OpenLanguage' scope='vector' type='string-select' "
152
24
        "   description='If the layer to be opened is multilingual "
153
24
        "(in fact the *.rel* file), this parameter sets the language "
154
24
        "to be read.'>"
155
24
        "    <Value>ENG</Value>"
156
24
        "    <Value>CAT</Value>"
157
24
        "    <Value>SPA</Value>"
158
24
        "  </Option>"
159
24
        "</OpenOptionList>");
160
161
24
    poDriver->SetMetadataItem(
162
24
        GDAL_DS_LAYER_CREATIONOPTIONLIST,
163
24
        "<LayerCreationOptionList>"
164
24
        "  <Option name='Version' type='string-select' description='Version of "
165
24
        "the file. "
166
24
        "V1.1 is a limited 32 bits for FID and for internal offsets. "
167
24
        "V2.0 is the 64 bits version, with practically no limits for FID nor "
168
24
        "for internal offsets.' "
169
24
        "default='last_version'>"
170
24
        "<Value>V1.1</Value>"
171
24
        "<Value>V2.0</Value>"
172
24
        "<Value>last_version</Value>"
173
24
        "</Option>"
174
24
        "  <Option name='DBFEncoding' type='string-select' "
175
24
        "description='Encoding of "
176
24
        "the "
177
24
        ".dbf files."
178
24
        "MiraMon can write *.dbf* files in these two charsets.' "
179
24
        "default='ANSI'>"
180
24
        "<Value>UTF8</Value>"
181
24
        "<Value>ANSI</Value>"
182
24
        "</Option>"
183
24
        "  <Option name='CreationLanguage' scope='vector' type='string-select' "
184
24
        "   description='If the layer to be opened is multilingual "
185
24
        "(in fact the *.rel* file), this parameter sets the language "
186
24
        "to be read.'>"
187
24
        "    <Value>ENG</Value>"
188
24
        "    <Value>CAT</Value>"
189
24
        "    <Value>SPA</Value>"
190
24
        "  </Option>"
191
24
        "</LayerCreationOptionList>");
192
193
24
    poDriver->SetMetadataItem(
194
24
        GDAL_DMD_CREATIONFIELDDATATYPES,
195
24
        "Integer Integer64 Real String Date Time "
196
24
        "Binary IntegerList Integer64List RealList StringList");
197
24
    poDriver->pfnOpen = OGRMiraMonDriverOpen;
198
24
    poDriver->pfnIdentify = OGRMiraMonDriverIdentify;
199
24
    poDriver->pfnCreate = OGRMiraMonDriverCreate;
200
201
24
    GetGDALDriverManager()->RegisterDriver(poDriver);
202
24
}