Coverage Report

Created: 2025-12-31 08:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/jml/ogrjmldataset.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  JML Translator
4
 * Purpose:  Implements OGRJMLDataset class
5
 * Author:   Even Rouault, even dot rouault at spatialys dot com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys dot com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "cpl_conv.h"
14
#include "cpl_string.h"
15
#include "ogr_jml.h"
16
#include "ogrsf_frmts.h"
17
18
// g++ -DHAVE_EXPAT -fPIC -shared -Wall -g -DDEBUG ogr/ogrsf_frmts/jml/*.cpp -o
19
// ogr_JML.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/jml -L.
20
// -lgdal
21
22
/************************************************************************/
23
/*                          OGRJMLDataset()                             */
24
/************************************************************************/
25
26
OGRJMLDataset::OGRJMLDataset()
27
1.09k
    : poLayer(nullptr), fp(nullptr), bWriteMode(false)
28
1.09k
{
29
1.09k
}
30
31
/************************************************************************/
32
/*                         ~OGRJMLDataset()                             */
33
/************************************************************************/
34
35
OGRJMLDataset::~OGRJMLDataset()
36
37
1.09k
{
38
1.09k
    delete poLayer;
39
40
1.09k
    if (fp != nullptr)
41
1.09k
        VSIFCloseL(fp);
42
1.09k
}
43
44
/************************************************************************/
45
/*                           TestCapability()                           */
46
/************************************************************************/
47
48
int OGRJMLDataset::TestCapability(const char *pszCap) const
49
50
168
{
51
168
    if (EQUAL(pszCap, ODsCCreateLayer))
52
56
        return bWriteMode && poLayer == nullptr;
53
112
    if (EQUAL(pszCap, ODsCZGeometries))
54
0
        return true;
55
56
112
    return false;
57
112
}
58
59
/************************************************************************/
60
/*                              GetLayer()                              */
61
/************************************************************************/
62
63
const OGRLayer *OGRJMLDataset::GetLayer(int iLayer) const
64
65
1.56k
{
66
1.56k
    if (iLayer != 0)
67
0
        return nullptr;
68
69
1.56k
    return poLayer;
70
1.56k
}
71
72
/************************************************************************/
73
/*                            Identify()                                */
74
/************************************************************************/
75
76
int OGRJMLDataset::Identify(GDALOpenInfo *poOpenInfo)
77
77.1k
{
78
77.1k
    return poOpenInfo->nHeaderBytes != 0 &&
79
44.5k
           strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader),
80
44.5k
                  "<JCSDataFile") != nullptr;
81
77.1k
}
82
83
/************************************************************************/
84
/*                                Open()                                */
85
/************************************************************************/
86
87
GDALDataset *OGRJMLDataset::Open(GDALOpenInfo *poOpenInfo)
88
89
1.03k
{
90
1.03k
    if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr ||
91
1.03k
        poOpenInfo->eAccess == GA_Update)
92
0
        return nullptr;
93
94
#ifndef HAVE_EXPAT
95
    CPLError(CE_Failure, CPLE_NotSupported,
96
             "OGR/JML driver has not been built with read support. "
97
             "Expat library required");
98
    return nullptr;
99
#else
100
1.03k
    OGRJMLDataset *poDS = new OGRJMLDataset();
101
1.03k
    poDS->SetDescription(poOpenInfo->pszFilename);
102
103
1.03k
    poDS->fp = poOpenInfo->fpL;
104
1.03k
    poOpenInfo->fpL = nullptr;
105
106
1.03k
    poDS->poLayer = new OGRJMLLayer(
107
1.03k
        CPLGetBasenameSafe(poOpenInfo->pszFilename).c_str(), poDS, poDS->fp);
108
109
1.03k
    return poDS;
110
1.03k
#endif
111
1.03k
}
112
113
/************************************************************************/
114
/*                               Create()                               */
115
/************************************************************************/
116
117
GDALDataset *OGRJMLDataset::Create(const char *pszFilename, int /* nXSize */,
118
                                   int /* nYSize */, int /* nBands */,
119
                                   GDALDataType /* eDT */,
120
                                   char ** /* papszOptions */)
121
56
{
122
56
    if (strcmp(pszFilename, "/dev/stdout") == 0)
123
0
        pszFilename = "/vsistdout/";
124
125
    /* -------------------------------------------------------------------- */
126
    /*     Do not override exiting file.                                    */
127
    /* -------------------------------------------------------------------- */
128
56
    VSIStatBufL sStatBuf;
129
130
56
    if (VSIStatL(pszFilename, &sStatBuf) == 0)
131
0
    {
132
0
        CPLError(CE_Failure, CPLE_NotSupported,
133
0
                 "You have to delete %s before being able to create it "
134
0
                 "with the JML driver",
135
0
                 pszFilename);
136
0
        return nullptr;
137
0
    }
138
139
56
    OGRJMLDataset *poDS = new OGRJMLDataset();
140
141
    /* -------------------------------------------------------------------- */
142
    /*      Create the output file.                                         */
143
    /* -------------------------------------------------------------------- */
144
56
    poDS->bWriteMode = true;
145
56
    poDS->SetDescription(pszFilename);
146
147
56
    poDS->fp = VSIFOpenL(pszFilename, "w");
148
56
    if (poDS->fp == nullptr)
149
0
    {
150
0
        CPLError(CE_Failure, CPLE_OpenFailed, "Failed to create JML file %s.",
151
0
                 pszFilename);
152
0
        delete poDS;
153
0
        return nullptr;
154
0
    }
155
156
56
    return poDS;
157
56
}
158
159
/************************************************************************/
160
/*                           ICreateLayer()                             */
161
/************************************************************************/
162
163
OGRLayer *OGRJMLDataset::ICreateLayer(const char *pszLayerName,
164
                                      const OGRGeomFieldDefn *poGeomFieldDefn,
165
                                      CSLConstList papszOptions)
166
56
{
167
56
    if (!bWriteMode || poLayer != nullptr)
168
0
        return nullptr;
169
170
56
    bool bAddRGBField = CPLTestBool(
171
56
        CSLFetchNameValueDef(papszOptions, "CREATE_R_G_B_FIELD", "YES"));
172
56
    bool bAddOGRStyleField = CPLTestBool(
173
56
        CSLFetchNameValueDef(papszOptions, "CREATE_OGR_STYLE_FIELD", "NO"));
174
56
    bool bClassicGML =
175
56
        CPLTestBool(CSLFetchNameValueDef(papszOptions, "CLASSIC_GML", "NO"));
176
56
    OGRSpatialReference *poSRSClone = nullptr;
177
56
    const auto poSRS =
178
56
        poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
179
56
    if (poSRS)
180
0
    {
181
0
        poSRSClone = poSRS->Clone();
182
0
        poSRSClone->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
183
0
    }
184
56
    poLayer =
185
56
        new OGRJMLWriterLayer(pszLayerName, poSRSClone, this, fp, bAddRGBField,
186
56
                              bAddOGRStyleField, bClassicGML);
187
56
    if (poSRSClone)
188
0
        poSRSClone->Release();
189
190
56
    return poLayer;
191
56
}
192
193
/************************************************************************/
194
/*                         RegisterOGRJML()                             */
195
/************************************************************************/
196
197
void RegisterOGRJML()
198
22
{
199
22
    if (GDALGetDriverByName("JML") != nullptr)
200
0
        return;
201
202
22
    GDALDriver *poDriver = new GDALDriver();
203
204
22
    poDriver->SetDescription("JML");
205
22
    poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
206
22
    poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
207
22
    poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
208
22
    poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
209
22
    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "OpenJUMP JML");
210
22
    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "jml");
211
22
    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/jml.html");
212
213
22
    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
214
22
    poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES, "YES");
215
22
    poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_READ, "YES");
216
22
    poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_WRITE, "YES");
217
22
    poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
218
219
22
    poDriver->SetMetadataItem(
220
22
        GDAL_DS_LAYER_CREATIONOPTIONLIST,
221
22
        "<LayerCreationOptionList>"
222
22
        "   <Option name='CREATE_R_G_B_FIELD' type='boolean' "
223
22
        "description='Whether to create a R_G_B field' default='YES'/>"
224
22
        "   <Option name='CREATE_OGR_STYLE_FIELD' type='boolean' "
225
22
        "description='Whether to create a OGR_STYLE field' default='NO'/>"
226
22
        "</LayerCreationOptionList>");
227
228
22
    poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
229
22
                              "<CreationOptionList/>");
230
231
22
    poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES,
232
22
                              "Integer Integer64 Real String Date DateTime");
233
234
22
    poDriver->pfnOpen = OGRJMLDataset::Open;
235
22
    poDriver->pfnIdentify = OGRJMLDataset::Identify;
236
22
    poDriver->pfnCreate = OGRJMLDataset::Create;
237
238
22
    GetGDALDriverManager()->RegisterDriver(poDriver);
239
22
}