Coverage Report

Created: 2025-11-16 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  The OGRSFDriverRegistrar class implementation.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 1999,  Les Technologies SoftMap Inc.
9
 * Copyright (c) 2008-2012, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "ogrsf_frmts.h"
15
#include "ogr_api.h"
16
#include "ograpispy.h"
17
18
/************************************************************************/
19
/*                         OGRSFDriverRegistrar                         */
20
/************************************************************************/
21
22
/**
23
 * \brief Constructor
24
 *
25
 * Normally the driver registrar is constructed by the
26
 * OGRSFDriverRegistrar::GetRegistrar() accessor which ensures singleton
27
 * status.
28
 */
29
30
OGRSFDriverRegistrar::OGRSFDriverRegistrar()
31
0
{
32
0
}
33
34
/************************************************************************/
35
/*                       ~OGRSFDriverRegistrar()                        */
36
/************************************************************************/
37
38
OGRSFDriverRegistrar::~OGRSFDriverRegistrar()
39
0
{
40
0
}
41
42
//! @cond Doxygen_Suppress
43
/************************************************************************/
44
/*                           GetRegistrar()                             */
45
/************************************************************************/
46
47
OGRSFDriverRegistrar *OGRSFDriverRegistrar::GetRegistrar()
48
0
{
49
0
    static OGRSFDriverRegistrar oSingleton;
50
0
    return &oSingleton;
51
0
}
52
53
//! @endcond
54
55
/************************************************************************/
56
/*                           OGRCleanupAll()                            */
57
/************************************************************************/
58
59
/**
60
 * \brief Cleanup all OGR related resources.
61
 *
62
 * \see GDALDestroy()
63
 * \deprecated Use GDALDestroy() instead
64
 */
65
void OGRCleanupAll()
66
67
0
{
68
0
    GDALDestroyDriverManager();
69
0
}
70
71
/************************************************************************/
72
/*                              OGROpen()                               */
73
/************************************************************************/
74
75
/**
76
  \brief Open a file / data source with one of the registered drivers.
77
78
  This function loops through all the drivers registered with the driver
79
  manager trying each until one succeeds with the given data source.
80
81
  If this function fails, CPLGetLastErrorMsg() can be used to check if there
82
  is an error message explaining why.
83
84
  For drivers supporting the VSI virtual file API, it is possible to open
85
  a file in a .zip archive (see VSIInstallZipFileHandler()), in a .tar/.tar.gz/.tgz archive
86
  (see VSIInstallTarFileHandler()) or on a HTTP / FTP server (see VSIInstallCurlFileHandler())
87
88
  NOTE: It is *NOT* safe to cast the returned handle to
89
  OGRDataSource*. If a C++ object is needed, the handle should be cast to GDALDataset*.
90
  Similarly, the returned OGRSFDriverH handle should be cast to GDALDriver*, and
91
  *NOT* OGRSFDriver*.
92
93
  @deprecated Use GDALOpenEx()
94
95
  @param pszName the name of the file, or data source to open.
96
  @param bUpdate FALSE for read-only access (the default) or TRUE for
97
         read-write access.
98
  @param pahDriverList if non-NULL, this argument will be updated with a
99
         pointer to the driver which was used to open the data source.
100
101
  @return NULL on error or if the pass name is not supported by this driver,
102
  otherwise a handle to a GDALDataset.  This GDALDataset should be
103
  closed by deleting the object when it is no longer needed.
104
105
  Example:
106
107
  \code{.cpp}
108
    OGRDataSourceH hDS;
109
    OGRSFDriverH *pahDriver;
110
111
    hDS = OGROpen( "polygon.shp", 0, pahDriver );
112
    if( hDS == NULL )
113
    {
114
        return;
115
    }
116
117
    ... use the data source ...
118
119
    OGRReleaseDataSource( hDS );
120
  \endcode
121
122
*/
123
124
OGRDataSourceH OGROpen(const char *pszName, int bUpdate,
125
                       OGRSFDriverH *pahDriverList)
126
127
0
{
128
0
    VALIDATE_POINTER1(pszName, "OGROpen", nullptr);
129
130
0
    GDALDatasetH hDS =
131
0
        GDALOpenEx(pszName, GDAL_OF_VECTOR | ((bUpdate) ? GDAL_OF_UPDATE : 0),
132
0
                   nullptr, nullptr, nullptr);
133
0
    if (hDS != nullptr && pahDriverList != nullptr)
134
0
        *pahDriverList =
135
0
            reinterpret_cast<OGRSFDriverH>(GDALGetDatasetDriver(hDS));
136
137
0
    return reinterpret_cast<OGRDataSourceH>(hDS);
138
0
}
139
140
/************************************************************************/
141
/*                           OGROpenShared()                            */
142
/************************************************************************/
143
144
/**
145
  \brief Open a file / data source with one of the registered drivers if not
146
  already opened, or increment reference count of already opened data source
147
  previously opened with OGROpenShared()
148
149
  This function loops through all the drivers registered with the driver
150
  manager trying each until one succeeds with the given data source.
151
152
  If this function fails, CPLGetLastErrorMsg() can be used to check if there
153
  is an error message explaining why.
154
155
  NOTE: It is *NOT* safe to cast the returned handle to
156
  OGRDataSource*. If a C++ object is needed, the handle should be cast to GDALDataset*.
157
  Similarly, the returned OGRSFDriverH handle should be cast to GDALDriver*, and
158
  *NOT* OGRSFDriver*.
159
160
  @deprecated Use GDALOpenEx()
161
162
  @param pszName the name of the file, or data source to open.
163
  @param bUpdate FALSE for read-only access (the default) or TRUE for
164
         read-write access.
165
  @param pahDriverList if non-NULL, this argument will be updated with a
166
         pointer to the driver which was used to open the data source.
167
168
  @return NULL on error or if the pass name is not supported by this driver,
169
  otherwise a handle to a GDALDataset.  This GDALDataset should be
170
  closed by deleting the object when it is no longer needed.
171
172
  Example:
173
174
  \code{.cpp}
175
    OGRDataSourceH  hDS;
176
    OGRSFDriverH        *pahDriver;
177
178
    hDS = OGROpenShared( "polygon.shp", 0, pahDriver );
179
    if( hDS == NULL )
180
    {
181
        return;
182
    }
183
184
    ... use the data source ...
185
186
    OGRReleaseDataSource( hDS );
187
  \endcode
188
189
*/
190
OGRDataSourceH OGROpenShared(const char *pszName, int bUpdate,
191
                             OGRSFDriverH *pahDriverList)
192
193
0
{
194
0
    VALIDATE_POINTER1(pszName, "OGROpenShared", nullptr);
195
196
0
    GDALDatasetH hDS = GDALOpenEx(
197
0
        pszName,
198
0
        GDAL_OF_VECTOR | ((bUpdate) ? GDAL_OF_UPDATE : 0) | GDAL_OF_SHARED,
199
0
        nullptr, nullptr, nullptr);
200
0
    if (hDS != nullptr && pahDriverList != nullptr)
201
0
        *pahDriverList =
202
0
            reinterpret_cast<OGRSFDriverH>(GDALGetDatasetDriver(hDS));
203
0
    return reinterpret_cast<OGRDataSourceH>(hDS);
204
0
}
205
206
/************************************************************************/
207
/*                        OGRReleaseDataSource()                        */
208
/************************************************************************/
209
210
/**
211
\brief Drop a reference to this datasource, and if the reference count drops to zero close (destroy) the datasource.
212
213
Internally this actually calls
214
the OGRSFDriverRegistrar::ReleaseDataSource() method.  This method is
215
essentially a convenient alias.
216
217
@deprecated Use GDALClose()
218
219
@param hDS handle to the data source to release
220
221
@return OGRERR_NONE on success or an error code.
222
*/
223
224
OGRErr OGRReleaseDataSource(OGRDataSourceH hDS)
225
226
0
{
227
0
    VALIDATE_POINTER1(hDS, "OGRReleaseDataSource", OGRERR_INVALID_HANDLE);
228
229
0
    GDALClose(reinterpret_cast<GDALDatasetH>(hDS));
230
231
0
    return OGRERR_NONE;
232
0
}
233
234
//! @cond Doxygen_Suppress
235
/************************************************************************/
236
/*                           GetOpenDSCount()                           */
237
/************************************************************************/
238
239
int OGRSFDriverRegistrar::GetOpenDSCount()
240
0
{
241
0
    CPLError(CE_Failure, CPLE_AppDefined, "Stub implementation");
242
0
    return 0;
243
0
}
244
245
/************************************************************************/
246
/*                         OGRGetOpenDSCount()                          */
247
/************************************************************************/
248
249
int OGRGetOpenDSCount()
250
251
0
{
252
0
    return OGRSFDriverRegistrar::GetRegistrar()->GetOpenDSCount();
253
0
}
254
255
/************************************************************************/
256
/*                             GetOpenDS()                              */
257
/************************************************************************/
258
259
OGRDataSource *OGRSFDriverRegistrar::GetOpenDS(CPL_UNUSED int iDS)
260
0
{
261
0
    CPLError(CE_Failure, CPLE_AppDefined, "Stub implementation");
262
0
    return nullptr;
263
0
}
264
265
/************************************************************************/
266
/*                            OGRGetOpenDS()                            */
267
/************************************************************************/
268
269
OGRDataSourceH OGRGetOpenDS(int iDS)
270
271
0
{
272
0
    return reinterpret_cast<OGRDataSourceH>(
273
0
        OGRSFDriverRegistrar::GetRegistrar()->GetOpenDS(iDS));
274
0
}
275
276
/************************************************************************/
277
/*                          OpenWithDriverArg()                         */
278
/************************************************************************/
279
280
GDALDataset *OGRSFDriverRegistrar::OpenWithDriverArg(GDALDriver *poDriver,
281
                                                     GDALOpenInfo *poOpenInfo)
282
0
{
283
0
    OGRDataSource *poDS = reinterpret_cast<OGRDataSource *>(
284
0
        reinterpret_cast<OGRSFDriver *>(poDriver)->Open(
285
0
            poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update));
286
0
    if (poDS != nullptr)
287
0
        poDS->SetDescription(poDS->GetName());
288
0
    return poDS;
289
0
}
290
291
/************************************************************************/
292
/*                          CreateVectorOnly()                          */
293
/************************************************************************/
294
295
GDALDataset *OGRSFDriverRegistrar::CreateVectorOnly(GDALDriver *poDriver,
296
                                                    const char *pszName,
297
                                                    char **papszOptions)
298
0
{
299
0
    OGRDataSource *poDS = reinterpret_cast<OGRDataSource *>(
300
0
        reinterpret_cast<OGRSFDriver *>(poDriver)->CreateDataSource(
301
0
            pszName, papszOptions));
302
0
    if (poDS != nullptr && poDS->GetName() != nullptr)
303
0
        poDS->SetDescription(poDS->GetName());
304
0
    return poDS;
305
0
}
306
307
/************************************************************************/
308
/*                          DeleteDataSource()                          */
309
/************************************************************************/
310
311
CPLErr OGRSFDriverRegistrar::DeleteDataSource(GDALDriver *poDriver,
312
                                              const char *pszName)
313
0
{
314
0
    if (reinterpret_cast<OGRSFDriver *>(poDriver)->DeleteDataSource(pszName) ==
315
0
        OGRERR_NONE)
316
0
        return CE_None;
317
0
    else
318
0
        return CE_Failure;
319
0
}
320
321
/************************************************************************/
322
/*                           RegisterDriver()                           */
323
/************************************************************************/
324
325
void OGRSFDriverRegistrar::RegisterDriver(OGRSFDriver *poDriver)
326
327
0
{
328
0
    GDALDriver *poGDALDriver =
329
0
        GDALDriver::FromHandle(GDALGetDriverByName(poDriver->GetName()));
330
0
    if (poGDALDriver == nullptr)
331
0
    {
332
0
        poDriver->SetDescription(poDriver->GetName());
333
0
        poDriver->SetMetadataItem("OGR_DRIVER", "YES");
334
335
0
        if (poDriver->GetMetadataItem(GDAL_DMD_LONGNAME) == nullptr)
336
0
            poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, poDriver->GetName());
337
338
0
        poDriver->pfnOpenWithDriverArg = OpenWithDriverArg;
339
340
0
        if (poDriver->TestCapability(ODrCCreateDataSource))
341
0
        {
342
0
            poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
343
0
            poDriver->pfnCreateVectorOnly = CreateVectorOnly;
344
0
        }
345
0
        if (poDriver->TestCapability(ODrCDeleteDataSource))
346
0
        {
347
0
            poDriver->pfnDeleteDataSource = DeleteDataSource;
348
0
        }
349
350
0
        poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
351
352
0
        GetGDALDriverManager()->RegisterDriver(poDriver);
353
0
    }
354
0
    else
355
0
    {
356
0
        if (poGDALDriver->GetMetadataItem("OGR_DRIVER") == nullptr)
357
0
        {
358
0
            CPLError(CE_Failure, CPLE_AppDefined,
359
0
                     "A non OGR driver is registered with the same name: %s",
360
0
                     poDriver->GetName());
361
0
        }
362
0
        delete poDriver;
363
0
    }
364
0
}
365
366
/************************************************************************/
367
/*                         OGRRegisterDriver()                          */
368
/************************************************************************/
369
370
void OGRRegisterDriver(OGRSFDriverH hDriver)
371
372
0
{
373
0
    VALIDATE_POINTER0(hDriver, "OGRRegisterDriver");
374
375
0
    GetGDALDriverManager()->RegisterDriver(GDALDriver::FromHandle(hDriver));
376
0
}
377
378
/************************************************************************/
379
/*                        OGRDeregisterDriver()                         */
380
/************************************************************************/
381
382
void OGRDeregisterDriver(OGRSFDriverH hDriver)
383
384
0
{
385
0
    VALIDATE_POINTER0(hDriver, "OGRDeregisterDriver");
386
387
0
    GetGDALDriverManager()->DeregisterDriver(GDALDriver::FromHandle(hDriver));
388
0
}
389
390
/************************************************************************/
391
/*                           GetDriverCount()                           */
392
/************************************************************************/
393
394
int OGRSFDriverRegistrar::GetDriverCount()
395
396
0
{
397
    /* We must be careful only to return drivers that are actual OGRSFDriver* */
398
0
    GDALDriverManager *poDriverManager = GetGDALDriverManager();
399
0
    int nTotal = poDriverManager->GetDriverCount();
400
0
    int nOGRDriverCount = 0;
401
0
    for (int i = 0; i < nTotal; i++)
402
0
    {
403
0
        GDALDriver *poDriver = poDriverManager->GetDriver(i);
404
0
        if (poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) != nullptr)
405
0
            nOGRDriverCount++;
406
0
    }
407
0
    return nOGRDriverCount;
408
0
}
409
410
//! @endcond
411
412
/************************************************************************/
413
/*                         OGRGetDriverCount()                          */
414
/************************************************************************/
415
416
/**
417
  \brief Fetch the number of registered drivers.
418
419
  @deprecated Use GDALGetDriverCount()
420
421
  @return the drivers count.
422
423
*/
424
int OGRGetDriverCount()
425
426
0
{
427
0
    return OGRSFDriverRegistrar::GetRegistrar()->GetDriverCount();
428
0
}
429
430
/************************************************************************/
431
/*                             GetDriver()                              */
432
/************************************************************************/
433
434
//! @cond Doxygen_Suppress
435
GDALDriver *OGRSFDriverRegistrar::GetDriver(int iDriver)
436
437
0
{
438
    /* We must be careful only to return drivers that are actual OGRSFDriver* */
439
0
    GDALDriverManager *poDriverManager = GetGDALDriverManager();
440
0
    int nTotal = poDriverManager->GetDriverCount();
441
0
    int nOGRDriverCount = 0;
442
0
    for (int i = 0; i < nTotal; i++)
443
0
    {
444
0
        GDALDriver *poDriver = poDriverManager->GetDriver(i);
445
0
        if (poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) != nullptr)
446
0
        {
447
0
            if (nOGRDriverCount == iDriver)
448
0
                return poDriver;
449
0
            nOGRDriverCount++;
450
0
        }
451
0
    }
452
0
    return nullptr;
453
0
}
454
455
//! @endcond
456
457
/************************************************************************/
458
/*                            OGRGetDriver()                            */
459
/************************************************************************/
460
461
/**
462
  \brief Fetch the indicated driver.
463
464
  NOTE: It is *NOT* safe to cast the returned handle to
465
  OGRSFDriver*. If a C++ object is needed, the handle should be cast to GDALDriver*.
466
467
  @deprecated Use GDALGetDriver()
468
469
  @param iDriver the driver index, from 0 to GetDriverCount()-1.
470
471
  @return handle to the driver, or NULL if iDriver is out of range.
472
473
*/
474
475
OGRSFDriverH OGRGetDriver(int iDriver)
476
477
0
{
478
0
    return reinterpret_cast<OGRSFDriverH>(
479
0
        OGRSFDriverRegistrar::GetRegistrar()->GetDriver(iDriver));
480
0
}
481
482
/************************************************************************/
483
/*                          GetDriverByName()                           */
484
/************************************************************************/
485
486
//! @cond Doxygen_Suppress
487
GDALDriver *OGRSFDriverRegistrar::GetDriverByName(const char *pszName)
488
489
0
{
490
0
    GDALDriverManager *poDriverManager = GetGDALDriverManager();
491
0
    GDALDriver *poGDALDriver =
492
0
        poDriverManager->GetDriverByName(CPLSPrintf("OGR_%s", pszName));
493
0
    if (poGDALDriver == nullptr)
494
0
        poGDALDriver = poDriverManager->GetDriverByName(pszName);
495
0
    if (poGDALDriver == nullptr ||
496
0
        poGDALDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
497
0
        return nullptr;
498
0
    return poGDALDriver;
499
0
}
500
501
//! @endcond
502
503
/************************************************************************/
504
/*                         OGRGetDriverByName()                         */
505
/************************************************************************/
506
507
/**
508
  \brief Fetch the indicated driver.
509
510
  NOTE: It is *NOT* safe to cast the returned handle to
511
  OGRSFDriver*. If a C++ object is needed, the handle should be cast to GDALDriver*.
512
513
  @deprecated Use GDALGetDriverByName()
514
515
  @param pszName the driver name
516
517
  @return the driver, or NULL if no driver with that name is found
518
*/
519
520
OGRSFDriverH OGRGetDriverByName(const char *pszName)
521
522
0
{
523
0
    VALIDATE_POINTER1(pszName, "OGRGetDriverByName", nullptr);
524
525
0
    return reinterpret_cast<OGRSFDriverH>(
526
0
        OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszName));
527
0
}