/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 | } |