Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Core
4 : * Purpose: Base class for raster file formats.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 1998, 2003, Frank Warmerdam
9 : * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_port.h"
15 : #include "gdal.h"
16 : #include "gdal_priv.h"
17 :
18 : #include <climits>
19 : #include <cstdarg>
20 : #include <cstdio>
21 : #include <cstdlib>
22 : #include <cstring>
23 : #include <algorithm>
24 : #include <map>
25 : #include <mutex>
26 : #include <new>
27 : #include <set>
28 : #include <string>
29 : #include <utility>
30 :
31 : #include "cpl_conv.h"
32 : #include "cpl_error.h"
33 : #include "cpl_hash_set.h"
34 : #include "cpl_multiproc.h"
35 : #include "cpl_progress.h"
36 : #include "cpl_string.h"
37 : #include "cpl_vsi.h"
38 : #include "cpl_vsi_error.h"
39 : #include "gdal_alg.h"
40 : #include "ogr_api.h"
41 : #include "ogr_attrind.h"
42 : #include "ogr_core.h"
43 : #include "ogr_feature.h"
44 : #include "ogr_featurestyle.h"
45 : #include "ogr_gensql.h"
46 : #include "ogr_geometry.h"
47 : #include "ogr_p.h"
48 : #include "ogr_spatialref.h"
49 : #include "ogr_srs_api.h"
50 : #include "ograpispy.h"
51 : #include "ogrsf_frmts.h"
52 : #include "ogrunionlayer.h"
53 : #include "ogr_swq.h"
54 :
55 : #include "../frmts/derived/derivedlist.h"
56 :
57 : #ifdef SQLITE_ENABLED
58 : #include "../sqlite/ogrsqliteexecutesql.h"
59 : #endif
60 :
61 : extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
62 :
63 : CPL_C_START
64 : GDALAsyncReader *GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff,
65 : int nYOff, int nXSize, int nYSize,
66 : void *pBuf, int nBufXSize,
67 : int nBufYSize, GDALDataType eBufType,
68 : int nBandCount, int *panBandMap,
69 : int nPixelSpace, int nLineSpace,
70 : int nBandSpace, char **papszOptions);
71 : CPL_C_END
72 :
73 : enum class GDALAllowReadWriteMutexState
74 : {
75 : RW_MUTEX_STATE_UNKNOWN,
76 : RW_MUTEX_STATE_ALLOWED,
77 : RW_MUTEX_STATE_DISABLED
78 : };
79 :
80 : const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
81 : const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
82 :
83 : class GDALDataset::Private
84 : {
85 : CPL_DISALLOW_COPY_ASSIGN(Private)
86 :
87 : public:
88 : CPLMutex *hMutex = nullptr;
89 : std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
90 : #ifdef DEBUG_EXTRA
91 : std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
92 : #endif
93 : GDALAllowReadWriteMutexState eStateReadWriteMutex =
94 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
95 : int nCurrentLayerIdx = 0;
96 : int nLayerCount = -1;
97 : GIntBig nFeatureReadInLayer = 0;
98 : GIntBig nFeatureReadInDataset = 0;
99 : GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
100 : GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
101 : OGRLayer *poCurrentLayer = nullptr;
102 :
103 : std::mutex m_oMutexWKT{};
104 :
105 : char *m_pszWKTCached = nullptr;
106 : OGRSpatialReference *m_poSRSCached = nullptr;
107 : char *m_pszWKTGCPCached = nullptr;
108 : OGRSpatialReference *m_poSRSGCPCached = nullptr;
109 :
110 : GDALDataset *poParentDataset = nullptr;
111 :
112 : bool m_bOverviewsEnabled = true;
113 :
114 : std::vector<int>
115 : m_anBandMap{}; // used by RasterIO(). Values are 1, 2, etc.
116 :
117 130306 : Private() = default;
118 : };
119 :
120 : struct SharedDatasetCtxt
121 : {
122 : // PID of the thread that mark the dataset as shared
123 : // This may not be the actual PID, but the responsiblePID.
124 : GIntBig nPID;
125 : char *pszDescription;
126 : char *pszConcatenatedOpenOptions;
127 : int nOpenFlags;
128 :
129 : GDALDataset *poDS;
130 : };
131 :
132 : // Set of datasets opened as shared datasets (with GDALOpenShared)
133 : // The values in the set are of type SharedDatasetCtxt.
134 : static CPLHashSet *phSharedDatasetSet = nullptr;
135 :
136 : // Set of all datasets created in the constructor of GDALDataset.
137 : // In the case of a shared dataset, memorize the PID of the thread
138 : // that marked the dataset as shared, so that we can remove it from
139 : // the phSharedDatasetSet in the destructor of the dataset, even
140 : // if GDALClose is called from a different thread.
141 : static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
142 :
143 : static CPLMutex *hDLMutex = nullptr;
144 :
145 : // Static array of all datasets. Used by GDALGetOpenDatasets.
146 : // Not thread-safe. See GDALGetOpenDatasets.
147 : static GDALDataset **ppDatasets = nullptr;
148 :
149 8363 : static unsigned long GDALSharedDatasetHashFunc(const void *elt)
150 : {
151 8363 : const SharedDatasetCtxt *psStruct =
152 : static_cast<const SharedDatasetCtxt *>(elt);
153 : return static_cast<unsigned long>(
154 8363 : CPLHashSetHashStr(psStruct->pszDescription) ^
155 8363 : CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^
156 8363 : psStruct->nOpenFlags ^ psStruct->nPID);
157 : }
158 :
159 6978 : static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)
160 : {
161 6978 : const SharedDatasetCtxt *psStruct1 =
162 : static_cast<const SharedDatasetCtxt *>(elt1);
163 6978 : const SharedDatasetCtxt *psStruct2 =
164 : static_cast<const SharedDatasetCtxt *>(elt2);
165 13863 : return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
166 6885 : strcmp(psStruct1->pszConcatenatedOpenOptions,
167 6885 : psStruct2->pszConcatenatedOpenOptions) == 0 &&
168 20748 : psStruct1->nPID == psStruct2->nPID &&
169 13863 : psStruct1->nOpenFlags == psStruct2->nOpenFlags;
170 : }
171 :
172 390 : static void GDALSharedDatasetFreeFunc(void *elt)
173 : {
174 390 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
175 390 : CPLFree(psStruct->pszDescription);
176 390 : CPLFree(psStruct->pszConcatenatedOpenOptions);
177 390 : CPLFree(psStruct);
178 390 : }
179 :
180 : static std::string
181 7040 : GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)
182 : {
183 7040 : std::string osStr;
184 7053 : for (const char *pszOption : cpl::Iterate(papszOpenOptions))
185 13 : osStr += pszOption;
186 7040 : return osStr;
187 : }
188 :
189 : /************************************************************************/
190 : /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
191 : /************************************************************************/
192 :
193 : // The open-shared mutex must be used by the ProxyPool too.
194 61651 : CPLMutex **GDALGetphDLMutex()
195 : {
196 61651 : return &hDLMutex;
197 : }
198 :
199 : // The current thread will act in the behalf of the thread of PID
200 : // responsiblePID.
201 54296 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
202 : {
203 : GIntBig *pResponsiblePID =
204 54296 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
205 54297 : if (pResponsiblePID == nullptr)
206 : {
207 219 : pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
208 219 : CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
209 : }
210 54297 : *pResponsiblePID = responsiblePID;
211 54297 : }
212 :
213 : // Get the PID of the thread that the current thread will act in the behalf of
214 : // By default : the current thread acts in the behalf of itself.
215 166522 : GIntBig GDALGetResponsiblePIDForCurrentThread()
216 : {
217 : GIntBig *pResponsiblePID =
218 166522 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
219 166446 : if (pResponsiblePID == nullptr)
220 45486 : return CPLGetPID();
221 120960 : return *pResponsiblePID;
222 : }
223 :
224 : /************************************************************************/
225 : /* ==================================================================== */
226 : /* GDALDataset */
227 : /* ==================================================================== */
228 : /************************************************************************/
229 :
230 : /**
231 : * \class GDALDataset "gdal_priv.h"
232 : *
233 : * A dataset encapsulating one or more raster bands. Details are further
234 : * discussed in the <a href="https://gdal.org/user/raster_data_model.html">GDAL
235 : * Raster Data Model</a>.
236 : *
237 : * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
238 : * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
239 : * dataset.
240 : */
241 :
242 : /************************************************************************/
243 : /* GDALDataset() */
244 : /************************************************************************/
245 :
246 : //! @cond Doxygen_Suppress
247 114317 : GDALDataset::GDALDataset()
248 114317 : : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
249 : {
250 114205 : }
251 :
252 130350 : GDALDataset::GDALDataset(int bForceCachedIOIn)
253 130228 : : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
254 130350 : m_poPrivate(new(std::nothrow) GDALDataset::Private)
255 : {
256 130234 : }
257 :
258 : //! @endcond
259 :
260 : /************************************************************************/
261 : /* ~GDALDataset() */
262 : /************************************************************************/
263 :
264 : /**
265 : * \brief Destroy an open GDALDataset.
266 : *
267 : * This is the accepted method of closing a GDAL dataset and deallocating
268 : * all resources associated with it.
269 : *
270 : * Equivalent of the C callable GDALClose(). Except that GDALClose() first
271 : * decrements the reference count, and then closes only if it has dropped to
272 : * zero.
273 : *
274 : * For Windows users, it is not recommended to use the delete operator on the
275 : * dataset object because of known issues when allocating and freeing memory
276 : * across module boundaries. Calling GDALClose() is then a better option.
277 : */
278 :
279 130329 : GDALDataset::~GDALDataset()
280 :
281 : {
282 : // we don't want to report destruction of datasets that
283 : // were never really open or meant as internal
284 130325 : if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))
285 : {
286 61666 : if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
287 207 : CPLDebug("GDAL",
288 : "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
289 207 : GetDescription(), this, static_cast<int>(CPLGetPID()),
290 207 : static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
291 : else
292 61476 : CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
293 : }
294 :
295 130376 : if (IsMarkedSuppressOnClose())
296 : {
297 2120 : if (poDriver == nullptr ||
298 : // Someone issuing Create("foo.tif") on a
299 : // memory driver doesn't expect files with those names to be deleted
300 : // on a file system...
301 : // This is somewhat messy. Ideally there should be a way for the
302 : // driver to overload the default behavior
303 1055 : (!EQUAL(poDriver->GetDescription(), "MEM") &&
304 1031 : !EQUAL(poDriver->GetDescription(), "Memory")))
305 : {
306 1041 : VSIUnlink(GetDescription());
307 : }
308 : }
309 :
310 : /* -------------------------------------------------------------------- */
311 : /* Remove dataset from the "open" dataset list. */
312 : /* -------------------------------------------------------------------- */
313 130332 : if (!bIsInternal)
314 : {
315 124766 : CPLMutexHolderD(&hDLMutex);
316 62383 : if (poAllDatasetMap)
317 : {
318 : std::map<GDALDataset *, GIntBig>::iterator oIter =
319 62383 : poAllDatasetMap->find(this);
320 62383 : CPLAssert(oIter != poAllDatasetMap->end());
321 :
322 62383 : UnregisterFromSharedDataset();
323 :
324 62383 : poAllDatasetMap->erase(oIter);
325 :
326 62383 : if (poAllDatasetMap->empty())
327 : {
328 23765 : delete poAllDatasetMap;
329 23765 : poAllDatasetMap = nullptr;
330 23765 : if (phSharedDatasetSet)
331 : {
332 236 : CPLHashSetDestroy(phSharedDatasetSet);
333 : }
334 23765 : phSharedDatasetSet = nullptr;
335 23765 : CPLFree(ppDatasets);
336 23765 : ppDatasets = nullptr;
337 : }
338 : }
339 : }
340 :
341 : /* -------------------------------------------------------------------- */
342 : /* Destroy the raster bands if they exist. */
343 : /* -------------------------------------------------------------------- */
344 1014330 : for (int i = 0; i < nBands && papoBands != nullptr; ++i)
345 : {
346 883999 : if (papoBands[i] != nullptr)
347 884001 : delete papoBands[i];
348 883998 : papoBands[i] = nullptr;
349 : }
350 :
351 130331 : CPLFree(papoBands);
352 :
353 130331 : if (m_poStyleTable)
354 : {
355 23 : delete m_poStyleTable;
356 23 : m_poStyleTable = nullptr;
357 : }
358 :
359 130331 : if (m_poPrivate != nullptr)
360 : {
361 130332 : if (m_poPrivate->hMutex != nullptr)
362 14856 : CPLDestroyMutex(m_poPrivate->hMutex);
363 :
364 : // coverity[missing_lock]
365 130332 : CPLFree(m_poPrivate->m_pszWKTCached);
366 130331 : if (m_poPrivate->m_poSRSCached)
367 : {
368 0 : m_poPrivate->m_poSRSCached->Release();
369 : }
370 : // coverity[missing_lock]
371 130331 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
372 130328 : if (m_poPrivate->m_poSRSGCPCached)
373 : {
374 0 : m_poPrivate->m_poSRSGCPCached->Release();
375 : }
376 : }
377 :
378 130327 : delete m_poPrivate;
379 :
380 130331 : CSLDestroy(papszOpenOptions);
381 130327 : }
382 :
383 : /************************************************************************/
384 : /* Close() */
385 : /************************************************************************/
386 :
387 : /** Do final cleanup before a dataset is destroyed.
388 : *
389 : * This method is typically called by GDALClose() or the destructor of a
390 : * GDALDataset subclass. It might also be called by C++ users before
391 : * destroying a dataset. It should not be called on a shared dataset whose
392 : * reference count is greater than one.
393 : *
394 : * It gives a last chance to the closing process to return an error code if
395 : * something goes wrong, in particular in creation / update scenarios where
396 : * file write or network communication might occur when finalizing the dataset.
397 : *
398 : * Implementations should be robust to this method to be called several times
399 : * (on subsequent calls, it should do nothing and return CE_None).
400 : * Once it has been called, no other method than Close() or the dataset
401 : * destructor should be called. RasterBand or OGRLayer owned by the dataset
402 : * should be assumed as no longer being valid.
403 : *
404 : * If a driver implements this method, it must also call it from its
405 : * dataset destructor.
406 : *
407 : * A typical implementation might look as the following
408 : * \code{.cpp}
409 : *
410 : * MyDataset::~MyDataset()
411 : * {
412 : * try
413 : * {
414 : * MyDataset::Close();
415 : * }
416 : * catch (const std::exception &exc)
417 : * {
418 : * // If Close() can throw exception
419 : * CPLError(CE_Failure, CPLE_AppDefined,
420 : * "Exception thrown in MyDataset::Close(): %s",
421 : * exc.what());
422 : * }
423 : * catch (...)
424 : * {
425 : * // If Close() can throw exception
426 : * CPLError(CE_Failure, CPLE_AppDefined,
427 : * "Exception thrown in MyDataset::Close()");
428 : * }
429 : * }
430 : *
431 : * CPLErr MyDataset::Close()
432 : * {
433 : * CPLErr eErr = CE_None;
434 : * if( nOpenFlags != OPEN_FLAGS_CLOSED )
435 : * {
436 : * if( MyDataset::FlushCache(true) != CE_None )
437 : * eErr = CE_Failure;
438 : *
439 : * // Do something driver specific
440 : * if (m_fpImage)
441 : * {
442 : * if( VSIFCloseL(m_fpImage) != 0 )
443 : * {
444 : * CPLError(CE_Failure, CPLE_FileIO, "VSIFCloseL() failed");
445 : * eErr = CE_Failure;
446 : * }
447 : * }
448 : *
449 : * // Call parent Close() implementation.
450 : * if( MyParentDatasetClass::Close() != CE_None )
451 : * eErr = CE_Failure;
452 : * }
453 : * return eErr;
454 : * }
455 : * \endcode
456 : *
457 : * @since GDAL 3.7
458 : */
459 76543 : CPLErr GDALDataset::Close()
460 : {
461 : // Call UnregisterFromSharedDataset() before altering nOpenFlags
462 76543 : UnregisterFromSharedDataset();
463 :
464 76544 : nOpenFlags = OPEN_FLAGS_CLOSED;
465 76544 : return CE_None;
466 : }
467 :
468 : /************************************************************************/
469 : /* UnregisterFromSharedDataset() */
470 : /************************************************************************/
471 :
472 138926 : void GDALDataset::UnregisterFromSharedDataset()
473 : {
474 138926 : if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))
475 138536 : return;
476 :
477 780 : CPLMutexHolderD(&hDLMutex);
478 :
479 : std::map<GDALDataset *, GIntBig>::iterator oIter =
480 390 : poAllDatasetMap->find(this);
481 390 : CPLAssert(oIter != poAllDatasetMap->end());
482 390 : const GIntBig nPIDCreatorForShared = oIter->second;
483 390 : bShared = false;
484 : SharedDatasetCtxt sStruct;
485 390 : sStruct.nPID = nPIDCreatorForShared;
486 390 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
487 390 : sStruct.pszDescription = const_cast<char *>(GetDescription());
488 : std::string osConcatenatedOpenOptions =
489 780 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
490 390 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
491 390 : sStruct.poDS = nullptr;
492 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
493 390 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
494 390 : if (psStruct && psStruct->poDS == this)
495 : {
496 389 : CPLHashSetRemove(phSharedDatasetSet, psStruct);
497 : }
498 : else
499 : {
500 1 : CPLDebug("GDAL",
501 : "Should not happen. Cannot find %s, "
502 : "this=%p in phSharedDatasetSet",
503 1 : GetDescription(), this);
504 : }
505 : }
506 :
507 : /************************************************************************/
508 : /* AddToDatasetOpenList() */
509 : /************************************************************************/
510 :
511 63784 : void GDALDataset::AddToDatasetOpenList()
512 : {
513 : /* -------------------------------------------------------------------- */
514 : /* Add this dataset to the open dataset list. */
515 : /* -------------------------------------------------------------------- */
516 63784 : bIsInternal = false;
517 :
518 63784 : CPLMutexHolderD(&hDLMutex);
519 :
520 63784 : if (poAllDatasetMap == nullptr)
521 23775 : poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
522 63784 : (*poAllDatasetMap)[this] = -1;
523 63784 : }
524 :
525 : /************************************************************************/
526 : /* FlushCache() */
527 : /************************************************************************/
528 :
529 : /**
530 : * \brief Flush all write cached data to disk.
531 : *
532 : * Any raster (or other GDAL) data written via GDAL calls, but buffered
533 : * internally will be written to disk.
534 : *
535 : * The default implementation of this method just calls the FlushCache() method
536 : * on each of the raster bands and the SyncToDisk() method
537 : * on each of the layers. Conceptually, calling FlushCache() on a dataset
538 : * should include any work that might be accomplished by calling SyncToDisk()
539 : * on layers in that dataset.
540 : *
541 : * Using this method does not prevent use from calling GDALClose()
542 : * to properly close a dataset and ensure that important data not addressed
543 : * by FlushCache() is written in the file.
544 : *
545 : * This method is the same as the C function GDALFlushCache().
546 : *
547 : * @param bAtClosing Whether this is called from a GDALDataset destructor
548 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
549 : */
550 :
551 96352 : CPLErr GDALDataset::FlushCache(bool bAtClosing)
552 :
553 : {
554 96352 : CPLErr eErr = CE_None;
555 : // This sometimes happens if a dataset is destroyed before completely
556 : // built.
557 :
558 96352 : if (papoBands)
559 : {
560 1269520 : for (int i = 0; i < nBands; ++i)
561 : {
562 1181020 : if (papoBands[i])
563 : {
564 1181020 : if (papoBands[i]->FlushCache(bAtClosing) != CE_None)
565 7 : eErr = CE_Failure;
566 : }
567 : }
568 : }
569 :
570 96352 : const int nLayers = GetLayerCount();
571 : // cppcheck-suppress knownConditionTrueFalse
572 96353 : if (nLayers > 0)
573 : {
574 7164 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
575 12121 : for (int i = 0; i < nLayers; ++i)
576 : {
577 8539 : OGRLayer *poLayer = GetLayer(i);
578 :
579 8539 : if (poLayer)
580 : {
581 8539 : if (poLayer->SyncToDisk() != OGRERR_NONE)
582 0 : eErr = CE_Failure;
583 : }
584 : }
585 : }
586 :
587 96353 : return eErr;
588 : }
589 :
590 : /************************************************************************/
591 : /* GDALFlushCache() */
592 : /************************************************************************/
593 :
594 : /**
595 : * \brief Flush all write cached data to disk.
596 : *
597 : * @see GDALDataset::FlushCache().
598 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
599 : */
600 :
601 4289 : CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)
602 :
603 : {
604 4289 : VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);
605 :
606 4289 : return GDALDataset::FromHandle(hDS)->FlushCache(false);
607 : }
608 :
609 : /************************************************************************/
610 : /* DropCache() */
611 : /************************************************************************/
612 :
613 : /**
614 : * \brief Drop all write cached data
615 : *
616 : * This method is the same as the C function GDALDropCache().
617 : *
618 : * @return CE_None in case of success
619 : * @since 3.9
620 : */
621 :
622 1 : CPLErr GDALDataset::DropCache()
623 :
624 : {
625 1 : CPLErr eErr = CE_None;
626 :
627 1 : if (papoBands)
628 : {
629 2 : for (int i = 0; i < nBands; ++i)
630 : {
631 1 : if (papoBands[i])
632 : {
633 1 : if (papoBands[i]->DropCache() != CE_None)
634 0 : eErr = CE_Failure;
635 : }
636 : }
637 : }
638 :
639 1 : return eErr;
640 : }
641 :
642 : /************************************************************************/
643 : /* GDALDropCache() */
644 : /************************************************************************/
645 :
646 : /**
647 : * \brief Drop all write cached data
648 : *
649 : * @see GDALDataset::DropCache().
650 : * @return CE_None in case of success
651 : * @since 3.9
652 : */
653 :
654 0 : CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS)
655 :
656 : {
657 0 : VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure);
658 :
659 0 : return GDALDataset::FromHandle(hDS)->DropCache();
660 : }
661 :
662 : /************************************************************************/
663 : /* GetEstimatedRAMUsage() */
664 : /************************************************************************/
665 :
666 : /**
667 : * \brief Return the intrinsic RAM usage of this dataset.
668 : *
669 : * The returned value should take into account caches in the underlying driver
670 : * and decoding library, but not the usage related to the GDAL block cache.
671 : *
672 : * At time of writing, this method is only implemented in the JP2OpenJPEG
673 : * driver. For single-tiled JPEG2000 images, the decoding of the image,
674 : * even partially, involves allocating at least
675 : * width * height * number_of_bands * sizeof(uint32_t) bytes inside the libopenjp2
676 : * library.
677 : *
678 : * This method is used by the GDALDatasetPool class, itself used by the GDAL VRT
679 : * driver, to determine how long a dataset in the pool must be kept open, given
680 : * the RAM usage of the dataset with respect to the usable total RAM.
681 : *
682 : * @since GDAL 3.7
683 : * @return RAM usage in bytes, or -1 if unknown (the default implementation
684 : * returns -1)
685 : */
686 :
687 1119 : GIntBig GDALDataset::GetEstimatedRAMUsage()
688 : {
689 1119 : return -1;
690 : }
691 :
692 : /************************************************************************/
693 : /* BlockBasedFlushCache() */
694 : /* */
695 : /* This helper method can be called by the */
696 : /* GDALDataset::FlushCache() for particular drivers to ensure */
697 : /* that buffers will be flushed in a manner suitable for pixel */
698 : /* interleaved (by block) IO. That is, if all the bands have */
699 : /* the same size blocks then a given block will be flushed for */
700 : /* all bands before proceeding to the next block. */
701 : /************************************************************************/
702 :
703 : //! @cond Doxygen_Suppress
704 346 : CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)
705 :
706 : {
707 346 : GDALRasterBand *poBand1 = GetRasterBand(1);
708 346 : if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))
709 : {
710 7 : return GDALDataset::FlushCache(bAtClosing);
711 : }
712 :
713 339 : int nBlockXSize = 0;
714 339 : int nBlockYSize = 0;
715 339 : poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
716 :
717 : /* -------------------------------------------------------------------- */
718 : /* Verify that all bands match. */
719 : /* -------------------------------------------------------------------- */
720 1104 : for (int iBand = 1; iBand < nBands; ++iBand)
721 : {
722 765 : GDALRasterBand *poBand = GetRasterBand(iBand + 1);
723 :
724 : int nThisBlockXSize, nThisBlockYSize;
725 765 : poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
726 765 : if (nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize)
727 : {
728 0 : return GDALDataset::FlushCache(bAtClosing);
729 : }
730 : }
731 :
732 : /* -------------------------------------------------------------------- */
733 : /* Now flush writable data. */
734 : /* -------------------------------------------------------------------- */
735 790 : for (int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY)
736 : {
737 991 : for (int iX = 0; iX < poBand1->nBlocksPerRow; ++iX)
738 : {
739 1690 : for (int iBand = 0; iBand < nBands; ++iBand)
740 : {
741 1150 : const CPLErr eErr = papoBands[iBand]->FlushBlock(iX, iY);
742 :
743 1150 : if (eErr != CE_None)
744 0 : return CE_Failure;
745 : }
746 : }
747 : }
748 339 : return CE_None;
749 : }
750 :
751 : /************************************************************************/
752 : /* RasterInitialize() */
753 : /* */
754 : /* Initialize raster size */
755 : /************************************************************************/
756 :
757 0 : void GDALDataset::RasterInitialize(int nXSize, int nYSize)
758 :
759 : {
760 0 : CPLAssert(nXSize > 0 && nYSize > 0);
761 :
762 0 : nRasterXSize = nXSize;
763 0 : nRasterYSize = nYSize;
764 0 : }
765 :
766 : //! @endcond
767 :
768 : /************************************************************************/
769 : /* AddBand() */
770 : /************************************************************************/
771 :
772 : /**
773 : * \fn GDALDataset::AddBand(GDALDataType, char**)
774 : * \brief Add a band to a dataset.
775 : *
776 : * This method will add a new band to the dataset if the underlying format
777 : * supports this action. Most formats do not.
778 : *
779 : * Note that the new GDALRasterBand is not returned. It may be fetched
780 : * after successful completion of the method by calling
781 : * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
782 : * band will always be the last band.
783 : *
784 : * @param eType the data type of the pixels in the new band.
785 : *
786 : * @param papszOptions a list of NAME=VALUE option strings. The supported
787 : * options are format specific. NULL may be passed by default.
788 : *
789 : * @return CE_None on success or CE_Failure on failure.
790 : */
791 :
792 0 : CPLErr GDALDataset::AddBand(CPL_UNUSED GDALDataType eType,
793 : CPL_UNUSED char **papszOptions)
794 :
795 : {
796 0 : ReportError(CE_Failure, CPLE_NotSupported,
797 : "Dataset does not support the AddBand() method.");
798 :
799 0 : return CE_Failure;
800 : }
801 :
802 : /************************************************************************/
803 : /* GDALAddBand() */
804 : /************************************************************************/
805 :
806 : /**
807 : * \brief Add a band to a dataset.
808 : *
809 : * @see GDALDataset::AddBand().
810 : */
811 :
812 63 : CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,
813 : CSLConstList papszOptions)
814 :
815 : {
816 63 : VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
817 :
818 126 : return GDALDataset::FromHandle(hDataset)->AddBand(
819 63 : eType, const_cast<char **>(papszOptions));
820 : }
821 :
822 : /************************************************************************/
823 : /* SetBand() */
824 : /************************************************************************/
825 :
826 : //! @cond Doxygen_Suppress
827 : /** Set a band in the band array, updating the band count, and array size
828 : * appropriately.
829 : *
830 : * @param nNewBand new band number (indexing starts at 1)
831 : * @param poBand band object.
832 : */
833 :
834 1099020 : void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)
835 :
836 : {
837 : /* -------------------------------------------------------------------- */
838 : /* Do we need to grow the bands list? */
839 : /* -------------------------------------------------------------------- */
840 1099020 : if (nBands < nNewBand || papoBands == nullptr)
841 : {
842 597854 : GDALRasterBand **papoNewBands = nullptr;
843 :
844 597854 : if (papoBands == nullptr)
845 80153 : papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
846 80178 : sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
847 : else
848 : papoNewBands = static_cast<GDALRasterBand **>(
849 517625 : VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
850 517676 : std::max(nNewBand, nBands)));
851 597778 : if (papoNewBands == nullptr)
852 : {
853 0 : ReportError(CE_Failure, CPLE_OutOfMemory,
854 : "Cannot allocate band array");
855 0 : return;
856 : }
857 :
858 597778 : papoBands = papoNewBands;
859 :
860 1150190 : for (int i = nBands; i < nNewBand; ++i)
861 552411 : papoBands[i] = nullptr;
862 :
863 597778 : nBands = std::max(nBands, nNewBand);
864 :
865 597780 : if (m_poPrivate)
866 : {
867 597958 : for (int i = static_cast<int>(m_poPrivate->m_anBandMap.size());
868 1696750 : i < nBands; ++i)
869 : {
870 1098850 : m_poPrivate->m_anBandMap.push_back(i + 1);
871 : }
872 : }
873 : }
874 :
875 : /* -------------------------------------------------------------------- */
876 : /* Set the band. Resetting the band is currently not permitted. */
877 : /* -------------------------------------------------------------------- */
878 1098890 : if (papoBands[nNewBand - 1] != nullptr)
879 : {
880 2 : ReportError(CE_Failure, CPLE_NotSupported,
881 : "Cannot set band %d as it is already set", nNewBand);
882 2 : return;
883 : }
884 :
885 1098880 : papoBands[nNewBand - 1] = poBand;
886 :
887 : /* -------------------------------------------------------------------- */
888 : /* Set back reference information on the raster band. Note */
889 : /* that the GDALDataset is a friend of the GDALRasterBand */
890 : /* specifically to allow this. */
891 : /* -------------------------------------------------------------------- */
892 1098880 : poBand->nBand = nNewBand;
893 1098880 : poBand->poDS = this;
894 1098880 : poBand->nRasterXSize = nRasterXSize;
895 1098880 : poBand->nRasterYSize = nRasterYSize;
896 1098880 : poBand->eAccess = eAccess; // Default access to be same as dataset.
897 : }
898 :
899 : //! @endcond
900 :
901 : /************************************************************************/
902 : /* SetBand() */
903 : /************************************************************************/
904 :
905 : //! @cond Doxygen_Suppress
906 : /** Set a band in the band array, updating the band count, and array size
907 : * appropriately.
908 : *
909 : * @param nNewBand new band number (indexing starts at 1)
910 : * @param poBand band object.
911 : */
912 :
913 71595 : void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)
914 : {
915 71595 : SetBand(nNewBand, poBand.release());
916 71594 : }
917 :
918 : //! @endcond
919 :
920 : /************************************************************************/
921 : /* GetRasterXSize() */
922 : /************************************************************************/
923 :
924 : /**
925 :
926 : \brief Fetch raster width in pixels.
927 :
928 : Equivalent of the C function GDALGetRasterXSize().
929 :
930 : @return the width in pixels of raster bands in this GDALDataset.
931 :
932 : */
933 :
934 382654 : int GDALDataset::GetRasterXSize() const
935 : {
936 382654 : return nRasterXSize;
937 : }
938 :
939 : /************************************************************************/
940 : /* GDALGetRasterXSize() */
941 : /************************************************************************/
942 :
943 : /**
944 : * \brief Fetch raster width in pixels.
945 : *
946 : * @see GDALDataset::GetRasterXSize().
947 : */
948 :
949 32683 : int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)
950 :
951 : {
952 32683 : VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
953 :
954 32683 : return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
955 : }
956 :
957 : /************************************************************************/
958 : /* GetRasterYSize() */
959 : /************************************************************************/
960 :
961 : /**
962 :
963 : \brief Fetch raster height in pixels.
964 :
965 : Equivalent of the C function GDALGetRasterYSize().
966 :
967 : @return the height in pixels of raster bands in this GDALDataset.
968 :
969 : */
970 :
971 333020 : int GDALDataset::GetRasterYSize() const
972 : {
973 333020 : return nRasterYSize;
974 : }
975 :
976 : /************************************************************************/
977 : /* GDALGetRasterYSize() */
978 : /************************************************************************/
979 :
980 : /**
981 : * \brief Fetch raster height in pixels.
982 : *
983 : * @see GDALDataset::GetRasterYSize().
984 : */
985 :
986 32381 : int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)
987 :
988 : {
989 32381 : VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
990 :
991 32381 : return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
992 : }
993 :
994 : /************************************************************************/
995 : /* GetRasterBand() */
996 : /************************************************************************/
997 :
998 : /**
999 :
1000 : \brief Fetch a band object for a dataset.
1001 :
1002 : See GetBands() for a C++ iterator version of this method.
1003 :
1004 : Equivalent of the C function GDALGetRasterBand().
1005 :
1006 : @param nBandId the index number of the band to fetch, from 1 to
1007 : GetRasterCount().
1008 :
1009 : @return the nBandId th band object
1010 :
1011 : */
1012 :
1013 9272600 : GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)
1014 :
1015 : {
1016 9272600 : if (papoBands)
1017 : {
1018 9269290 : if (nBandId < 1 || nBandId > nBands)
1019 : {
1020 13403 : ReportError(CE_Failure, CPLE_IllegalArg,
1021 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1022 : nBandId);
1023 13 : return nullptr;
1024 : }
1025 :
1026 9255890 : return papoBands[nBandId - 1];
1027 : }
1028 3315 : return nullptr;
1029 : }
1030 :
1031 : /************************************************************************/
1032 : /* GetRasterBand() */
1033 : /************************************************************************/
1034 :
1035 : /**
1036 :
1037 : \brief Fetch a band object for a dataset.
1038 :
1039 : See GetBands() for a C++ iterator version of this method.
1040 :
1041 : Equivalent of the C function GDALGetRasterBand().
1042 :
1043 : @param nBandId the index number of the band to fetch, from 1 to
1044 : GetRasterCount().
1045 :
1046 : @return the nBandId th band object
1047 :
1048 : */
1049 :
1050 0 : const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const
1051 :
1052 : {
1053 0 : if (papoBands)
1054 : {
1055 0 : if (nBandId < 1 || nBandId > nBands)
1056 : {
1057 0 : ReportError(CE_Failure, CPLE_IllegalArg,
1058 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1059 : nBandId);
1060 0 : return nullptr;
1061 : }
1062 :
1063 0 : return papoBands[nBandId - 1];
1064 : }
1065 0 : return nullptr;
1066 : }
1067 :
1068 : /************************************************************************/
1069 : /* GDALGetRasterBand() */
1070 : /************************************************************************/
1071 :
1072 : /**
1073 : * \brief Fetch a band object for a dataset.
1074 : * @see GDALDataset::GetRasterBand().
1075 : */
1076 :
1077 289237 : GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)
1078 :
1079 : {
1080 289237 : VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
1081 :
1082 289237 : return GDALRasterBand::ToHandle(
1083 289237 : GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
1084 : }
1085 :
1086 : /************************************************************************/
1087 : /* GetRasterCount() */
1088 : /************************************************************************/
1089 :
1090 : /**
1091 : * \brief Fetch the number of raster bands on this dataset.
1092 : *
1093 : * Same as the C function GDALGetRasterCount().
1094 : *
1095 : * @return the number of raster bands.
1096 : */
1097 :
1098 4242620 : int GDALDataset::GetRasterCount() const
1099 : {
1100 4242620 : return papoBands ? nBands : 0;
1101 : }
1102 :
1103 : /************************************************************************/
1104 : /* GDALGetRasterCount() */
1105 : /************************************************************************/
1106 :
1107 : /**
1108 : * \brief Fetch the number of raster bands on this dataset.
1109 : *
1110 : * @see GDALDataset::GetRasterCount().
1111 : */
1112 :
1113 374938 : int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)
1114 :
1115 : {
1116 374938 : VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
1117 :
1118 374938 : return GDALDataset::FromHandle(hDS)->GetRasterCount();
1119 : }
1120 :
1121 : /************************************************************************/
1122 : /* GetProjectionRef() */
1123 : /************************************************************************/
1124 :
1125 : /**
1126 : * \brief Fetch the projection definition string for this dataset.
1127 : *
1128 : * Same as the C function GDALGetProjectionRef().
1129 : *
1130 : * The returned string defines the projection coordinate system of the
1131 : * image in OpenGIS WKT format. It should be suitable for use with the
1132 : * OGRSpatialReference class.
1133 : *
1134 : * When a projection definition is not available an empty (but not NULL)
1135 : * string is returned.
1136 : *
1137 : * \note Starting with GDAL 3.0, this is a compatibility layer around
1138 : * GetSpatialRef()
1139 : *
1140 : * @return a pointer to an internal projection reference string. It should
1141 : * not be altered, freed or expected to last for long.
1142 : *
1143 : * @see https://gdal.org/tutorials/osr_api_tut.html
1144 : */
1145 :
1146 6071 : const char *GDALDataset::GetProjectionRef() const
1147 : {
1148 6071 : const auto poSRS = GetSpatialRef();
1149 6071 : if (!poSRS || !m_poPrivate)
1150 : {
1151 2591 : return "";
1152 : }
1153 3480 : char *pszWKT = nullptr;
1154 3480 : poSRS->exportToWkt(&pszWKT);
1155 3480 : if (!pszWKT)
1156 : {
1157 0 : return "";
1158 : }
1159 :
1160 : // If called on a thread-safe dataset, we might be called by several
1161 : // threads, so make sure our accesses to m_pszWKTCached are protected
1162 : // by a mutex.
1163 6960 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1164 3480 : if (m_poPrivate->m_pszWKTCached &&
1165 1285 : strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)
1166 : {
1167 1284 : CPLFree(pszWKT);
1168 1284 : return m_poPrivate->m_pszWKTCached;
1169 : }
1170 2196 : CPLFree(m_poPrivate->m_pszWKTCached);
1171 2196 : m_poPrivate->m_pszWKTCached = pszWKT;
1172 2196 : return m_poPrivate->m_pszWKTCached;
1173 : }
1174 :
1175 : /************************************************************************/
1176 : /* GetSpatialRef() */
1177 : /************************************************************************/
1178 :
1179 : /**
1180 : * \brief Fetch the spatial reference for this dataset.
1181 : *
1182 : * Same as the C function GDALGetSpatialRef().
1183 : *
1184 : * When a projection definition is not available, null is returned. If used on
1185 : * a dataset where there are GCPs and not a geotransform, this method returns
1186 : * null. Use GetGCPSpatialRef() instead.
1187 : *
1188 : * @since GDAL 3.0
1189 : *
1190 : * @return a pointer to an internal object. It should not be altered or freed.
1191 : * Its lifetime will be the one of the dataset object, or until the next
1192 : * call to this method.
1193 : *
1194 : * @see https://gdal.org/tutorials/osr_api_tut.html
1195 : */
1196 :
1197 13983 : const OGRSpatialReference *GDALDataset::GetSpatialRef() const
1198 : {
1199 13983 : return nullptr;
1200 : }
1201 :
1202 : /************************************************************************/
1203 : /* GDALGetSpatialRef() */
1204 : /************************************************************************/
1205 :
1206 : /**
1207 : * \brief Fetch the spatial reference for this dataset.
1208 : *
1209 : * @since GDAL 3.0
1210 : *
1211 : * @see GDALDataset::GetSpatialRef()
1212 : */
1213 :
1214 5861 : OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)
1215 :
1216 : {
1217 5861 : VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
1218 :
1219 5861 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1220 5861 : GDALDataset::FromHandle(hDS)->GetSpatialRef()));
1221 : }
1222 :
1223 : /************************************************************************/
1224 : /* GDALGetProjectionRef() */
1225 : /************************************************************************/
1226 :
1227 : /**
1228 : * \brief Fetch the projection definition string for this dataset.
1229 : *
1230 : * @see GDALDataset::GetProjectionRef()
1231 : */
1232 :
1233 1392 : const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)
1234 :
1235 : {
1236 1392 : VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
1237 :
1238 1392 : return GDALDataset::FromHandle(hDS)->GetProjectionRef();
1239 : }
1240 :
1241 : /************************************************************************/
1242 : /* SetProjection() */
1243 : /************************************************************************/
1244 :
1245 : /**
1246 : * \brief Set the projection reference string for this dataset.
1247 : *
1248 : * The string should be in OGC WKT or PROJ.4 format. An error may occur
1249 : * because of incorrectly specified projection strings, because the dataset
1250 : * is not writable, or because the dataset does not support the indicated
1251 : * projection. Many formats do not support writing projections.
1252 : *
1253 : * This method is the same as the C GDALSetProjection() function.
1254 : *
1255 : * \note Startig with GDAL 3.0, this is a compatibility layer around
1256 : * SetSpatialRef()
1257 :
1258 : * @param pszProjection projection reference string.
1259 : *
1260 : * @return CE_Failure if an error occurs, otherwise CE_None.
1261 : */
1262 :
1263 2470 : CPLErr GDALDataset::SetProjection(const char *pszProjection)
1264 : {
1265 2470 : if (pszProjection && pszProjection[0] != '\0')
1266 : {
1267 4610 : OGRSpatialReference oSRS;
1268 2305 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1269 2305 : if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)
1270 : {
1271 2 : return CE_Failure;
1272 : }
1273 2303 : return SetSpatialRef(&oSRS);
1274 : }
1275 : else
1276 : {
1277 165 : return SetSpatialRef(nullptr);
1278 : }
1279 : }
1280 :
1281 : /************************************************************************/
1282 : /* SetSpatialRef() */
1283 : /************************************************************************/
1284 :
1285 : /**
1286 : * \brief Set the spatial reference system for this dataset.
1287 : *
1288 : * An error may occur because the dataset
1289 : * is not writable, or because the dataset does not support the indicated
1290 : * projection. Many formats do not support writing projections.
1291 : *
1292 : * This method is the same as the C GDALSetSpatialRef() function.
1293 : *
1294 : * @since GDAL 3.0
1295 :
1296 : * @param poSRS spatial reference system object. nullptr can potentially be
1297 : * passed for drivers that support unsetting the SRS.
1298 : *
1299 : * @return CE_Failure if an error occurs, otherwise CE_None.
1300 : */
1301 :
1302 0 : CPLErr GDALDataset::SetSpatialRef(CPL_UNUSED const OGRSpatialReference *poSRS)
1303 : {
1304 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1305 0 : ReportError(CE_Failure, CPLE_NotSupported,
1306 : "Dataset does not support the SetSpatialRef() method.");
1307 0 : return CE_Failure;
1308 : }
1309 :
1310 : /************************************************************************/
1311 : /* GDALSetSpatialRef() */
1312 : /************************************************************************/
1313 :
1314 : /**
1315 : * \brief Set the spatial reference system for this dataset.
1316 : *
1317 : * @since GDAL 3.0
1318 : *
1319 : * @see GDALDataset::SetSpatialRef()
1320 : */
1321 :
1322 989 : CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)
1323 :
1324 : {
1325 989 : VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1326 :
1327 1978 : return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1328 989 : OGRSpatialReference::FromHandle(hSRS));
1329 : }
1330 :
1331 : /************************************************************************/
1332 : /* GDALSetProjection() */
1333 : /************************************************************************/
1334 :
1335 : /**
1336 : * \brief Set the projection reference string for this dataset.
1337 : *
1338 : * @see GDALDataset::SetProjection()
1339 : */
1340 :
1341 1975 : CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,
1342 : const char *pszProjection)
1343 :
1344 : {
1345 1975 : VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1346 :
1347 1975 : return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
1348 : }
1349 :
1350 : /************************************************************************/
1351 : /* GetGeoTransform() */
1352 : /************************************************************************/
1353 :
1354 : /**
1355 : * \brief Fetch the affine transformation coefficients.
1356 : *
1357 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
1358 : * space, and projection coordinates (Xp,Yp) space.
1359 : *
1360 : * \code
1361 : * Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
1362 : * Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
1363 : * \endcode
1364 : *
1365 : * In a north up image, padfTransform[1] is the pixel width, and
1366 : * padfTransform[5] is the pixel height. The upper left corner of the
1367 : * upper left pixel is at position (padfTransform[0],padfTransform[3]).
1368 : *
1369 : * The default transform is (0,1,0,0,0,1) and should be returned even when
1370 : * a CE_Failure error is returned, such as for formats that don't support
1371 : * transformation to projection coordinates.
1372 : *
1373 : * This method does the same thing as the C GDALGetGeoTransform() function.
1374 : *
1375 : * @param padfTransform an existing six double buffer into which the
1376 : * transformation will be placed.
1377 : *
1378 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
1379 : */
1380 :
1381 12317 : CPLErr GDALDataset::GetGeoTransform(double *padfTransform)
1382 :
1383 : {
1384 12317 : CPLAssert(padfTransform != nullptr);
1385 :
1386 12317 : padfTransform[0] = 0.0; // X Origin (top left corner)
1387 12317 : padfTransform[1] = 1.0; // X Pixel size */
1388 12317 : padfTransform[2] = 0.0;
1389 :
1390 12317 : padfTransform[3] = 0.0; // Y Origin (top left corner)
1391 12317 : padfTransform[4] = 0.0;
1392 12317 : padfTransform[5] = 1.0; // Y Pixel Size
1393 :
1394 12317 : return CE_Failure;
1395 : }
1396 :
1397 : /************************************************************************/
1398 : /* GDALGetGeoTransform() */
1399 : /************************************************************************/
1400 :
1401 : /**
1402 : * \brief Fetch the affine transformation coefficients.
1403 : *
1404 : * @see GDALDataset::GetGeoTransform()
1405 : */
1406 :
1407 7862 : CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1408 :
1409 : {
1410 7862 : VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1411 :
1412 7862 : return GDALDataset::FromHandle(hDS)->GetGeoTransform(padfTransform);
1413 : }
1414 :
1415 : /************************************************************************/
1416 : /* SetGeoTransform() */
1417 : /************************************************************************/
1418 :
1419 : /**
1420 : * \fn GDALDataset::SetGeoTransform(double*)
1421 : * \brief Set the affine transformation coefficients.
1422 : *
1423 : * See GetGeoTransform() for details on the meaning of the padfTransform
1424 : * coefficients.
1425 : *
1426 : * This method does the same thing as the C GDALSetGeoTransform() function.
1427 : *
1428 : * @param padfTransform a six double buffer containing the transformation
1429 : * coefficients to be written with the dataset.
1430 : *
1431 : * @return CE_None on success, or CE_Failure if this transform cannot be
1432 : * written.
1433 : */
1434 :
1435 0 : CPLErr GDALDataset::SetGeoTransform(CPL_UNUSED double *padfTransform)
1436 :
1437 : {
1438 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1439 0 : ReportError(CE_Failure, CPLE_NotSupported,
1440 : "SetGeoTransform() not supported for this dataset.");
1441 :
1442 0 : return CE_Failure;
1443 : }
1444 :
1445 : /************************************************************************/
1446 : /* GDALSetGeoTransform() */
1447 : /************************************************************************/
1448 :
1449 : /**
1450 : * \brief Set the affine transformation coefficients.
1451 : *
1452 : * @see GDALDataset::SetGeoTransform()
1453 : */
1454 :
1455 3781 : CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1456 :
1457 : {
1458 3781 : VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1459 :
1460 3781 : return GDALDataset::FromHandle(hDS)->SetGeoTransform(padfTransform);
1461 : }
1462 :
1463 : /************************************************************************/
1464 : /* GetInternalHandle() */
1465 : /************************************************************************/
1466 :
1467 : /**
1468 : * \fn GDALDataset::GetInternalHandle(const char*)
1469 : * \brief Fetch a format specific internally meaningful handle.
1470 : *
1471 : * This method is the same as the C GDALGetInternalHandle() method.
1472 : *
1473 : * @param pszHandleName the handle name desired. The meaningful names
1474 : * will be specific to the file format.
1475 : *
1476 : * @return the desired handle value, or NULL if not recognized/supported.
1477 : */
1478 :
1479 0 : void *GDALDataset::GetInternalHandle(CPL_UNUSED const char *pszHandleName)
1480 :
1481 : {
1482 0 : return nullptr;
1483 : }
1484 :
1485 : /************************************************************************/
1486 : /* GDALGetInternalHandle() */
1487 : /************************************************************************/
1488 :
1489 : /**
1490 : * \brief Fetch a format specific internally meaningful handle.
1491 : *
1492 : * @see GDALDataset::GetInternalHandle()
1493 : */
1494 :
1495 60 : void *CPL_STDCALL GDALGetInternalHandle(GDALDatasetH hDS,
1496 : const char *pszRequest)
1497 :
1498 : {
1499 60 : VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
1500 :
1501 60 : return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
1502 : }
1503 :
1504 : /************************************************************************/
1505 : /* GetDriver() */
1506 : /************************************************************************/
1507 :
1508 : /**
1509 : * \brief Fetch the driver to which this dataset relates.
1510 : *
1511 : * This method is the same as the C GDALGetDatasetDriver() function.
1512 : *
1513 : * @return the driver on which the dataset was created with GDALOpen() or
1514 : * GDALCreate().
1515 : */
1516 :
1517 28765 : GDALDriver *GDALDataset::GetDriver()
1518 : {
1519 28765 : return poDriver;
1520 : }
1521 :
1522 : /************************************************************************/
1523 : /* GDALGetDatasetDriver() */
1524 : /************************************************************************/
1525 :
1526 : /**
1527 : * \brief Fetch the driver to which this dataset relates.
1528 : *
1529 : * @see GDALDataset::GetDriver()
1530 : */
1531 :
1532 2702 : GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)
1533 :
1534 : {
1535 2702 : VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1536 :
1537 : return static_cast<GDALDriverH>(
1538 2702 : GDALDataset::FromHandle(hDataset)->GetDriver());
1539 : }
1540 :
1541 : /************************************************************************/
1542 : /* Reference() */
1543 : /************************************************************************/
1544 :
1545 : /**
1546 : * \brief Add one to dataset reference count.
1547 : *
1548 : * The reference is one after instantiation.
1549 : *
1550 : * This method is the same as the C GDALReferenceDataset() function.
1551 : *
1552 : * @return the post-increment reference count.
1553 : */
1554 :
1555 18986 : int GDALDataset::Reference()
1556 : {
1557 18986 : return ++nRefCount;
1558 : }
1559 :
1560 : /************************************************************************/
1561 : /* GDALReferenceDataset() */
1562 : /************************************************************************/
1563 :
1564 : /**
1565 : * \brief Add one to dataset reference count.
1566 : *
1567 : * @see GDALDataset::Reference()
1568 : */
1569 :
1570 1092 : int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)
1571 :
1572 : {
1573 1092 : VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1574 :
1575 1092 : return GDALDataset::FromHandle(hDataset)->Reference();
1576 : }
1577 :
1578 : /************************************************************************/
1579 : /* Dereference() */
1580 : /************************************************************************/
1581 :
1582 : /**
1583 : * \brief Subtract one from dataset reference count.
1584 : *
1585 : * The reference is one after instantiation. Generally when the reference
1586 : * count has dropped to zero the dataset may be safely deleted (closed).
1587 : *
1588 : * This method is the same as the C GDALDereferenceDataset() function.
1589 : *
1590 : * @return the post-decrement reference count.
1591 : */
1592 :
1593 68991 : int GDALDataset::Dereference()
1594 : {
1595 68991 : return --nRefCount;
1596 : }
1597 :
1598 : /************************************************************************/
1599 : /* GDALDereferenceDataset() */
1600 : /************************************************************************/
1601 :
1602 : /**
1603 : * \brief Subtract one from dataset reference count.
1604 : *
1605 : * @see GDALDataset::Dereference()
1606 : */
1607 :
1608 53614 : int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)
1609 :
1610 : {
1611 53614 : VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1612 :
1613 53614 : return GDALDataset::FromHandle(hDataset)->Dereference();
1614 : }
1615 :
1616 : /************************************************************************/
1617 : /* ReleaseRef() */
1618 : /************************************************************************/
1619 :
1620 : /**
1621 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1622 : * @return TRUE if the object has been destroyed.
1623 : * @since GDAL 2.2
1624 : */
1625 :
1626 14300 : int GDALDataset::ReleaseRef()
1627 :
1628 : {
1629 14300 : if (Dereference() <= 0)
1630 : {
1631 3374 : nRefCount = 1;
1632 3374 : delete this;
1633 3374 : return TRUE;
1634 : }
1635 10926 : return FALSE;
1636 : }
1637 :
1638 : /************************************************************************/
1639 : /* GDALReleaseDataset() */
1640 : /************************************************************************/
1641 :
1642 : /**
1643 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1644 : *
1645 : * @see GDALDataset::ReleaseRef()
1646 : * @since GDAL 2.2
1647 : */
1648 :
1649 1323 : int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)
1650 :
1651 : {
1652 1323 : VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1653 :
1654 1323 : return GDALDataset::FromHandle(hDataset)->ReleaseRef();
1655 : }
1656 :
1657 : /************************************************************************/
1658 : /* GetShared() */
1659 : /************************************************************************/
1660 :
1661 : /**
1662 : * \brief Returns shared flag.
1663 : *
1664 : * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1665 : */
1666 :
1667 92954 : int GDALDataset::GetShared() const
1668 : {
1669 92954 : return bShared;
1670 : }
1671 :
1672 : /************************************************************************/
1673 : /* MarkAsShared() */
1674 : /************************************************************************/
1675 :
1676 : /**
1677 : * \brief Mark this dataset as available for sharing.
1678 : */
1679 :
1680 404 : void GDALDataset::MarkAsShared()
1681 :
1682 : {
1683 404 : CPLAssert(!bShared);
1684 :
1685 404 : bShared = true;
1686 404 : if (bIsInternal)
1687 13 : return;
1688 :
1689 391 : GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1690 :
1691 : // Insert the dataset in the set of shared opened datasets.
1692 782 : CPLMutexHolderD(&hDLMutex);
1693 391 : if (phSharedDatasetSet == nullptr)
1694 237 : phSharedDatasetSet =
1695 237 : CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1696 : GDALSharedDatasetFreeFunc);
1697 :
1698 : SharedDatasetCtxt *psStruct =
1699 391 : static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1700 391 : psStruct->poDS = this;
1701 391 : psStruct->nPID = nPID;
1702 391 : psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
1703 391 : psStruct->pszDescription = CPLStrdup(GetDescription());
1704 : std::string osConcatenatedOpenOptions =
1705 782 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
1706 391 : psStruct->pszConcatenatedOpenOptions =
1707 391 : CPLStrdup(osConcatenatedOpenOptions.c_str());
1708 391 : if (CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
1709 : {
1710 1 : GDALSharedDatasetFreeFunc(psStruct);
1711 1 : ReportError(CE_Failure, CPLE_AppDefined,
1712 : "An existing shared dataset already has this description. "
1713 : "This should not happen.");
1714 : }
1715 : else
1716 : {
1717 390 : CPLHashSetInsert(phSharedDatasetSet, psStruct);
1718 :
1719 390 : (*poAllDatasetMap)[this] = nPID;
1720 : }
1721 : }
1722 :
1723 : /************************************************************************/
1724 : /* MarkSuppressOnClose() */
1725 : /************************************************************************/
1726 :
1727 : /** Set that the dataset must be deleted on close. */
1728 1066 : void GDALDataset::MarkSuppressOnClose()
1729 : {
1730 1066 : bSuppressOnClose = true;
1731 1066 : }
1732 :
1733 : /************************************************************************/
1734 : /* UnMarkSuppressOnClose() */
1735 : /************************************************************************/
1736 :
1737 : /** Remove the flag requesting the dataset to be deleted on close. */
1738 1 : void GDALDataset::UnMarkSuppressOnClose()
1739 : {
1740 1 : bSuppressOnClose = false;
1741 1 : }
1742 :
1743 : /************************************************************************/
1744 : /* CleanupPostFileClosing() */
1745 : /************************************************************************/
1746 :
1747 : /** This method should be called by driver implementations in their destructor,
1748 : * after having closed all files, but before having freed resources that
1749 : * are needed for their GetFileList() implementation.
1750 : * This is used to implement MarkSuppressOnClose behavior.
1751 : */
1752 251 : void GDALDataset::CleanupPostFileClosing()
1753 : {
1754 251 : if (IsMarkedSuppressOnClose())
1755 : {
1756 1 : char **papszFileList = GetFileList();
1757 3 : for (int i = 0; papszFileList && papszFileList[i]; ++i)
1758 2 : VSIUnlink(papszFileList[i]);
1759 1 : CSLDestroy(papszFileList);
1760 : }
1761 251 : }
1762 :
1763 : /************************************************************************/
1764 : /* GetGCPCount() */
1765 : /************************************************************************/
1766 :
1767 : /**
1768 : * \brief Get number of GCPs.
1769 : *
1770 : * This method is the same as the C function GDALGetGCPCount().
1771 : *
1772 : * @return number of GCPs for this dataset. Zero if there are none.
1773 : */
1774 :
1775 12750 : int GDALDataset::GetGCPCount()
1776 : {
1777 12750 : return 0;
1778 : }
1779 :
1780 : /************************************************************************/
1781 : /* GDALGetGCPCount() */
1782 : /************************************************************************/
1783 :
1784 : /**
1785 : * \brief Get number of GCPs.
1786 : *
1787 : * @see GDALDataset::GetGCPCount()
1788 : */
1789 :
1790 1033 : int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)
1791 :
1792 : {
1793 1033 : VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
1794 :
1795 1033 : return GDALDataset::FromHandle(hDS)->GetGCPCount();
1796 : }
1797 :
1798 : /************************************************************************/
1799 : /* GetGCPProjection() */
1800 : /************************************************************************/
1801 :
1802 : /**
1803 : * \brief Get output projection for GCPs.
1804 : *
1805 : * This method is the same as the C function GDALGetGCPProjection().
1806 : *
1807 : * The projection string follows the normal rules from GetProjectionRef().
1808 : *
1809 : * \note Starting with GDAL 3.0, this is a compatibility layer around
1810 : * GetGCPSpatialRef()
1811 : *
1812 : * @return internal projection string or "" if there are no GCPs.
1813 : * It should not be altered, freed or expected to last for long.
1814 : */
1815 :
1816 808 : const char *GDALDataset::GetGCPProjection()
1817 : {
1818 808 : const auto poSRS = GetGCPSpatialRef();
1819 808 : if (!poSRS || !m_poPrivate)
1820 : {
1821 471 : return "";
1822 : }
1823 337 : char *pszWKT = nullptr;
1824 337 : poSRS->exportToWkt(&pszWKT);
1825 337 : if (!pszWKT)
1826 : {
1827 0 : return "";
1828 : }
1829 :
1830 : // If called on a thread-safe dataset, we might be called by several
1831 : // threads, so make sure our accesses to m_pszWKTCached are protected
1832 : // by a mutex.
1833 674 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1834 337 : if (m_poPrivate->m_pszWKTGCPCached &&
1835 256 : strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0)
1836 : {
1837 256 : CPLFree(pszWKT);
1838 256 : return m_poPrivate->m_pszWKTGCPCached;
1839 : }
1840 81 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
1841 81 : m_poPrivate->m_pszWKTGCPCached = pszWKT;
1842 81 : return m_poPrivate->m_pszWKTGCPCached;
1843 : }
1844 :
1845 : /************************************************************************/
1846 : /* GetGCPSpatialRef() */
1847 : /************************************************************************/
1848 :
1849 : /**
1850 : * \brief Get output spatial reference system for GCPs.
1851 : *
1852 : * Same as the C function GDALGetGCPSpatialRef().
1853 : *
1854 : * When a SRS is not available, null is returned. If used on
1855 : * a dataset where there is a geotransform, and not GCPs, this method returns
1856 : * null. Use GetSpatialRef() instead.
1857 : *
1858 : * @since GDAL 3.0
1859 : *
1860 : * @return a pointer to an internal object. It should not be altered or freed.
1861 : * Its lifetime will be the one of the dataset object, or until the next
1862 : * call to this method.
1863 : */
1864 :
1865 39 : const OGRSpatialReference *GDALDataset::GetGCPSpatialRef() const
1866 : {
1867 39 : return nullptr;
1868 : }
1869 :
1870 : /************************************************************************/
1871 : /* GDALGetGCPSpatialRef() */
1872 : /************************************************************************/
1873 :
1874 : /**
1875 : * \brief Get output spatial reference system for GCPs.
1876 : *
1877 : * @since GDAL 3.0
1878 : *
1879 : * @see GDALDataset::GetGCPSpatialRef()
1880 : */
1881 :
1882 464 : OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)
1883 :
1884 : {
1885 464 : VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
1886 :
1887 464 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1888 464 : GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
1889 : }
1890 :
1891 : /************************************************************************/
1892 : /* GDALGetGCPProjection() */
1893 : /************************************************************************/
1894 :
1895 : /**
1896 : * \brief Get output projection for GCPs.
1897 : *
1898 : * @see GDALDataset::GetGCPProjection()
1899 : */
1900 :
1901 737 : const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)
1902 :
1903 : {
1904 737 : VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
1905 :
1906 737 : return GDALDataset::FromHandle(hDS)->GetGCPProjection();
1907 : }
1908 :
1909 : /************************************************************************/
1910 : /* GetGCPs() */
1911 : /************************************************************************/
1912 :
1913 : /**
1914 : * \brief Fetch GCPs.
1915 : *
1916 : * This method is the same as the C function GDALGetGCPs().
1917 : *
1918 : * @return pointer to internal GCP structure list. It should not be modified,
1919 : * and may change on the next GDAL call.
1920 : */
1921 :
1922 10 : const GDAL_GCP *GDALDataset::GetGCPs()
1923 : {
1924 10 : return nullptr;
1925 : }
1926 :
1927 : /************************************************************************/
1928 : /* GDALGetGCPs() */
1929 : /************************************************************************/
1930 :
1931 : /**
1932 : * \brief Fetch GCPs.
1933 : *
1934 : * @see GDALDataset::GetGCPs()
1935 : */
1936 :
1937 554 : const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)
1938 :
1939 : {
1940 554 : VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
1941 :
1942 554 : return GDALDataset::FromHandle(hDS)->GetGCPs();
1943 : }
1944 :
1945 : /************************************************************************/
1946 : /* SetGCPs() */
1947 : /************************************************************************/
1948 :
1949 : /**
1950 : * \brief Assign GCPs.
1951 : *
1952 : * This method is the same as the C function GDALSetGCPs().
1953 : *
1954 : * This method assigns the passed set of GCPs to this dataset, as well as
1955 : * setting their coordinate system. Internally copies are made of the
1956 : * coordinate system and list of points, so the caller remains responsible for
1957 : * deallocating these arguments if appropriate.
1958 : *
1959 : * Most formats do not support setting of GCPs, even formats that can
1960 : * handle GCPs. These formats will return CE_Failure.
1961 : *
1962 : * \note Startig with GDAL 3.0, this is a compatibility layer around
1963 : * SetGCPs(int, const GDAL_GCP*, const char*)
1964 : *
1965 : * @param nGCPCount number of GCPs being assigned.
1966 : *
1967 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
1968 : *
1969 : * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
1970 : * GCP output coordinates. This parameter should be "" if no output coordinate
1971 : * system is known.
1972 : *
1973 : * @return CE_None on success, CE_Failure on failure (including if action is
1974 : * not supported for this format).
1975 : */
1976 :
1977 52 : CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,
1978 : const char *pszGCPProjection)
1979 :
1980 : {
1981 52 : if (pszGCPProjection && pszGCPProjection[0] != '\0')
1982 : {
1983 66 : OGRSpatialReference oSRS;
1984 33 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1985 33 : if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)
1986 : {
1987 0 : return CE_Failure;
1988 : }
1989 33 : return SetGCPs(nGCPCount, pasGCPList, &oSRS);
1990 : }
1991 : else
1992 : {
1993 19 : return SetGCPs(nGCPCount, pasGCPList,
1994 19 : static_cast<const OGRSpatialReference *>(nullptr));
1995 : }
1996 : }
1997 :
1998 : /************************************************************************/
1999 : /* SetGCPs() */
2000 : /************************************************************************/
2001 :
2002 : /**
2003 : * \brief Assign GCPs.
2004 : *
2005 : * This method is the same as the C function GDALSetGCPs().
2006 : *
2007 : * This method assigns the passed set of GCPs to this dataset, as well as
2008 : * setting their coordinate system. Internally copies are made of the
2009 : * coordinate system and list of points, so the caller remains responsible for
2010 : * deallocating these arguments if appropriate.
2011 : *
2012 : * Most formats do not support setting of GCPs, even formats that can
2013 : * handle GCPs. These formats will return CE_Failure.
2014 : *
2015 : * @since GDAL 3.0
2016 : *
2017 : * @param nGCPCount number of GCPs being assigned.
2018 : *
2019 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2020 : *
2021 : * @param poGCP_SRS the new coordinate reference system to assign for the
2022 : * GCP output coordinates. This parameter should be null if no output
2023 : * coordinate system is known.
2024 : *
2025 : * @return CE_None on success, CE_Failure on failure (including if action is
2026 : * not supported for this format).
2027 : */
2028 :
2029 0 : CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,
2030 : CPL_UNUSED const GDAL_GCP *pasGCPList,
2031 : CPL_UNUSED const OGRSpatialReference *poGCP_SRS)
2032 :
2033 : {
2034 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
2035 0 : ReportError(CE_Failure, CPLE_NotSupported,
2036 : "Dataset does not support the SetGCPs() method.");
2037 :
2038 0 : return CE_Failure;
2039 : }
2040 :
2041 : /************************************************************************/
2042 : /* GDALSetGCPs() */
2043 : /************************************************************************/
2044 :
2045 : /**
2046 : * \brief Assign GCPs.
2047 : *
2048 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
2049 : */
2050 :
2051 29 : CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,
2052 : const GDAL_GCP *pasGCPList,
2053 : const char *pszGCPProjection)
2054 :
2055 : {
2056 29 : VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
2057 :
2058 29 : return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,
2059 29 : pszGCPProjection);
2060 : }
2061 :
2062 : /************************************************************************/
2063 : /* GDALSetGCPs2() */
2064 : /************************************************************************/
2065 :
2066 : /**
2067 : * \brief Assign GCPs.
2068 : *
2069 : * @since GDAL 3.0
2070 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
2071 : */
2072 :
2073 9 : CPLErr GDALSetGCPs2(GDALDatasetH hDS, int nGCPCount, const GDAL_GCP *pasGCPList,
2074 : OGRSpatialReferenceH hSRS)
2075 :
2076 : {
2077 9 : VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
2078 :
2079 18 : return GDALDataset::FromHandle(hDS)->SetGCPs(
2080 9 : nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
2081 : }
2082 :
2083 : /************************************************************************/
2084 : /* BuildOverviews() */
2085 : /************************************************************************/
2086 :
2087 : /**
2088 : * \brief Build raster overview(s)
2089 : *
2090 : * If the operation is unsupported for the indicated dataset, then
2091 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
2092 : * CPLE_NotSupported.
2093 : *
2094 : * Depending on the actual file format, all overviews level can be also
2095 : * deleted by specifying nOverviews == 0. This works at least for external
2096 : * overviews (.ovr), TIFF internal overviews, etc.
2097 : *
2098 : * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
2099 : * to "ALL_CPUS" or a integer value to specify the number of threads to use for
2100 : * overview computation.
2101 : *
2102 : * This method is the same as the C function GDALBuildOverviewsEx().
2103 : *
2104 : * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
2105 : * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
2106 : * or "NONE" controlling the downsampling method applied.
2107 : * @param nOverviews number of overviews to build, or 0 to clean overviews.
2108 : * @param panOverviewList the list of overview decimation factors (positive
2109 : * integers, normally larger or equal to 2) to build, or
2110 : * NULL if nOverviews == 0.
2111 : * @param nListBands number of bands to build overviews for in panBandList.
2112 : * Build for all bands if this is 0.
2113 : * @param panBandList list of band numbers.
2114 : * @param pfnProgress a function to call to report progress, or NULL.
2115 : * @param pProgressData application data to pass to the progress function.
2116 : * @param papszOptions (GDAL >= 3.6) NULL terminated list of options as
2117 : * key=value pairs, or NULL
2118 : *
2119 : * @return CE_None on success or CE_Failure if the operation doesn't work.
2120 : *
2121 : * For example, to build overview level 2, 4 and 8 on all bands the following
2122 : * call could be made:
2123 : * \code{.cpp}
2124 : * int anOverviewList[3] = { 2, 4, 8 };
2125 : *
2126 : * poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
2127 : * GDALDummyProgress, nullptr );
2128 : * \endcode
2129 : *
2130 : * @see GDALRegenerateOverviewsEx()
2131 : */
2132 :
2133 672 : CPLErr GDALDataset::BuildOverviews(const char *pszResampling, int nOverviews,
2134 : const int *panOverviewList, int nListBands,
2135 : const int *panBandList,
2136 : GDALProgressFunc pfnProgress,
2137 : void *pProgressData,
2138 : CSLConstList papszOptions)
2139 : {
2140 672 : int *panAllBandList = nullptr;
2141 :
2142 672 : if (nListBands == 0)
2143 : {
2144 661 : nListBands = GetRasterCount();
2145 : panAllBandList =
2146 661 : static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
2147 1751 : for (int i = 0; i < nListBands; ++i)
2148 1090 : panAllBandList[i] = i + 1;
2149 :
2150 661 : panBandList = panAllBandList;
2151 : }
2152 :
2153 672 : if (pfnProgress == nullptr)
2154 640 : pfnProgress = GDALDummyProgress;
2155 :
2156 1663 : for (int i = 0; i < nOverviews; ++i)
2157 : {
2158 992 : if (panOverviewList[i] <= 0)
2159 : {
2160 1 : CPLError(CE_Failure, CPLE_IllegalArg,
2161 : "panOverviewList[%d] = %d is invalid. It must be a "
2162 : "positive value",
2163 1 : i, panOverviewList[i]);
2164 1 : CPLFree(panAllBandList);
2165 1 : return CE_Failure;
2166 : }
2167 : }
2168 :
2169 : // At time of writing, all overview generation options are actually
2170 : // expected to be passed as configuration options.
2171 671 : std::vector<std::unique_ptr<CPLConfigOptionSetter>> apoConfigOptionSetter;
2172 705 : for (const auto &[pszKey, pszValue] : cpl::IterateNameValue(papszOptions))
2173 : {
2174 : apoConfigOptionSetter.emplace_back(
2175 34 : std::make_unique<CPLConfigOptionSetter>(pszKey, pszValue, false));
2176 : }
2177 :
2178 : const CPLErr eErr =
2179 1342 : IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
2180 671 : panBandList, pfnProgress, pProgressData, papszOptions);
2181 :
2182 671 : if (panAllBandList != nullptr)
2183 659 : CPLFree(panAllBandList);
2184 :
2185 671 : return eErr;
2186 : }
2187 :
2188 : /************************************************************************/
2189 : /* GDALBuildOverviews() */
2190 : /************************************************************************/
2191 :
2192 : /**
2193 : * \brief Build raster overview(s)
2194 : *
2195 : * @see GDALDataset::BuildOverviews() and GDALBuildOverviews()
2196 : */
2197 :
2198 30 : CPLErr CPL_STDCALL GDALBuildOverviews(GDALDatasetH hDataset,
2199 : const char *pszResampling, int nOverviews,
2200 : const int *panOverviewList,
2201 : int nListBands, const int *panBandList,
2202 : GDALProgressFunc pfnProgress,
2203 : void *pProgressData)
2204 :
2205 : {
2206 30 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2207 :
2208 30 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2209 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2210 30 : pfnProgress, pProgressData, nullptr);
2211 : }
2212 :
2213 : /************************************************************************/
2214 : /* GDALBuildOverviews() */
2215 : /************************************************************************/
2216 :
2217 : /**
2218 : * \brief Build raster overview(s)
2219 : *
2220 : * @see GDALDataset::BuildOverviews()
2221 : * @since GDAL 3.6
2222 : */
2223 :
2224 : CPLErr CPL_STDCALL
2225 623 : GDALBuildOverviewsEx(GDALDatasetH hDataset, const char *pszResampling,
2226 : int nOverviews, const int *panOverviewList, int nListBands,
2227 : const int *panBandList, GDALProgressFunc pfnProgress,
2228 : void *pProgressData, CSLConstList papszOptions)
2229 :
2230 : {
2231 623 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2232 :
2233 623 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2234 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2235 623 : pfnProgress, pProgressData, papszOptions);
2236 : }
2237 :
2238 : /************************************************************************/
2239 : /* IBuildOverviews() */
2240 : /* */
2241 : /* Default implementation. */
2242 : /************************************************************************/
2243 :
2244 : //! @cond Doxygen_Suppress
2245 188 : CPLErr GDALDataset::IBuildOverviews(const char *pszResampling, int nOverviews,
2246 : const int *panOverviewList, int nListBands,
2247 : const int *panBandList,
2248 : GDALProgressFunc pfnProgress,
2249 : void *pProgressData,
2250 : CSLConstList papszOptions)
2251 :
2252 : {
2253 188 : if (oOvManager.IsInitialized())
2254 187 : return oOvManager.BuildOverviews(
2255 : nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2256 187 : panBandList, pfnProgress, pProgressData, papszOptions);
2257 : else
2258 : {
2259 1 : ReportError(CE_Failure, CPLE_NotSupported,
2260 : "BuildOverviews() not supported for this dataset.");
2261 :
2262 1 : return CE_Failure;
2263 : }
2264 : }
2265 :
2266 : //! @endcond
2267 :
2268 : /************************************************************************/
2269 : /* IRasterIO() */
2270 : /* */
2271 : /* The default implementation of IRasterIO() is, in the general */
2272 : /* case to pass the request off to each band objects rasterio */
2273 : /* methods with appropriate arguments. In some cases, it might */
2274 : /* choose instead the BlockBasedRasterIO() implementation. */
2275 : /************************************************************************/
2276 :
2277 : //! @cond Doxygen_Suppress
2278 439897 : CPLErr GDALDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2279 : int nXSize, int nYSize, void *pData,
2280 : int nBufXSize, int nBufYSize,
2281 : GDALDataType eBufType, int nBandCount,
2282 : BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,
2283 : GSpacing nLineSpace, GSpacing nBandSpace,
2284 : GDALRasterIOExtraArg *psExtraArg)
2285 :
2286 : {
2287 439897 : const char *pszInterleave = nullptr;
2288 :
2289 439897 : CPLAssert(nullptr != pData);
2290 :
2291 439897 : const bool bHasSubpixelShift =
2292 440993 : psExtraArg->bFloatingPointWindowValidity &&
2293 440081 : psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2294 184 : (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2295 :
2296 439797 : if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&
2297 69741 : nBandCount > 1 &&
2298 69741 : (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2299 879694 : nullptr &&
2300 65782 : EQUAL(pszInterleave, "PIXEL"))
2301 : {
2302 63598 : return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2303 : nBufXSize, nBufYSize, eBufType, nBandCount,
2304 : panBandMap, nPixelSpace, nLineSpace,
2305 63598 : nBandSpace, psExtraArg);
2306 : }
2307 :
2308 376299 : if (eRWFlag == GF_Read &&
2309 199595 : (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2310 199420 : psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2311 199419 : psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2312 199595 : psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2313 338 : !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)
2314 : {
2315 314 : if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())
2316 : {
2317 157 : int bTried = FALSE;
2318 157 : const CPLErr eErr = TryOverviewRasterIO(
2319 : eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
2320 : nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
2321 : nLineSpace, nBandSpace, psExtraArg, &bTried);
2322 157 : if (bTried)
2323 1 : return eErr;
2324 : }
2325 :
2326 313 : GDALDataType eFirstBandDT = GDT_Unknown;
2327 313 : int nFirstMaskFlags = 0;
2328 313 : GDALRasterBand *poFirstMaskBand = nullptr;
2329 313 : int nOKBands = 0;
2330 :
2331 : // Check if bands share the same mask band
2332 1277 : for (int i = 0; i < nBandCount; ++i)
2333 : {
2334 1050 : GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2335 1560 : if ((nBufXSize < nXSize || nBufYSize < nYSize) &&
2336 504 : poBand->GetOverviewCount())
2337 : {
2338 : // Could be improved to select the appropriate overview.
2339 3 : break;
2340 : }
2341 1053 : if (poBand->GetColorTable() != nullptr)
2342 : {
2343 0 : break;
2344 : }
2345 1057 : const GDALDataType eDT = poBand->GetRasterDataType();
2346 1059 : if (GDALDataTypeIsComplex(eDT))
2347 : {
2348 30 : break;
2349 : }
2350 1022 : if (i == 0)
2351 : {
2352 280 : eFirstBandDT = eDT;
2353 280 : nFirstMaskFlags = poBand->GetMaskFlags();
2354 283 : if (nFirstMaskFlags == GMF_NODATA)
2355 : {
2356 : // The dataset-level resampling code is not ready for nodata
2357 : // Fallback to band-level resampling
2358 6 : break;
2359 : }
2360 277 : poFirstMaskBand = poBand->GetMaskBand();
2361 : }
2362 : else
2363 : {
2364 742 : if (eDT != eFirstBandDT)
2365 : {
2366 0 : break;
2367 : }
2368 742 : int nMaskFlags = poBand->GetMaskFlags();
2369 744 : if (nMaskFlags == GMF_NODATA)
2370 : {
2371 : // The dataset-level resampling code is not ready for nodata
2372 : // Fallback to band-level resampling
2373 0 : break;
2374 : }
2375 744 : GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2376 739 : if (nFirstMaskFlags == GMF_ALL_VALID &&
2377 : nMaskFlags == GMF_ALL_VALID)
2378 : {
2379 : // Ok.
2380 : }
2381 165 : else if (poFirstMaskBand == poMaskBand)
2382 : {
2383 : // Ok.
2384 : }
2385 : else
2386 : {
2387 55 : break;
2388 : }
2389 : }
2390 :
2391 964 : ++nOKBands;
2392 : }
2393 :
2394 321 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2395 321 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2396 :
2397 321 : CPLErr eErr = CE_None;
2398 321 : if (nOKBands > 0)
2399 : {
2400 281 : if (nOKBands < nBandCount)
2401 : {
2402 55 : psExtraArg->pfnProgress = GDALScaledProgress;
2403 110 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2404 55 : 0.0, static_cast<double>(nOKBands) / nBandCount,
2405 : pfnProgressGlobal, pProgressDataGlobal);
2406 55 : if (psExtraArg->pProgressData == nullptr)
2407 53 : psExtraArg->pfnProgress = nullptr;
2408 : }
2409 :
2410 281 : eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2411 : pData, nBufXSize, nBufYSize, eBufType,
2412 : nOKBands, panBandMap, nPixelSpace,
2413 : nLineSpace, nBandSpace, psExtraArg);
2414 :
2415 284 : if (nOKBands < nBandCount)
2416 : {
2417 55 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2418 : }
2419 : }
2420 324 : if (eErr == CE_None && nOKBands < nBandCount)
2421 : {
2422 92 : if (nOKBands > 0)
2423 : {
2424 53 : psExtraArg->pfnProgress = GDALScaledProgress;
2425 106 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2426 53 : static_cast<double>(nOKBands) / nBandCount, 1.0,
2427 : pfnProgressGlobal, pProgressDataGlobal);
2428 53 : if (psExtraArg->pProgressData == nullptr)
2429 51 : psExtraArg->pfnProgress = nullptr;
2430 : }
2431 184 : eErr = BandBasedRasterIO(
2432 : eRWFlag, nXOff, nYOff, nXSize, nYSize,
2433 92 : static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,
2434 : nBufYSize, eBufType, nBandCount - nOKBands,
2435 92 : panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,
2436 : psExtraArg);
2437 92 : if (nOKBands > 0)
2438 : {
2439 53 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2440 : }
2441 : }
2442 :
2443 323 : psExtraArg->pfnProgress = pfnProgressGlobal;
2444 323 : psExtraArg->pProgressData = pProgressDataGlobal;
2445 :
2446 323 : return eErr;
2447 : }
2448 :
2449 375985 : return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2450 : nBufXSize, nBufYSize, eBufType, nBandCount,
2451 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2452 375977 : psExtraArg);
2453 : }
2454 :
2455 : //! @endcond
2456 :
2457 : /************************************************************************/
2458 : /* BandBasedRasterIO() */
2459 : /* */
2460 : /* Pass the request off to each band objects rasterio methods with */
2461 : /* appropriate arguments. */
2462 : /************************************************************************/
2463 :
2464 : //! @cond Doxygen_Suppress
2465 640514 : CPLErr GDALDataset::BandBasedRasterIO(
2466 : GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
2467 : void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
2468 : int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
2469 : GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
2470 :
2471 : {
2472 : int iBandIndex;
2473 640514 : CPLErr eErr = CE_None;
2474 :
2475 640514 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2476 640514 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2477 :
2478 1575100 : for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
2479 : ++iBandIndex)
2480 : {
2481 934575 : GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2482 :
2483 934583 : if (poBand == nullptr)
2484 : {
2485 0 : eErr = CE_Failure;
2486 0 : break;
2487 : }
2488 :
2489 934583 : GByte *pabyBandData =
2490 934583 : static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2491 :
2492 934583 : if (nBandCount > 1)
2493 : {
2494 432313 : psExtraArg->pfnProgress = GDALScaledProgress;
2495 864630 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2496 : 1.0 * iBandIndex / nBandCount,
2497 432313 : 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2498 : pProgressDataGlobal);
2499 432317 : if (psExtraArg->pProgressData == nullptr)
2500 428747 : psExtraArg->pfnProgress = nullptr;
2501 : }
2502 :
2503 1869180 : eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2504 : pabyBandData, nBufXSize, nBufYSize, eBufType,
2505 934587 : nPixelSpace, nLineSpace, psExtraArg);
2506 :
2507 934598 : if (nBandCount > 1)
2508 432334 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2509 : }
2510 :
2511 640529 : psExtraArg->pfnProgress = pfnProgressGlobal;
2512 640529 : psExtraArg->pProgressData = pProgressDataGlobal;
2513 :
2514 640529 : return eErr;
2515 : }
2516 :
2517 : //! @endcond
2518 :
2519 : /************************************************************************/
2520 : /* ValidateRasterIOOrAdviseReadParameters() */
2521 : /************************************************************************/
2522 :
2523 : //! @cond Doxygen_Suppress
2524 731046 : CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
2525 : const char *pszCallingFunc, int *pbStopProcessingOnCENone, int nXOff,
2526 : int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize,
2527 : int nBandCount, const int *panBandMap)
2528 : {
2529 :
2530 : /* -------------------------------------------------------------------- */
2531 : /* Some size values are "noop". Lets just return to avoid */
2532 : /* stressing lower level functions. */
2533 : /* -------------------------------------------------------------------- */
2534 731046 : if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)
2535 : {
2536 16 : CPLDebug("GDAL",
2537 : "%s skipped for odd window or buffer size.\n"
2538 : " Window = (%d,%d)x%dx%d\n"
2539 : " Buffer = %dx%d",
2540 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2541 : nBufYSize);
2542 :
2543 4 : *pbStopProcessingOnCENone = TRUE;
2544 4 : return CE_None;
2545 : }
2546 :
2547 731030 : CPLErr eErr = CE_None;
2548 731030 : *pbStopProcessingOnCENone = FALSE;
2549 :
2550 731030 : if (nXOff < 0 || nXOff > INT_MAX - nXSize ||
2551 731031 : nXOff + nXSize > nRasterXSize || nYOff < 0 ||
2552 731033 : nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)
2553 : {
2554 2 : ReportError(CE_Failure, CPLE_IllegalArg,
2555 : "Access window out of range in %s. Requested "
2556 : "(%d,%d) of size %dx%d on raster of %dx%d.",
2557 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
2558 : nRasterYSize);
2559 2 : eErr = CE_Failure;
2560 : }
2561 :
2562 731030 : if (panBandMap == nullptr && nBandCount > GetRasterCount())
2563 : {
2564 0 : ReportError(CE_Failure, CPLE_IllegalArg,
2565 : "%s: nBandCount cannot be greater than %d", pszCallingFunc,
2566 : GetRasterCount());
2567 2 : eErr = CE_Failure;
2568 : }
2569 :
2570 2044240 : for (int i = 0; i < nBandCount && eErr == CE_None; ++i)
2571 : {
2572 1313200 : int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2573 1313200 : if (iBand < 1 || iBand > GetRasterCount())
2574 : {
2575 3 : ReportError(
2576 : CE_Failure, CPLE_IllegalArg,
2577 : "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
2578 : pszCallingFunc, i, iBand);
2579 3 : eErr = CE_Failure;
2580 : }
2581 :
2582 1313200 : if (eErr == CE_None && GetRasterBand(iBand) == nullptr)
2583 : {
2584 0 : ReportError(
2585 : CE_Failure, CPLE_IllegalArg,
2586 : "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
2587 : pszCallingFunc, i, iBand);
2588 0 : eErr = CE_Failure;
2589 : }
2590 : }
2591 :
2592 731037 : return eErr;
2593 : }
2594 :
2595 : //! @endcond
2596 :
2597 : /************************************************************************/
2598 : /* RasterIO() */
2599 : /************************************************************************/
2600 :
2601 : /**
2602 : * \brief Read/write a region of image data from multiple bands.
2603 : *
2604 : * This method allows reading a region of one or more GDALRasterBands from
2605 : * this dataset into a buffer, or writing data from a buffer into a region
2606 : * of the GDALRasterBands. It automatically takes care of data type
2607 : * translation if the data type (eBufType) of the buffer is different than
2608 : * that of the GDALRasterBand.
2609 : * The method also takes care of image decimation / replication if the
2610 : * buffer size (nBufXSize x nBufYSize) is different than the size of the
2611 : * region being accessed (nXSize x nYSize).
2612 : *
2613 : * The window of interest expressed by (nXOff, nYOff, nXSize, nYSize) should be
2614 : * fully within the raster space, that is nXOff >= 0, nYOff >= 0,
2615 : * nXOff + nXSize <= GetRasterXSize() and nYOff + nYSize <= GetRasterYSize().
2616 : * If reads larger than the raster space are wished, GDALTranslate() might be used.
2617 : * Or use nLineSpace and a possibly shifted pData value.
2618 : *
2619 : * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
2620 : * writing from various organization of buffers.
2621 : *
2622 : * Some formats may efficiently implement decimation into a buffer by
2623 : * reading from lower resolution overview images. The logic of the default
2624 : * implementation in the base class GDALRasterBand is the following one. It
2625 : * computes a target_downscaling_factor from the window of interest and buffer
2626 : * size which is min(nXSize/nBufXSize, nYSize/nBufYSize).
2627 : * It then walks through overviews and will select the first one whose
2628 : * downscaling factor is greater than target_downscaling_factor / 1.2.
2629 : *
2630 : * Let's assume we have overviews at downscaling factors 2, 4 and 8.
2631 : * The relationship between target_downscaling_factor and the select overview
2632 : * level is the following one:
2633 : *
2634 : * target_downscaling_factor | selected_overview
2635 : * ------------------------- | -----------------
2636 : * ]0, 2 / 1.2] | full resolution band
2637 : * ]2 / 1.2, 4 / 1.2] | 2x downsampled band
2638 : * ]4 / 1.2, 8 / 1.2] | 4x downsampled band
2639 : * ]8 / 1.2, infinity[ | 8x downsampled band
2640 : *
2641 : * Note that starting with GDAL 3.9, this 1.2 oversampling factor can be
2642 : * modified by setting the GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD configuration
2643 : * option. Also note that starting with GDAL 3.9, when the resampling algorithm
2644 : * specified in psExtraArg->eResampleAlg is different from GRIORA_NearestNeighbour,
2645 : * this oversampling threshold defaults to 1. Consequently if there are overviews
2646 : * of downscaling factor 2, 4 and 8, and the desired downscaling factor is
2647 : * 7.99, the overview of factor 4 will be selected for a non nearest resampling.
2648 : *
2649 : * For highest performance full resolution data access, read and write
2650 : * on "block boundaries" as returned by GetBlockSize(), or use the
2651 : * ReadBlock() and WriteBlock() methods.
2652 : *
2653 : * This method is the same as the C GDALDatasetRasterIO() or
2654 : * GDALDatasetRasterIOEx() functions.
2655 : *
2656 : * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
2657 : * write a region of data.
2658 : *
2659 : * @param nXOff The pixel offset to the top left corner of the region
2660 : * of the band to be accessed. This would be zero to start from the left side.
2661 : *
2662 : * @param nYOff The line offset to the top left corner of the region
2663 : * of the band to be accessed. This would be zero to start from the top.
2664 : *
2665 : * @param nXSize The width of the region of the band to be accessed in pixels.
2666 : *
2667 : * @param nYSize The height of the region of the band to be accessed in lines.
2668 : *
2669 : * @param pData The buffer into which the data should be read, or from which
2670 : * it should be written. This buffer must contain at least
2671 : * nBufXSize * nBufYSize * nBandCount words of type eBufType. It is organized
2672 : * in left to right,top to bottom pixel order. Spacing is controlled by the
2673 : * nPixelSpace, and nLineSpace parameters.
2674 : * Note that even with eRWFlag==GF_Write, the content of the buffer might be
2675 : * temporarily modified during the execution of this method (and eventually
2676 : * restored back to its original content), so it is not safe to use a buffer
2677 : * stored in a read-only section of the calling program.
2678 : *
2679 : * @param nBufXSize the width of the buffer image into which the desired region
2680 : * is to be read, or from which it is to be written.
2681 : *
2682 : * @param nBufYSize the height of the buffer image into which the desired
2683 : * region is to be read, or from which it is to be written.
2684 : *
2685 : * @param eBufType the type of the pixel values in the pData data buffer. The
2686 : * pixel values will automatically be translated to/from the GDALRasterBand
2687 : * data type as needed. Most driver implementations will use GDALCopyWords64()
2688 : * to perform data type translation.
2689 : *
2690 : * @param nBandCount the number of bands being read or written.
2691 : *
2692 : * @param panBandMap the list of nBandCount band numbers being read/written.
2693 : * Note band numbers are 1 based. This may be NULL to select the first
2694 : * nBandCount bands. (Note: before GDAL 3.10, argument type was "int*", and
2695 : * not "const int*")
2696 : *
2697 : * @param nPixelSpace The byte offset from the start of one pixel value in
2698 : * pData to the start of the next pixel value within a scanline. If defaulted
2699 : * (0) the size of the datatype eBufType is used.
2700 : *
2701 : * @param nLineSpace The byte offset from the start of one scanline in
2702 : * pData to the start of the next. If defaulted (0) the size of the datatype
2703 : * eBufType * nBufXSize is used.
2704 : *
2705 : * @param nBandSpace the byte offset from the start of one bands data to the
2706 : * start of the next. If defaulted (0) the value will be
2707 : * nLineSpace * nBufYSize implying band sequential organization
2708 : * of the data buffer.
2709 : *
2710 : * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
2711 : * structure with additional arguments to specify resampling and progress
2712 : * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
2713 : * configuration option can also be defined to override the default resampling
2714 : * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
2715 : *
2716 : * @return CE_Failure if the access fails, otherwise CE_None.
2717 : */
2718 :
2719 718377 : CPLErr GDALDataset::RasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2720 : int nXSize, int nYSize, void *pData, int nBufXSize,
2721 : int nBufYSize, GDALDataType eBufType,
2722 : int nBandCount, const int *panBandMap,
2723 : GSpacing nPixelSpace, GSpacing nLineSpace,
2724 : GSpacing nBandSpace,
2725 : GDALRasterIOExtraArg *psExtraArg)
2726 :
2727 : {
2728 : GDALRasterIOExtraArg sExtraArg;
2729 718377 : if (psExtraArg == nullptr)
2730 : {
2731 532739 : INIT_RASTERIO_EXTRA_ARG(sExtraArg);
2732 :
2733 : // 4 below inits are not strictly needed but make Coverity Scan
2734 : // happy
2735 532739 : sExtraArg.dfXOff = nXOff;
2736 532739 : sExtraArg.dfYOff = nYOff;
2737 532739 : sExtraArg.dfXSize = nXSize;
2738 532739 : sExtraArg.dfYSize = nYSize;
2739 :
2740 532739 : psExtraArg = &sExtraArg;
2741 : }
2742 185638 : else if (CPL_UNLIKELY(psExtraArg->nVersion !=
2743 : RASTERIO_EXTRA_ARG_CURRENT_VERSION))
2744 : {
2745 0 : ReportError(CE_Failure, CPLE_AppDefined,
2746 : "Unhandled version of GDALRasterIOExtraArg");
2747 0 : return CE_Failure;
2748 : }
2749 :
2750 718377 : GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
2751 : nBufYSize);
2752 :
2753 718361 : if (CPL_UNLIKELY(nullptr == pData))
2754 : {
2755 0 : ReportError(CE_Failure, CPLE_AppDefined,
2756 : "The buffer into which the data should be read is null");
2757 0 : return CE_Failure;
2758 : }
2759 :
2760 : /* -------------------------------------------------------------------- */
2761 : /* Do some validation of parameters. */
2762 : /* -------------------------------------------------------------------- */
2763 :
2764 718361 : if (CPL_UNLIKELY(eRWFlag != GF_Read && eRWFlag != GF_Write))
2765 : {
2766 0 : ReportError(
2767 : CE_Failure, CPLE_IllegalArg,
2768 : "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
2769 : eRWFlag);
2770 0 : return CE_Failure;
2771 : }
2772 :
2773 718361 : if (eRWFlag == GF_Write)
2774 : {
2775 213595 : if (CPL_UNLIKELY(eAccess != GA_Update))
2776 : {
2777 2 : ReportError(CE_Failure, CPLE_AppDefined,
2778 : "Write operation not permitted on dataset opened "
2779 : "in read-only mode");
2780 2 : return CE_Failure;
2781 : }
2782 : }
2783 :
2784 718359 : int bStopProcessing = FALSE;
2785 718359 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2786 : "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2787 : nBufYSize, nBandCount, panBandMap);
2788 718370 : if (eErr != CE_None || bStopProcessing)
2789 21 : return eErr;
2790 718349 : if (CPL_UNLIKELY(eBufType == GDT_Unknown || eBufType == GDT_TypeCount))
2791 : {
2792 2 : ReportError(CE_Failure, CPLE_AppDefined,
2793 : "Illegal GDT_Unknown/GDT_TypeCount argument");
2794 2 : return CE_Failure;
2795 : }
2796 :
2797 : /* -------------------------------------------------------------------- */
2798 : /* If pixel and line spacing are defaulted assign reasonable */
2799 : /* value assuming a packed buffer. */
2800 : /* -------------------------------------------------------------------- */
2801 718347 : if (nPixelSpace == 0)
2802 417333 : nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
2803 :
2804 718349 : if (nLineSpace == 0)
2805 : {
2806 520268 : nLineSpace = nPixelSpace * nBufXSize;
2807 : }
2808 :
2809 718349 : if (nBandSpace == 0 && nBandCount > 1)
2810 : {
2811 67469 : nBandSpace = nLineSpace * nBufYSize;
2812 : }
2813 :
2814 718349 : if (panBandMap == nullptr)
2815 : {
2816 354367 : if (!m_poPrivate)
2817 0 : return CE_Failure;
2818 354367 : CPLAssert(static_cast<int>(m_poPrivate->m_anBandMap.size()) == nBands);
2819 354367 : panBandMap = m_poPrivate->m_anBandMap.data();
2820 : }
2821 :
2822 718349 : int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
2823 :
2824 : /* -------------------------------------------------------------------- */
2825 : /* We are being forced to use cached IO instead of a driver */
2826 : /* specific implementation. */
2827 : /* -------------------------------------------------------------------- */
2828 718356 : if (bForceCachedIO)
2829 : {
2830 18 : eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2831 : nBufXSize, nBufYSize, eBufType, nBandCount,
2832 : panBandMap, nPixelSpace, nLineSpace,
2833 18 : nBandSpace, psExtraArg);
2834 : }
2835 :
2836 : /* -------------------------------------------------------------------- */
2837 : /* Call the format specific function. */
2838 : /* -------------------------------------------------------------------- */
2839 : else
2840 : {
2841 718345 : eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2842 : nBufXSize, nBufYSize, eBufType, nBandCount,
2843 : // TODO: remove this const_cast once IRasterIO()
2844 : // takes a const int*
2845 : const_cast<int *>(panBandMap), nPixelSpace, nLineSpace,
2846 718338 : nBandSpace, psExtraArg);
2847 : }
2848 :
2849 718363 : if (bCallLeaveReadWrite)
2850 401565 : LeaveReadWrite();
2851 :
2852 718363 : return eErr;
2853 : }
2854 :
2855 : /************************************************************************/
2856 : /* GDALDatasetRasterIO() */
2857 : /************************************************************************/
2858 :
2859 : /**
2860 : * \brief Read/write a region of image data from multiple bands.
2861 : *
2862 : * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
2863 : * resolution, progress callback, etc. are needed)
2864 : *
2865 : * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
2866 : *
2867 : * @see GDALDataset::RasterIO()
2868 : */
2869 :
2870 4398 : CPLErr CPL_STDCALL GDALDatasetRasterIO(GDALDatasetH hDS, GDALRWFlag eRWFlag,
2871 : int nXOff, int nYOff, int nXSize,
2872 : int nYSize, void *pData, int nBufXSize,
2873 : int nBufYSize, GDALDataType eBufType,
2874 : int nBandCount, const int *panBandMap,
2875 : int nPixelSpace, int nLineSpace,
2876 : int nBandSpace)
2877 :
2878 : {
2879 4398 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
2880 :
2881 4398 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2882 :
2883 4398 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2884 : nBufXSize, nBufYSize, eBufType, nBandCount,
2885 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2886 4398 : nullptr);
2887 : }
2888 :
2889 : /************************************************************************/
2890 : /* GDALDatasetRasterIOEx() */
2891 : /************************************************************************/
2892 :
2893 : /**
2894 : * \brief Read/write a region of image data from multiple bands.
2895 : *
2896 : * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
2897 : *
2898 : * @see GDALDataset::RasterIO()
2899 : * @since GDAL 2.0
2900 : */
2901 :
2902 352188 : CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
2903 : GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
2904 : int nYSize, void *pData, int nBufXSize, int nBufYSize,
2905 : GDALDataType eBufType, int nBandCount, const int *panBandMap,
2906 : GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
2907 : GDALRasterIOExtraArg *psExtraArg)
2908 :
2909 : {
2910 352188 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
2911 :
2912 352188 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2913 :
2914 352188 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2915 : nBufXSize, nBufYSize, eBufType, nBandCount,
2916 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2917 352188 : psExtraArg);
2918 : }
2919 :
2920 : /************************************************************************/
2921 : /* GetOpenDatasets() */
2922 : /************************************************************************/
2923 :
2924 : /**
2925 : * \brief Fetch all open GDAL dataset handles.
2926 : *
2927 : * This method is the same as the C function GDALGetOpenDatasets().
2928 : *
2929 : * NOTE: This method is not thread safe. The returned list may change
2930 : * at any time and it should not be freed.
2931 : *
2932 : * @param pnCount integer into which to place the count of dataset pointers
2933 : * being returned.
2934 : *
2935 : * @return a pointer to an array of dataset handles.
2936 : */
2937 :
2938 1899 : GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)
2939 :
2940 : {
2941 3798 : CPLMutexHolderD(&hDLMutex);
2942 :
2943 1899 : if (poAllDatasetMap == nullptr)
2944 : {
2945 1874 : *pnCount = 0;
2946 1874 : return nullptr;
2947 : }
2948 :
2949 25 : *pnCount = static_cast<int>(poAllDatasetMap->size());
2950 25 : ppDatasets = static_cast<GDALDataset **>(
2951 25 : CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
2952 25 : std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();
2953 683 : for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)
2954 658 : ppDatasets[i] = oIter->first;
2955 25 : return ppDatasets;
2956 : }
2957 :
2958 : /************************************************************************/
2959 : /* GDALGetOpenDatasets() */
2960 : /************************************************************************/
2961 :
2962 : /**
2963 : * \brief Fetch all open GDAL dataset handles.
2964 : *
2965 : * @see GDALDataset::GetOpenDatasets()
2966 : */
2967 :
2968 0 : void CPL_STDCALL GDALGetOpenDatasets(GDALDatasetH **ppahDSList, int *pnCount)
2969 :
2970 : {
2971 0 : VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
2972 0 : VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
2973 :
2974 0 : *ppahDSList =
2975 0 : reinterpret_cast<GDALDatasetH *>(GDALDataset::GetOpenDatasets(pnCount));
2976 : }
2977 :
2978 : /************************************************************************/
2979 : /* GDALCleanOpenDatasetsList() */
2980 : /************************************************************************/
2981 :
2982 : // Useful when called from the child of a fork(), to avoid closing
2983 : // the datasets of the parent at the child termination.
2984 0 : void GDALNullifyOpenDatasetsList()
2985 : {
2986 0 : poAllDatasetMap = nullptr;
2987 0 : phSharedDatasetSet = nullptr;
2988 0 : ppDatasets = nullptr;
2989 0 : hDLMutex = nullptr;
2990 0 : }
2991 :
2992 : /************************************************************************/
2993 : /* GDALGetAccess() */
2994 : /************************************************************************/
2995 :
2996 : /**
2997 : * \brief Return access flag
2998 : *
2999 : * @see GDALDataset::GetAccess()
3000 : */
3001 :
3002 0 : int CPL_STDCALL GDALGetAccess(GDALDatasetH hDS)
3003 : {
3004 0 : VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
3005 :
3006 0 : return GDALDataset::FromHandle(hDS)->GetAccess();
3007 : }
3008 :
3009 : /************************************************************************/
3010 : /* AdviseRead() */
3011 : /************************************************************************/
3012 :
3013 : /**
3014 : * \brief Advise driver of upcoming read requests.
3015 : *
3016 : * Some GDAL drivers operate more efficiently if they know in advance what
3017 : * set of upcoming read requests will be made. The AdviseRead() method allows
3018 : * an application to notify the driver of the region and bands of interest,
3019 : * and at what resolution the region will be read.
3020 : *
3021 : * Many drivers just ignore the AdviseRead() call, but it can dramatically
3022 : * accelerate access via some drivers.
3023 : *
3024 : * Depending on call paths, drivers might receive several calls to
3025 : * AdviseRead() with the same parameters.
3026 : *
3027 : * @param nXOff The pixel offset to the top left corner of the region
3028 : * of the band to be accessed. This would be zero to start from the left side.
3029 : *
3030 : * @param nYOff The line offset to the top left corner of the region
3031 : * of the band to be accessed. This would be zero to start from the top.
3032 : *
3033 : * @param nXSize The width of the region of the band to be accessed in pixels.
3034 : *
3035 : * @param nYSize The height of the region of the band to be accessed in lines.
3036 : *
3037 : * @param nBufXSize the width of the buffer image into which the desired region
3038 : * is to be read, or from which it is to be written.
3039 : *
3040 : * @param nBufYSize the height of the buffer image into which the desired
3041 : * region is to be read, or from which it is to be written.
3042 : *
3043 : * @param eBufType the type of the pixel values in the pData data buffer. The
3044 : * pixel values will automatically be translated to/from the GDALRasterBand
3045 : * data type as needed.
3046 : *
3047 : * @param nBandCount the number of bands being read or written.
3048 : *
3049 : * @param panBandMap the list of nBandCount band numbers being read/written.
3050 : * Note band numbers are 1 based. This may be NULL to select the first
3051 : * nBandCount bands.
3052 : *
3053 : * @param papszOptions a list of name=value strings with special control
3054 : * options. Normally this is NULL.
3055 : *
3056 : * @return CE_Failure if the request is invalid and CE_None if it works or
3057 : * is ignored.
3058 : */
3059 :
3060 12426 : CPLErr GDALDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
3061 : int nBufXSize, int nBufYSize,
3062 : GDALDataType eBufType, int nBandCount,
3063 : int *panBandMap, char **papszOptions)
3064 :
3065 : {
3066 : /* -------------------------------------------------------------------- */
3067 : /* Do some validation of parameters. */
3068 : /* -------------------------------------------------------------------- */
3069 12426 : int bStopProcessing = FALSE;
3070 12426 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3071 : "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
3072 : nBufXSize, nBufYSize, nBandCount, panBandMap);
3073 12426 : if (eErr != CE_None || bStopProcessing)
3074 0 : return eErr;
3075 :
3076 54519 : for (int iBand = 0; iBand < nBandCount; ++iBand)
3077 : {
3078 42093 : GDALRasterBand *poBand = nullptr;
3079 :
3080 42093 : if (panBandMap == nullptr)
3081 40813 : poBand = GetRasterBand(iBand + 1);
3082 : else
3083 1280 : poBand = GetRasterBand(panBandMap[iBand]);
3084 :
3085 42093 : if (poBand == nullptr)
3086 0 : return CE_Failure;
3087 :
3088 84186 : eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
3089 42093 : nBufYSize, eBufType, papszOptions);
3090 :
3091 42093 : if (eErr != CE_None)
3092 0 : return eErr;
3093 : }
3094 :
3095 12426 : return CE_None;
3096 : }
3097 :
3098 : /************************************************************************/
3099 : /* GDALDatasetAdviseRead() */
3100 : /************************************************************************/
3101 :
3102 : /**
3103 : * \brief Advise driver of upcoming read requests.
3104 : *
3105 : * @see GDALDataset::AdviseRead()
3106 : */
3107 1 : CPLErr CPL_STDCALL GDALDatasetAdviseRead(GDALDatasetH hDS, int nXOff, int nYOff,
3108 : int nXSize, int nYSize, int nBufXSize,
3109 : int nBufYSize, GDALDataType eDT,
3110 : int nBandCount, int *panBandMap,
3111 : CSLConstList papszOptions)
3112 :
3113 : {
3114 1 : VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
3115 :
3116 2 : return GDALDataset::FromHandle(hDS)->AdviseRead(
3117 : nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount,
3118 1 : panBandMap, const_cast<char **>(papszOptions));
3119 : }
3120 :
3121 : /************************************************************************/
3122 : /* GDALAntiRecursionStruct */
3123 : /************************************************************************/
3124 :
3125 : // Prevent infinite recursion.
3126 : struct GDALAntiRecursionStruct
3127 : {
3128 : struct DatasetContext
3129 : {
3130 : std::string osFilename;
3131 : int nOpenFlags;
3132 : std::string osAllowedDrivers;
3133 :
3134 74577 : DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,
3135 : const std::string &osAllowedDriversIn)
3136 74577 : : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),
3137 74577 : osAllowedDrivers(osAllowedDriversIn)
3138 : {
3139 74570 : }
3140 : };
3141 :
3142 : struct DatasetContextCompare
3143 : {
3144 1138070 : bool operator()(const DatasetContext &lhs,
3145 : const DatasetContext &rhs) const
3146 : {
3147 3327830 : return lhs.osFilename < rhs.osFilename ||
3148 1103460 : (lhs.osFilename == rhs.osFilename &&
3149 1087330 : (lhs.nOpenFlags < rhs.nOpenFlags ||
3150 2173040 : (lhs.nOpenFlags == rhs.nOpenFlags &&
3151 2223710 : lhs.osAllowedDrivers < rhs.osAllowedDrivers)));
3152 : }
3153 : };
3154 :
3155 : std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
3156 : int nRecLevel = 0;
3157 : std::map<std::string, int> m_oMapDepth{};
3158 : };
3159 :
3160 : #ifdef _WIN32
3161 : // Currently thread_local and C++ objects don't work well with DLL on Windows
3162 : static void FreeAntiRecursionOpen(void *pData)
3163 : {
3164 : delete static_cast<GDALAntiRecursionStruct *>(pData);
3165 : }
3166 :
3167 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3168 : {
3169 : static GDALAntiRecursionStruct dummy;
3170 : int bMemoryErrorOccurred = false;
3171 : void *pData =
3172 : CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
3173 : if (bMemoryErrorOccurred)
3174 : {
3175 : return dummy;
3176 : }
3177 : if (pData == nullptr)
3178 : {
3179 : auto pAntiRecursion = new GDALAntiRecursionStruct();
3180 : CPLSetTLSWithFreeFuncEx(CTLS_GDALOPEN_ANTIRECURSION, pAntiRecursion,
3181 : FreeAntiRecursionOpen, &bMemoryErrorOccurred);
3182 : if (bMemoryErrorOccurred)
3183 : {
3184 : delete pAntiRecursion;
3185 : return dummy;
3186 : }
3187 : return *pAntiRecursion;
3188 : }
3189 : return *static_cast<GDALAntiRecursionStruct *>(pData);
3190 : }
3191 : #else
3192 : static thread_local GDALAntiRecursionStruct g_tls_antiRecursion;
3193 :
3194 128553 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3195 : {
3196 128553 : return g_tls_antiRecursion;
3197 : }
3198 : #endif
3199 :
3200 : //! @cond Doxygen_Suppress
3201 53975 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)
3202 53975 : : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),
3203 : m_osIdentifier(osIdentifier),
3204 53975 : m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3205 : {
3206 53975 : CPLAssert(!osIdentifier.empty());
3207 53975 : }
3208 :
3209 53975 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(
3210 53975 : const GDALAntiRecursionGuard &other, const std::string &osIdentifier)
3211 53975 : : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),
3212 53975 : m_osIdentifier(osIdentifier.empty()
3213 : ? osIdentifier
3214 26819 : : other.m_osIdentifier + osIdentifier),
3215 53975 : m_nDepth(m_osIdentifier.empty()
3216 53975 : ? 0
3217 80794 : : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3218 : {
3219 53975 : }
3220 :
3221 107950 : GDALAntiRecursionGuard::~GDALAntiRecursionGuard()
3222 : {
3223 107950 : if (!m_osIdentifier.empty())
3224 : {
3225 80794 : --m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier];
3226 : }
3227 107950 : }
3228 :
3229 : //! @endcond
3230 :
3231 : /************************************************************************/
3232 : /* GetFileList() */
3233 : /************************************************************************/
3234 :
3235 : /**
3236 : * \brief Fetch files forming dataset.
3237 : *
3238 : * Returns a list of files believed to be part of this dataset. If it returns
3239 : * an empty list of files it means there is believed to be no local file
3240 : * system files associated with the dataset (for instance a virtual dataset).
3241 : * The returned file list is owned by the caller and should be deallocated
3242 : * with CSLDestroy().
3243 : *
3244 : * The returned filenames will normally be relative or absolute paths
3245 : * depending on the path used to originally open the dataset. The strings
3246 : * will be UTF-8 encoded.
3247 : *
3248 : * This method is the same as the C GDALGetFileList() function.
3249 : *
3250 : * @return NULL or a NULL terminated array of file names.
3251 : */
3252 :
3253 4797 : char **GDALDataset::GetFileList()
3254 :
3255 : {
3256 9594 : CPLString osMainFilename = GetDescription();
3257 : VSIStatBufL sStat;
3258 :
3259 4797 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3260 : const GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,
3261 9594 : std::string());
3262 4797 : auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
3263 4797 : if (cpl::contains(aosDatasetList, datasetCtxt))
3264 0 : return nullptr;
3265 :
3266 : /* -------------------------------------------------------------------- */
3267 : /* Is the main filename even a real filesystem object? */
3268 : /* -------------------------------------------------------------------- */
3269 : int bMainFileReal =
3270 4797 : VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
3271 :
3272 : /* -------------------------------------------------------------------- */
3273 : /* Form new list. */
3274 : /* -------------------------------------------------------------------- */
3275 4797 : char **papszList = nullptr;
3276 :
3277 4797 : if (bMainFileReal)
3278 4736 : papszList = CSLAddString(papszList, osMainFilename);
3279 :
3280 4797 : if (sAntiRecursion.nRecLevel == 100)
3281 : {
3282 0 : CPLError(CE_Failure, CPLE_AppDefined,
3283 : "GetFileList() called with too many recursion levels");
3284 0 : return papszList;
3285 : }
3286 4797 : ++sAntiRecursion.nRecLevel;
3287 :
3288 : /* -------------------------------------------------------------------- */
3289 : /* Do we have a known overview file? */
3290 : /* -------------------------------------------------------------------- */
3291 4797 : if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
3292 : {
3293 63 : auto iter = aosDatasetList.insert(datasetCtxt).first;
3294 63 : char **papszOvrList = oOvManager.poODS->GetFileList();
3295 63 : papszList = CSLInsertStrings(papszList, -1, papszOvrList);
3296 63 : CSLDestroy(papszOvrList);
3297 63 : aosDatasetList.erase(iter);
3298 : }
3299 :
3300 : /* -------------------------------------------------------------------- */
3301 : /* Do we have a known mask file? */
3302 : /* -------------------------------------------------------------------- */
3303 4797 : if (oOvManager.HaveMaskFile())
3304 : {
3305 11 : auto iter = aosDatasetList.insert(datasetCtxt).first;
3306 11 : for (const char *pszFile :
3307 22 : CPLStringList(oOvManager.poMaskDS->GetFileList()))
3308 : {
3309 11 : if (CSLFindString(papszList, pszFile) < 0)
3310 11 : papszList = CSLAddString(papszList, pszFile);
3311 : }
3312 11 : aosDatasetList.erase(iter);
3313 : }
3314 :
3315 4797 : --sAntiRecursion.nRecLevel;
3316 :
3317 4797 : return papszList;
3318 : }
3319 :
3320 : /************************************************************************/
3321 : /* GDALGetFileList() */
3322 : /************************************************************************/
3323 :
3324 : /**
3325 : * \brief Fetch files forming dataset.
3326 : *
3327 : * @see GDALDataset::GetFileList()
3328 : */
3329 :
3330 3999 : char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)
3331 :
3332 : {
3333 3999 : VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3334 :
3335 3999 : return GDALDataset::FromHandle(hDS)->GetFileList();
3336 : }
3337 :
3338 : /************************************************************************/
3339 : /* CreateMaskBand() */
3340 : /************************************************************************/
3341 :
3342 : /**
3343 : * \brief Adds a mask band to the dataset
3344 : *
3345 : * The default implementation of the CreateMaskBand() method is implemented
3346 : * based on similar rules to the .ovr handling implemented using the
3347 : * GDALDefaultOverviews object. A TIFF file with the extension .msk will
3348 : * be created with the same basename as the original file, and it will have
3349 : * one band.
3350 : * The mask images will be deflate compressed tiled images with the same
3351 : * block size as the original image if possible.
3352 : * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
3353 : * level, where xx matches the band number of a band of the main dataset. The
3354 : * value of those items will be the one of the nFlagsIn parameter.
3355 : *
3356 : * Note that if you got a mask band with a previous call to GetMaskBand(), it
3357 : * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
3358 : * again.
3359 : *
3360 : * @since GDAL 1.5.0
3361 : *
3362 : * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
3363 : * GMF_PER_DATASET will be always set, even if not explicitly
3364 : * specified.
3365 : * @return CE_None on success or CE_Failure on an error.
3366 : *
3367 : * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
3368 : * @see GDALRasterBand::CreateMaskBand()
3369 : *
3370 : */
3371 17 : CPLErr GDALDataset::CreateMaskBand(int nFlagsIn)
3372 :
3373 : {
3374 17 : if (oOvManager.IsInitialized())
3375 : {
3376 17 : CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
3377 17 : if (eErr != CE_None)
3378 0 : return eErr;
3379 :
3380 : // Invalidate existing raster band masks.
3381 45 : for (int i = 0; i < nBands; ++i)
3382 : {
3383 28 : GDALRasterBand *poBand = papoBands[i];
3384 28 : poBand->poMask.reset();
3385 : }
3386 :
3387 17 : return CE_None;
3388 : }
3389 :
3390 0 : ReportError(CE_Failure, CPLE_NotSupported,
3391 : "CreateMaskBand() not supported for this dataset.");
3392 :
3393 0 : return CE_Failure;
3394 : }
3395 :
3396 : /************************************************************************/
3397 : /* GDALCreateDatasetMaskBand() */
3398 : /************************************************************************/
3399 :
3400 : /**
3401 : * \brief Adds a mask band to the dataset
3402 : * @see GDALDataset::CreateMaskBand()
3403 : */
3404 86 : CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)
3405 :
3406 : {
3407 86 : VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3408 :
3409 86 : return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
3410 : }
3411 :
3412 : /************************************************************************/
3413 : /* GDALOpen() */
3414 : /************************************************************************/
3415 :
3416 : /**
3417 : * \brief Open a raster file as a GDALDataset.
3418 : *
3419 : * This function will try to open the passed file, or virtual dataset
3420 : * name by invoking the Open method of each registered GDALDriver in turn.
3421 : * The first successful open will result in a returned dataset. If all
3422 : * drivers fail then NULL is returned and an error is issued.
3423 : *
3424 : * Several recommendations :
3425 : * <ul>
3426 : * <li>If you open a dataset object with GA_Update access, it is not recommended
3427 : * to open a new dataset on the same underlying file.</li>
3428 : * <li>The returned dataset should only be accessed by one thread at a time. If
3429 : * you want to use it from different threads, you must add all necessary code
3430 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3431 : * as GeoTIFF, maintain internal state variables that are updated each time a
3432 : * new block is read, thus preventing concurrent use.) </li>
3433 : * </ul>
3434 : *
3435 : * For drivers supporting the VSI virtual file API, it is possible to open a
3436 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3437 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3438 : * server (see VSIInstallCurlFileHandler())
3439 : *
3440 : * \sa GDALOpenShared()
3441 : * \sa GDALOpenEx()
3442 : *
3443 : * @param pszFilename the name of the file to access. In the case of
3444 : * exotic drivers this may not refer to a physical file, but instead contain
3445 : * information for the driver on how to access a dataset. It should be in UTF-8
3446 : * encoding.
3447 : *
3448 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
3449 : * drivers support only read only access.
3450 : *
3451 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3452 : * this handle can be cast to a GDALDataset *.
3453 : */
3454 :
3455 24356 : GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)
3456 :
3457 : {
3458 24356 : const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3459 24356 : const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3460 : GDALDatasetH hDataset =
3461 24356 : GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3462 24292 : return hDataset;
3463 : }
3464 :
3465 : /************************************************************************/
3466 : /* GetSharedDS() */
3467 : /************************************************************************/
3468 :
3469 6481 : static GDALDataset *GetSharedDS(const char *pszFilename,
3470 : unsigned int nOpenFlags,
3471 : const char *const *papszOpenOptions)
3472 : {
3473 12962 : CPLMutexHolderD(&hDLMutex);
3474 :
3475 6481 : if (phSharedDatasetSet != nullptr)
3476 : {
3477 6259 : const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3478 : SharedDatasetCtxt sStruct;
3479 :
3480 6259 : sStruct.nPID = nThisPID;
3481 6259 : sStruct.pszDescription = const_cast<char *>(pszFilename);
3482 6259 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
3483 : std::string osConcatenatedOpenOptions =
3484 6259 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
3485 6259 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
3486 6259 : sStruct.poDS = nullptr;
3487 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3488 6259 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3489 6259 : if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3490 : {
3491 154 : sStruct.nOpenFlags |= GDAL_OF_UPDATE;
3492 : psStruct = static_cast<SharedDatasetCtxt *>(
3493 154 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3494 : }
3495 6259 : if (psStruct)
3496 : {
3497 6106 : return psStruct->poDS;
3498 : }
3499 : }
3500 375 : return nullptr;
3501 : }
3502 :
3503 : /************************************************************************/
3504 : /* GDALOpenEx() */
3505 : /************************************************************************/
3506 :
3507 : /**
3508 : * \brief Open a raster or vector file as a GDALDataset.
3509 : *
3510 : * This function will try to open the passed file, or virtual dataset
3511 : * name by invoking the Open method of each registered GDALDriver in turn.
3512 : * The first successful open will result in a returned dataset. If all
3513 : * drivers fail then NULL is returned and an error is issued.
3514 : *
3515 : * Several recommendations :
3516 : * <ul>
3517 : * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
3518 : * recommended to open a new dataset on the same underlying file.</li>
3519 : * <li>The returned dataset should only be accessed by one thread at a time. If
3520 : * you want to use it from different threads, you must add all necessary code
3521 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3522 : * as GeoTIFF, maintain internal state variables that are updated each time a
3523 : * new block is read, thus preventing concurrent use.) </li>
3524 : * </ul>
3525 : *
3526 : * For drivers supporting the VSI virtual file API, it is possible to open a
3527 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3528 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3529 : * server (see VSIInstallCurlFileHandler())
3530 : *
3531 : * In order to reduce the need for searches through the operating system
3532 : * file system machinery, it is possible to give an optional list of files with
3533 : * the papszSiblingFiles parameter.
3534 : * This is the list of all files at the same level in the file system as the
3535 : * target file, including the target file. The filenames must not include any
3536 : * path components, are essentially just the output of VSIReadDir() on the
3537 : * parent directory. If the target object does not have filesystem semantics
3538 : * then the file list should be NULL.
3539 : *
3540 : * @param pszFilename the name of the file to access. In the case of
3541 : * exotic drivers this may not refer to a physical file, but instead contain
3542 : * information for the driver on how to access a dataset. It should be in UTF-8
3543 : * encoding.
3544 : *
3545 : * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
3546 : * through logical or operator.
3547 : * <ul>
3548 : * <li>Driver kind:
3549 : * <ul>
3550 : * <li>GDAL_OF_RASTER for raster drivers,</li>
3551 : * <li>GDAL_OF_MULTIDIM_RASTER for multidimensional raster drivers,</li>
3552 : * <li>GDAL_OF_VECTOR for vector drivers,</li>
3553 : * <li>GDAL_OF_GNM for Geographic Network Model drivers.</li>
3554 : * </ul>
3555 : * GDAL_OF_RASTER and GDAL_OF_MULTIDIM_RASTER are generally mutually
3556 : * exclusive. If none of the value is specified, GDAL_OF_RASTER | GDAL_OF_VECTOR
3557 : * | GDAL_OF_GNM is implied.
3558 : * </li>
3559 : * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.
3560 : * </li>
3561 : * <li>Shared mode: GDAL_OF_SHARED. If set,
3562 : * it allows the sharing of GDALDataset handles for a dataset with other callers
3563 : * that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will first consult
3564 : * its list of currently open and shared GDALDataset's, and if the
3565 : * GetDescription() name for one exactly matches the pszFilename passed to
3566 : * GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called
3567 : * from the same thread.
3568 : * </li>
3569 : * <li>Thread safe mode: GDAL_OF_THREAD_SAFE (added in 3.10).
3570 : * This must be use in combination with GDAL_OF_RASTER, and is mutually
3571 : * exclusive with GDAL_OF_UPDATE, GDAL_OF_VECTOR, GDAL_OF_MULTIDIM_RASTER or
3572 : * GDAL_OF_GNM.
3573 : * </li>
3574 : * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set,
3575 : * a failed attempt to open the file will lead to an error message to be
3576 : * reported.
3577 : * </li>
3578 : * </ul>
3579 : *
3580 : * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
3581 : * terminated list of strings with the driver short names that must be
3582 : * considered.
3583 : *
3584 : * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
3585 : * options passed to candidate drivers. An option exists for all drivers,
3586 : * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
3587 : * The level index starts at 0. The level number can be suffixed by "only" to
3588 : * specify that only this overview level must be visible, and not sub-levels.
3589 : * Open options are validated by default, and a warning is emitted in case the
3590 : * option is not recognized. In some scenarios, it might be not desirable (e.g.
3591 : * when not knowing which driver will open the file), so the special open option
3592 : * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
3593 : * since GDAL 2.1, an option name can be preceded by the @ character to indicate
3594 : * that it may not cause a warning if the driver doesn't declare this option.
3595 : * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
3596 : * no overviews should be exposed.
3597 : *
3598 : * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
3599 : * filenames that are auxiliary to the main filename. If NULL is passed, a
3600 : * probing of the file system will be done.
3601 : *
3602 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3603 : * this handle can be cast to a GDALDataset *.
3604 : *
3605 : * @since GDAL 2.0
3606 : */
3607 :
3608 75893 : GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
3609 : unsigned int nOpenFlags,
3610 : const char *const *papszAllowedDrivers,
3611 : const char *const *papszOpenOptions,
3612 : const char *const *papszSiblingFiles)
3613 : {
3614 75893 : VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
3615 :
3616 : // Do some sanity checks on incompatible flags with thread-safe mode.
3617 75893 : if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3618 : {
3619 : const struct
3620 : {
3621 : int nFlag;
3622 : const char *pszFlagName;
3623 128 : } asFlags[] = {
3624 : {GDAL_OF_UPDATE, "GDAL_OF_UPDATE"},
3625 : {GDAL_OF_VECTOR, "GDAL_OF_VECTOR"},
3626 : {GDAL_OF_MULTIDIM_RASTER, "GDAL_OF_MULTIDIM_RASTER"},
3627 : {GDAL_OF_GNM, "GDAL_OF_GNM"},
3628 : };
3629 :
3630 630 : for (const auto &asFlag : asFlags)
3631 : {
3632 506 : if ((nOpenFlags & asFlag.nFlag) != 0)
3633 : {
3634 4 : CPLError(CE_Failure, CPLE_IllegalArg,
3635 : "GDAL_OF_THREAD_SAFE and %s are mutually "
3636 : "exclusive",
3637 4 : asFlag.pszFlagName);
3638 4 : return nullptr;
3639 : }
3640 : }
3641 : }
3642 :
3643 : // If no driver kind is specified, assume all are to be probed.
3644 75889 : if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)
3645 7412 : nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
3646 :
3647 : /* -------------------------------------------------------------------- */
3648 : /* In case of shared dataset, first scan the existing list to see */
3649 : /* if it could already contain the requested dataset. */
3650 : /* -------------------------------------------------------------------- */
3651 75889 : if (nOpenFlags & GDAL_OF_SHARED)
3652 : {
3653 6481 : if (nOpenFlags & GDAL_OF_INTERNAL)
3654 : {
3655 0 : CPLError(CE_Failure, CPLE_IllegalArg,
3656 : "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
3657 0 : return nullptr;
3658 : }
3659 :
3660 : auto poSharedDS =
3661 6481 : GetSharedDS(pszFilename, nOpenFlags, papszOpenOptions);
3662 6481 : if (poSharedDS)
3663 : {
3664 6106 : poSharedDS->Reference();
3665 6106 : return poSharedDS;
3666 : }
3667 : }
3668 :
3669 69783 : GDALDriverManager *poDM = GetGDALDriverManager();
3670 : // CPLLocaleC oLocaleForcer;
3671 :
3672 69782 : CPLErrorReset();
3673 69782 : VSIErrorReset();
3674 69781 : CPLAssert(nullptr != poDM);
3675 :
3676 : // Build GDALOpenInfo just now to avoid useless file stat'ing if a
3677 : // shared dataset was asked before.
3678 : GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
3679 139444 : const_cast<char **>(papszSiblingFiles));
3680 69782 : oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3681 :
3682 69782 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3683 69782 : if (sAntiRecursion.nRecLevel == 100)
3684 : {
3685 0 : CPLError(CE_Failure, CPLE_AppDefined,
3686 : "GDALOpen() called with too many recursion levels");
3687 0 : return nullptr;
3688 : }
3689 :
3690 139449 : std::string osAllowedDrivers;
3691 165090 : for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
3692 95312 : osAllowedDrivers += pszDriverName;
3693 : auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(
3694 209180 : std::string(pszFilename), nOpenFlags, osAllowedDrivers);
3695 69771 : if (cpl::contains(sAntiRecursion.aosDatasetNamesWithFlags, dsCtxt))
3696 : {
3697 0 : CPLError(CE_Failure, CPLE_AppDefined,
3698 : "GDALOpen() called on %s recursively", pszFilename);
3699 0 : return nullptr;
3700 : }
3701 :
3702 : // Remove leading @ if present.
3703 : char **papszOpenOptionsCleaned =
3704 69763 : CSLDuplicate(const_cast<char **>(papszOpenOptions));
3705 75234 : for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
3706 : ++papszIter)
3707 : {
3708 5468 : char *pszOption = *papszIter;
3709 5468 : if (pszOption[0] == '@')
3710 181 : memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
3711 : }
3712 :
3713 69766 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3714 69766 : oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;
3715 :
3716 : #ifdef OGRAPISPY_ENABLED
3717 69766 : const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
3718 : const int iSnapshot =
3719 18481 : (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0
3720 88247 : ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)
3721 69766 : : INT_MIN;
3722 : #endif
3723 :
3724 69766 : const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);
3725 69775 : GDALDriver *poMissingPluginDriver = nullptr;
3726 139531 : std::vector<GDALDriver *> apoSecondPassDrivers;
3727 :
3728 : // Lookup of matching driver for dataset can involve up to 2 passes:
3729 : // - in the first pass, all drivers that are compabile of the request mode
3730 : // (raster/vector/etc.) are probed using their Identify() method if it
3731 : // exists. If the Identify() method returns FALSE, the driver is skipped.
3732 : // If the Identify() methods returns GDAL_IDENTIFY_UNKNOWN and that the
3733 : // driver is a deferred-loading plugin, it is added to the
3734 : // apoSecondPassDrivers list for potential later probing, and execution
3735 : // continues to the next driver in the list.
3736 : // Otherwise if Identify() returns non-FALSE, the Open() method is used.
3737 : // If Open() returns a non-NULL dataset, the loop stops and it is
3738 : // returned. Otherwise looping over remaining drivers continues.
3739 : // - the second pass is optional, only if at least one driver was added
3740 : // into apoSecondPassDrivers during the first pass. It is similar
3741 : // to the first pass except it runs only on apoSecondPassDrivers drivers.
3742 : // And the Open() method of such drivers is used, causing them to be
3743 : // loaded for real.
3744 69756 : int iPass = 1;
3745 69770 : retry:
3746 8129600 : for (int iDriver = 0;
3747 8129640 : iDriver < (iPass == 1 ? nDriverCount
3748 40 : : static_cast<int>(apoSecondPassDrivers.size()));
3749 : ++iDriver)
3750 : {
3751 : GDALDriver *poDriver =
3752 8110720 : iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
3753 2043 : : apoSecondPassDrivers[iDriver];
3754 11795800 : if (papszAllowedDrivers != nullptr &&
3755 3681260 : CSLFindString(papszAllowedDrivers,
3756 : GDALGetDriverShortName(poDriver)) == -1)
3757 : {
3758 7568180 : continue;
3759 : }
3760 :
3761 4523360 : if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)
3762 39039 : continue;
3763 :
3764 12043700 : if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&
3765 6597770 : (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
3766 2111600 : poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
3767 525948 : continue;
3768 11508100 : if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3769 5743990 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3770 1783770 : poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
3771 1371530 : continue;
3772 5459790 : if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
3773 2732570 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3774 143880 : poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)
3775 135999 : continue;
3776 :
3777 : // Remove general OVERVIEW_LEVEL open options from list before passing
3778 : // it to the driver, if it isn't a driver specific option already.
3779 2452690 : char **papszTmpOpenOptions = nullptr;
3780 2452690 : char **papszTmpOpenOptionsToValidate = nullptr;
3781 2452690 : char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
3782 2452690 : if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
3783 2449330 : nullptr &&
3784 183 : !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
3785 : {
3786 183 : papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
3787 : papszTmpOpenOptions =
3788 183 : CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
3789 183 : oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
3790 :
3791 183 : papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
3792 183 : papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate,
3793 : "OVERVIEW_LEVEL", nullptr);
3794 183 : papszTmpOpenOptionsToValidate = papszOptionsToValidate;
3795 : }
3796 :
3797 : const int nIdentifyRes =
3798 2449150 : poDriver->pfnIdentifyEx
3799 4898240 : ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)
3800 2449140 : : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)
3801 2449100 : : GDAL_IDENTIFY_UNKNOWN;
3802 2449100 : if (nIdentifyRes == FALSE)
3803 : {
3804 1904980 : CSLDestroy(papszTmpOpenOptions);
3805 1904680 : CSLDestroy(papszTmpOpenOptionsToValidate);
3806 1904410 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3807 1904410 : continue;
3808 : }
3809 544098 : else if (iPass == 1 && nIdentifyRes < 0 &&
3810 1088340 : poDriver->pfnOpen == nullptr &&
3811 123 : poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN"))
3812 : {
3813 : // Not loaded plugin
3814 122 : apoSecondPassDrivers.push_back(poDriver);
3815 122 : CSLDestroy(papszTmpOpenOptions);
3816 122 : CSLDestroy(papszTmpOpenOptionsToValidate);
3817 122 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3818 122 : continue;
3819 : }
3820 :
3821 544002 : const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;
3822 544002 : if (bIdentifyRes)
3823 : {
3824 49723 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3825 : }
3826 :
3827 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3828 : const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
3829 : CPLErrorReset();
3830 : #endif
3831 :
3832 544014 : sAntiRecursion.nRecLevel++;
3833 544014 : sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
3834 :
3835 543570 : GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
3836 :
3837 543647 : sAntiRecursion.nRecLevel--;
3838 543647 : sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
3839 :
3840 543195 : if (poDriver->pfnOpen != nullptr)
3841 : {
3842 : // If we couldn't determine for sure with Identify() (it returned
3843 : // -1), but Open() managed to open the file, post validate options.
3844 543015 : if (poDS != nullptr &&
3845 50004 : (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&
3846 49204 : !bIdentifyRes)
3847 : {
3848 827 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3849 : }
3850 : }
3851 180 : else if (poDriver->pfnOpenWithDriverArg != nullptr)
3852 : {
3853 : // do nothing
3854 : }
3855 0 : else if (bIdentifyRes &&
3856 0 : poDriver->GetMetadataItem("MISSING_PLUGIN_FILENAME"))
3857 : {
3858 0 : if (!poMissingPluginDriver)
3859 : {
3860 0 : poMissingPluginDriver = poDriver;
3861 : }
3862 : }
3863 : else
3864 : {
3865 : // should not happen given the GDAL_DCAP_OPEN check
3866 0 : CSLDestroy(papszTmpOpenOptions);
3867 0 : CSLDestroy(papszTmpOpenOptionsToValidate);
3868 0 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3869 0 : continue;
3870 : }
3871 :
3872 543195 : CSLDestroy(papszTmpOpenOptions);
3873 543162 : CSLDestroy(papszTmpOpenOptionsToValidate);
3874 542514 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3875 :
3876 542514 : if (poDS != nullptr)
3877 : {
3878 49994 : if (poDS->papszOpenOptions == nullptr)
3879 : {
3880 49735 : poDS->papszOpenOptions = papszOpenOptionsCleaned;
3881 49735 : papszOpenOptionsCleaned = nullptr;
3882 : }
3883 :
3884 : // Deal with generic OVERVIEW_LEVEL open option, unless it is
3885 : // driver specific.
3886 49994 : if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
3887 50039 : nullptr &&
3888 39 : !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
3889 : {
3890 : CPLString osVal(
3891 78 : CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
3892 39 : const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
3893 : const bool bThisLevelOnly =
3894 39 : nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
3895 : GDALDataset *poOvrDS =
3896 39 : GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly);
3897 39 : if (poOvrDS && (nOpenFlags & GDAL_OF_SHARED) != 0)
3898 : {
3899 4 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3900 : {
3901 0 : CPLError(
3902 : CE_Warning, CPLE_NotSupported,
3903 : "A dataset opened by GDALOpenShared should have "
3904 : "the same filename (%s) "
3905 : "and description (%s)",
3906 0 : pszFilename, poDS->GetDescription());
3907 : }
3908 : else
3909 : {
3910 4 : CSLDestroy(poDS->papszOpenOptions);
3911 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
3912 4 : poDS->papszOpenOptions = CSLSetNameValue(
3913 : poDS->papszOpenOptions, "OVERVIEW_LEVEL", nullptr);
3914 : }
3915 : }
3916 39 : poDS->ReleaseRef();
3917 39 : poDS = poOvrDS;
3918 39 : if (poDS == nullptr)
3919 : {
3920 1 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
3921 : {
3922 1 : CPLError(CE_Failure, CPLE_OpenFailed,
3923 : "Cannot open overview level %d of %s",
3924 : nOvrLevel, pszFilename);
3925 : }
3926 : }
3927 : else
3928 : {
3929 : // For thread-safe opening, currently poDS is what will be
3930 : // the "master" dataset owned by the thread-safe dataset
3931 : // returned to the user, hence we do not register it as a
3932 : // visible one in the open dataset list, or mark it as shared.
3933 38 : if (!(nOpenFlags & GDAL_OF_INTERNAL) &&
3934 36 : !(nOpenFlags & GDAL_OF_THREAD_SAFE))
3935 : {
3936 35 : poDS->AddToDatasetOpenList();
3937 : }
3938 38 : if (nOpenFlags & GDAL_OF_SHARED)
3939 : {
3940 4 : CSLDestroy(poDS->papszOpenOptions);
3941 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
3942 4 : poDS->nOpenFlags = nOpenFlags;
3943 4 : if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
3944 4 : poDS->MarkAsShared();
3945 : }
3946 : }
3947 : }
3948 49961 : else if (nOpenFlags & GDAL_OF_SHARED)
3949 : {
3950 366 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3951 : {
3952 2 : CPLError(CE_Warning, CPLE_NotSupported,
3953 : "A dataset opened by GDALOpenShared should have "
3954 : "the same filename (%s) "
3955 : "and description (%s)",
3956 2 : pszFilename, poDS->GetDescription());
3957 : }
3958 364 : else if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
3959 : {
3960 : // For thread-safe opening, currently poDS is what will be
3961 : // the "master" dataset owned by the thread-safe dataset
3962 : // returned to the user, hence we do not or mark it as shared.
3963 364 : poDS->MarkAsShared();
3964 : }
3965 : }
3966 :
3967 49999 : VSIErrorReset();
3968 :
3969 49996 : CSLDestroy(papszOpenOptionsCleaned);
3970 :
3971 : #ifdef OGRAPISPY_ENABLED
3972 49988 : if (iSnapshot != INT_MIN)
3973 : {
3974 10714 : GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
3975 10714 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3976 10714 : poDS = GDALDataset::FromHandle(hDS);
3977 : }
3978 : #endif
3979 :
3980 49988 : if (poDS)
3981 : {
3982 49992 : poDS->m_bCanBeReopened = true;
3983 :
3984 49992 : if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3985 : {
3986 : poDS =
3987 248 : GDALGetThreadSafeDataset(
3988 248 : std::unique_ptr<GDALDataset>(poDS), GDAL_OF_RASTER)
3989 124 : .release();
3990 124 : if (poDS)
3991 : {
3992 124 : poDS->m_bCanBeReopened = true;
3993 124 : poDS->poDriver = poDriver;
3994 124 : poDS->nOpenFlags = nOpenFlags;
3995 124 : if (!(nOpenFlags & GDAL_OF_INTERNAL))
3996 124 : poDS->AddToDatasetOpenList();
3997 124 : if (nOpenFlags & GDAL_OF_SHARED)
3998 0 : poDS->MarkAsShared();
3999 : }
4000 : }
4001 : }
4002 :
4003 50920 : return poDS;
4004 : }
4005 :
4006 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
4007 : if (bFpAvailableBefore && oOpenInfo.fpL == nullptr)
4008 : {
4009 : // In case the file descriptor was "consumed" by a driver
4010 : // that ultimately failed, re-open it for next drivers.
4011 : oOpenInfo.fpL = VSIFOpenL(
4012 : pszFilename, (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
4013 : }
4014 : #else
4015 492520 : if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
4016 : {
4017 776 : CSLDestroy(papszOpenOptionsCleaned);
4018 :
4019 : #ifdef OGRAPISPY_ENABLED
4020 924 : if (iSnapshot != INT_MIN)
4021 : {
4022 157 : GDALDatasetH hDS = nullptr;
4023 157 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4024 : }
4025 : #endif
4026 924 : return nullptr;
4027 : }
4028 : #endif
4029 : }
4030 :
4031 : // cppcheck-suppress knownConditionTrueFalse
4032 18912 : if (iPass == 1 && !apoSecondPassDrivers.empty())
4033 : {
4034 17 : CPLDebugOnly("GDAL", "GDALOpen(): Second pass");
4035 14 : iPass = 2;
4036 14 : goto retry;
4037 : }
4038 :
4039 18849 : CSLDestroy(papszOpenOptionsCleaned);
4040 :
4041 : #ifdef OGRAPISPY_ENABLED
4042 18783 : if (iSnapshot != INT_MIN)
4043 : {
4044 937 : GDALDatasetH hDS = nullptr;
4045 937 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4046 : }
4047 : #endif
4048 :
4049 18783 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4050 : {
4051 : // Check to see if there was a filesystem error, and report it if so.
4052 : // If not, return a more generic error.
4053 5896 : if (!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
4054 : {
4055 400 : if (nDriverCount == 0)
4056 : {
4057 0 : CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");
4058 : }
4059 400 : else if (oOpenInfo.bStatOK)
4060 : {
4061 397 : if (!poMissingPluginDriver)
4062 : {
4063 397 : CPLError(CE_Failure, CPLE_OpenFailed,
4064 : "`%s' not recognized as being in a supported file "
4065 : "format.",
4066 : pszFilename);
4067 : }
4068 : else
4069 : {
4070 0 : std::string osMsg("`");
4071 0 : osMsg += pszFilename;
4072 : osMsg +=
4073 : "' not recognized as being in a supported file format. "
4074 0 : "It could have been recognized by driver ";
4075 0 : osMsg += poMissingPluginDriver->GetDescription();
4076 0 : osMsg += ", but plugin ";
4077 : osMsg += poMissingPluginDriver->GetMetadataItem(
4078 0 : "MISSING_PLUGIN_FILENAME");
4079 : osMsg += " is not available in your "
4080 0 : "installation.";
4081 0 : if (const char *pszInstallationMsg =
4082 0 : poMissingPluginDriver->GetMetadataItem(
4083 0 : GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE))
4084 : {
4085 0 : osMsg += " ";
4086 0 : osMsg += pszInstallationMsg;
4087 : }
4088 :
4089 : VSIStatBuf sStat;
4090 0 : if (const char *pszGDALDriverPath =
4091 0 : CPLGetConfigOption("GDAL_DRIVER_PATH", nullptr))
4092 : {
4093 0 : if (VSIStat(pszGDALDriverPath, &sStat) != 0)
4094 : {
4095 0 : if (osMsg.back() != '.')
4096 0 : osMsg += ".";
4097 0 : osMsg += " Directory '";
4098 0 : osMsg += pszGDALDriverPath;
4099 : osMsg +=
4100 0 : "' pointed by GDAL_DRIVER_PATH does not exist.";
4101 : }
4102 : }
4103 : else
4104 : {
4105 0 : if (osMsg.back() != '.')
4106 0 : osMsg += ".";
4107 : #ifdef INSTALL_PLUGIN_FULL_DIR
4108 : if (VSIStat(INSTALL_PLUGIN_FULL_DIR, &sStat) != 0)
4109 : {
4110 : osMsg += " Directory '";
4111 : osMsg += INSTALL_PLUGIN_FULL_DIR;
4112 : osMsg += "' hardcoded in the GDAL library does not "
4113 : "exist and the GDAL_DRIVER_PATH "
4114 : "configuration option is not set.";
4115 : }
4116 : else
4117 : #endif
4118 : {
4119 : osMsg += " The GDAL_DRIVER_PATH configuration "
4120 0 : "option is not set.";
4121 : }
4122 : }
4123 :
4124 0 : CPLError(CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str());
4125 : }
4126 : }
4127 : else
4128 : {
4129 : // If Stat failed and no VSI error was set, assume it is because
4130 : // the file did not exist on the filesystem.
4131 3 : CPLError(CE_Failure, CPLE_OpenFailed,
4132 : "`%s' does not exist in the file system, "
4133 : "and is not recognized as a supported dataset name.",
4134 : pszFilename);
4135 : }
4136 : }
4137 : }
4138 :
4139 18836 : return nullptr;
4140 : }
4141 :
4142 : /************************************************************************/
4143 : /* GDALOpenShared() */
4144 : /************************************************************************/
4145 :
4146 : /**
4147 : * \brief Open a raster file as a GDALDataset.
4148 : *
4149 : * This function works the same as GDALOpen(), but allows the sharing of
4150 : * GDALDataset handles for a dataset with other callers to GDALOpenShared().
4151 : *
4152 : * In particular, GDALOpenShared() will first consult its list of currently
4153 : * open and shared GDALDataset's, and if the GetDescription() name for one
4154 : * exactly matches the pszFilename passed to GDALOpenShared() it will be
4155 : * referenced and returned.
4156 : *
4157 : * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
4158 : * pszFilename from two different threads, a different GDALDataset object will
4159 : * be returned as it is not safe to use the same dataset from different threads,
4160 : * unless the user does explicitly use mutexes in its code.
4161 : *
4162 : * For drivers supporting the VSI virtual file API, it is possible to open a
4163 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
4164 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
4165 : * server (see VSIInstallCurlFileHandler())
4166 : *
4167 : * \sa GDALOpen()
4168 : * \sa GDALOpenEx()
4169 : *
4170 : * @param pszFilename the name of the file to access. In the case of
4171 : * exotic drivers this may not refer to a physical file, but instead contain
4172 : * information for the driver on how to access a dataset. It should be in
4173 : * UTF-8 encoding.
4174 : *
4175 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
4176 : * drivers support only read only access.
4177 : *
4178 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
4179 : * this handle can be cast to a GDALDataset *.
4180 : */
4181 :
4182 5221 : GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,
4183 : GDALAccess eAccess)
4184 : {
4185 5221 : VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
4186 5221 : return GDALOpenEx(pszFilename,
4187 : GDAL_OF_RASTER |
4188 : (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
4189 : GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
4190 5221 : nullptr, nullptr, nullptr);
4191 : }
4192 :
4193 : /************************************************************************/
4194 : /* GDALClose() */
4195 : /************************************************************************/
4196 :
4197 : /**
4198 : * \brief Close GDAL dataset.
4199 : *
4200 : * For non-shared datasets (opened with GDALOpen()) the dataset is closed
4201 : * using the C++ "delete" operator, recovering all dataset related resources.
4202 : * For shared datasets (opened with GDALOpenShared()) the dataset is
4203 : * dereferenced, and closed only if the referenced count has dropped below 1.
4204 : *
4205 : * @param hDS The dataset to close. May be cast from a "GDALDataset *".
4206 : * @return CE_None in case of success (return value since GDAL 3.7). On a
4207 : * shared dataset whose reference count is not dropped below 1, CE_None will
4208 : * be returned.
4209 : */
4210 :
4211 67564 : CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)
4212 :
4213 : {
4214 67564 : if (!hDS)
4215 414 : return CE_None;
4216 :
4217 : #ifdef OGRAPISPY_ENABLED
4218 67150 : if (bOGRAPISpyEnabled)
4219 11 : OGRAPISpyPreClose(hDS);
4220 : #endif
4221 :
4222 67150 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
4223 :
4224 67150 : if (poDS->GetShared())
4225 : {
4226 : /* --------------------------------------------------------------------
4227 : */
4228 : /* If this file is in the shared dataset list then dereference */
4229 : /* it, and only delete/remote it if the reference count has */
4230 : /* dropped to zero. */
4231 : /* --------------------------------------------------------------------
4232 : */
4233 303 : if (poDS->Dereference() > 0)
4234 28 : return CE_None;
4235 :
4236 275 : CPLErr eErr = poDS->Close();
4237 275 : delete poDS;
4238 :
4239 : #ifdef OGRAPISPY_ENABLED
4240 275 : if (bOGRAPISpyEnabled)
4241 0 : OGRAPISpyPostClose();
4242 : #endif
4243 :
4244 275 : return eErr;
4245 : }
4246 :
4247 : /* -------------------------------------------------------------------- */
4248 : /* This is not shared dataset, so directly delete it. */
4249 : /* -------------------------------------------------------------------- */
4250 66847 : CPLErr eErr = poDS->Close();
4251 66847 : delete poDS;
4252 :
4253 : #ifdef OGRAPISPY_ENABLED
4254 66846 : if (bOGRAPISpyEnabled)
4255 11 : OGRAPISpyPostClose();
4256 : #endif
4257 66842 : return eErr;
4258 : }
4259 :
4260 : /************************************************************************/
4261 : /* GDALDumpOpenDataset() */
4262 : /************************************************************************/
4263 :
4264 0 : static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
4265 : {
4266 0 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
4267 0 : FILE *fp = static_cast<FILE *>(user_data);
4268 0 : GDALDataset *poDS = psStruct->poDS;
4269 :
4270 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4271 0 : ? "DriverIsNULL"
4272 0 : : poDS->GetDriver()->GetDescription();
4273 :
4274 0 : poDS->Reference();
4275 0 : CPL_IGNORE_RET_VAL(
4276 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4277 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName,
4278 0 : static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
4279 : poDS->GetRasterYSize(), poDS->GetRasterCount(),
4280 0 : poDS->GetDescription()));
4281 :
4282 0 : return TRUE;
4283 : }
4284 :
4285 0 : static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
4286 : {
4287 :
4288 : // Don't list shared datasets. They have already been listed by
4289 : // GDALDumpOpenSharedDatasetsForeach.
4290 0 : if (poDS->GetShared())
4291 0 : return TRUE;
4292 :
4293 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4294 0 : ? "DriverIsNULL"
4295 0 : : poDS->GetDriver()->GetDescription();
4296 :
4297 0 : poDS->Reference();
4298 0 : CPL_IGNORE_RET_VAL(
4299 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4300 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
4301 : poDS->GetRasterXSize(), poDS->GetRasterYSize(),
4302 0 : poDS->GetRasterCount(), poDS->GetDescription()));
4303 :
4304 0 : return TRUE;
4305 : }
4306 :
4307 : /**
4308 : * \brief List open datasets.
4309 : *
4310 : * Dumps a list of all open datasets (shared or not) to the indicated
4311 : * text file (may be stdout or stderr). This function is primarily intended
4312 : * to assist in debugging "dataset leaks" and reference counting issues.
4313 : * The information reported includes the dataset name, referenced count,
4314 : * shared status, driver name, size, and band count.
4315 : */
4316 :
4317 276 : int CPL_STDCALL GDALDumpOpenDatasets(FILE *fp)
4318 :
4319 : {
4320 276 : VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
4321 :
4322 552 : CPLMutexHolderD(&hDLMutex);
4323 :
4324 276 : if (poAllDatasetMap == nullptr)
4325 276 : return 0;
4326 :
4327 0 : CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
4328 :
4329 0 : for (const auto &oIter : *poAllDatasetMap)
4330 : {
4331 0 : GDALDumpOpenDatasetsForeach(oIter.first, fp);
4332 : }
4333 :
4334 0 : if (phSharedDatasetSet != nullptr)
4335 : {
4336 0 : CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach,
4337 : fp);
4338 : }
4339 0 : return static_cast<int>(poAllDatasetMap->size());
4340 : }
4341 :
4342 : /************************************************************************/
4343 : /* BeginAsyncReader() */
4344 : /************************************************************************/
4345 :
4346 : /**
4347 : * \brief Sets up an asynchronous data request
4348 : *
4349 : * This method establish an asynchronous raster read request for the
4350 : * indicated window on the dataset into the indicated buffer. The parameters
4351 : * for windowing, buffer size, buffer type and buffer organization are similar
4352 : * to those for GDALDataset::RasterIO(); however, this call only launches
4353 : * the request and filling the buffer is accomplished via calls to
4354 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4355 : *
4356 : * Once all processing for the created session is complete, or if no further
4357 : * refinement of the request is required, the GDALAsyncReader object should
4358 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4359 : *
4360 : * Note that the data buffer (pData) will potentially continue to be
4361 : * updated as long as the session lives, but it is not deallocated when
4362 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4363 : * should be deallocated by the application at that point.
4364 : *
4365 : * Additional information on asynchronous IO in GDAL may be found at:
4366 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4367 : *
4368 : * This method is the same as the C GDALBeginAsyncReader() function.
4369 : *
4370 : * @param nXOff The pixel offset to the top left corner of the region
4371 : * of the band to be accessed. This would be zero to start from the left side.
4372 : *
4373 : * @param nYOff The line offset to the top left corner of the region
4374 : * of the band to be accessed. This would be zero to start from the top.
4375 : *
4376 : * @param nXSize The width of the region of the band to be accessed in pixels.
4377 : *
4378 : * @param nYSize The height of the region of the band to be accessed in lines.
4379 : *
4380 : * @param pBuf The buffer into which the data should be read. This buffer must
4381 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4382 : * It is organized in left to right,top to bottom pixel order. Spacing is
4383 : * controlled by the nPixelSpace, and nLineSpace parameters.
4384 : *
4385 : * @param nBufXSize the width of the buffer image into which the desired region
4386 : * is to be read, or from which it is to be written.
4387 : *
4388 : * @param nBufYSize the height of the buffer image into which the desired
4389 : * region is to be read, or from which it is to be written.
4390 : *
4391 : * @param eBufType the type of the pixel values in the pData data buffer. The
4392 : * pixel values will automatically be translated to/from the GDALRasterBand
4393 : * data type as needed.
4394 : *
4395 : * @param nBandCount the number of bands being read or written.
4396 : *
4397 : * @param panBandMap the list of nBandCount band numbers being read/written.
4398 : * Note band numbers are 1 based. This may be NULL to select the first
4399 : * nBandCount bands.
4400 : *
4401 : * @param nPixelSpace The byte offset from the start of one pixel value in
4402 : * pData to the start of the next pixel value within a scanline. If defaulted
4403 : * (0) the size of the datatype eBufType is used.
4404 : *
4405 : * @param nLineSpace The byte offset from the start of one scanline in
4406 : * pData to the start of the next. If defaulted the size of the datatype
4407 : * eBufType * nBufXSize is used.
4408 : *
4409 : * @param nBandSpace the byte offset from the start of one bands data to the
4410 : * start of the next. If defaulted (zero) the value will be
4411 : * nLineSpace * nBufYSize implying band sequential organization
4412 : * of the data buffer.
4413 : *
4414 : * @param papszOptions Driver specific control options in a string list or NULL.
4415 : * Consult driver documentation for options supported.
4416 : *
4417 : * @return The GDALAsyncReader object representing the request.
4418 : */
4419 :
4420 1 : GDALAsyncReader *GDALDataset::BeginAsyncReader(
4421 : int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
4422 : int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
4423 : int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions)
4424 : {
4425 : // See gdaldefaultasync.cpp
4426 :
4427 1 : return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
4428 : nBufXSize, nBufYSize, eBufType, nBandCount,
4429 : panBandMap, nPixelSpace, nLineSpace,
4430 1 : nBandSpace, papszOptions);
4431 : }
4432 :
4433 : /************************************************************************/
4434 : /* GDALBeginAsyncReader() */
4435 : /************************************************************************/
4436 :
4437 : /**
4438 : * \brief Sets up an asynchronous data request
4439 : *
4440 : * This method establish an asynchronous raster read request for the
4441 : * indicated window on the dataset into the indicated buffer. The parameters
4442 : * for windowing, buffer size, buffer type and buffer organization are similar
4443 : * to those for GDALDataset::RasterIO(); however, this call only launches
4444 : * the request and filling the buffer is accomplished via calls to
4445 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4446 : *
4447 : * Once all processing for the created session is complete, or if no further
4448 : * refinement of the request is required, the GDALAsyncReader object should
4449 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4450 : *
4451 : * Note that the data buffer (pData) will potentially continue to be
4452 : * updated as long as the session lives, but it is not deallocated when
4453 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4454 : * should be deallocated by the application at that point.
4455 : *
4456 : * Additional information on asynchronous IO in GDAL may be found at:
4457 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4458 : *
4459 : * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
4460 : *
4461 : * @param hDS handle to the dataset object.
4462 : *
4463 : * @param nXOff The pixel offset to the top left corner of the region
4464 : * of the band to be accessed. This would be zero to start from the left side.
4465 : *
4466 : * @param nYOff The line offset to the top left corner of the region
4467 : * of the band to be accessed. This would be zero to start from the top.
4468 : *
4469 : * @param nXSize The width of the region of the band to be accessed in pixels.
4470 : *
4471 : * @param nYSize The height of the region of the band to be accessed in lines.
4472 : *
4473 : * @param pBuf The buffer into which the data should be read. This buffer must
4474 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4475 : * It is organized in left to right,top to bottom pixel order. Spacing is
4476 : * controlled by the nPixelSpace, and nLineSpace parameters.
4477 : *
4478 : * @param nBufXSize the width of the buffer image into which the desired region
4479 : * is to be read, or from which it is to be written.
4480 : *
4481 : * @param nBufYSize the height of the buffer image into which the desired
4482 : * region is to be read, or from which it is to be written.
4483 : *
4484 : * @param eBufType the type of the pixel values in the pData data buffer. The
4485 : * pixel values will automatically be translated to/from the GDALRasterBand
4486 : * data type as needed.
4487 : *
4488 : * @param nBandCount the number of bands being read or written.
4489 : *
4490 : * @param panBandMap the list of nBandCount band numbers being read/written.
4491 : * Note band numbers are 1 based. This may be NULL to select the first
4492 : * nBandCount bands.
4493 : *
4494 : * @param nPixelSpace The byte offset from the start of one pixel value in
4495 : * pData to the start of the next pixel value within a scanline. If defaulted
4496 : * (0) the size of the datatype eBufType is used.
4497 : *
4498 : * @param nLineSpace The byte offset from the start of one scanline in
4499 : * pData to the start of the next. If defaulted the size of the datatype
4500 : * eBufType * nBufXSize is used.
4501 : *
4502 : * @param nBandSpace the byte offset from the start of one bands data to the
4503 : * start of the next. If defaulted (zero) the value will be
4504 : * nLineSpace * nBufYSize implying band sequential organization
4505 : * of the data buffer.
4506 : *
4507 : * @param papszOptions Driver specific control options in a string list or NULL.
4508 : * Consult driver documentation for options supported.
4509 : *
4510 : * @return handle representing the request.
4511 : */
4512 :
4513 2 : GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(
4514 : GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf,
4515 : int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount,
4516 : int *panBandMap, int nPixelSpace, int nLineSpace, int nBandSpace,
4517 : CSLConstList papszOptions)
4518 :
4519 : {
4520 2 : VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
4521 : return static_cast<GDALAsyncReaderH>(
4522 2 : GDALDataset::FromHandle(hDS)->BeginAsyncReader(
4523 : nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
4524 : nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
4525 2 : const_cast<char **>(papszOptions)));
4526 : }
4527 :
4528 : /************************************************************************/
4529 : /* EndAsyncReader() */
4530 : /************************************************************************/
4531 :
4532 : /**
4533 : * End asynchronous request.
4534 : *
4535 : * This method destroys an asynchronous io request and recovers all
4536 : * resources associated with it.
4537 : *
4538 : * This method is the same as the C function GDALEndAsyncReader().
4539 : *
4540 : * @param poARIO pointer to a GDALAsyncReader
4541 : */
4542 :
4543 1 : void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO)
4544 : {
4545 1 : delete poARIO;
4546 1 : }
4547 :
4548 : /************************************************************************/
4549 : /* GDALEndAsyncReader() */
4550 : /************************************************************************/
4551 :
4552 : /**
4553 : * End asynchronous request.
4554 : *
4555 : * This method destroys an asynchronous io request and recovers all
4556 : * resources associated with it.
4557 : *
4558 : * This method is the same as the C++ method GDALDataset::EndAsyncReader().
4559 : *
4560 : * @param hDS handle to the dataset object.
4561 : * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
4562 : */
4563 :
4564 1 : void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS,
4565 : GDALAsyncReaderH hAsyncReaderH)
4566 : {
4567 1 : VALIDATE_POINTER0(hDS, "GDALDataset");
4568 1 : VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
4569 1 : GDALDataset::FromHandle(hDS)->EndAsyncReader(
4570 1 : static_cast<GDALAsyncReader *>(hAsyncReaderH));
4571 : }
4572 :
4573 : /************************************************************************/
4574 : /* CloseDependentDatasets() */
4575 : /************************************************************************/
4576 :
4577 : /**
4578 : * Drop references to any other datasets referenced by this dataset.
4579 : *
4580 : * This method should release any reference to other datasets (e.g. a VRT
4581 : * dataset to its sources), but not close the current dataset itself.
4582 : *
4583 : * If at least, one reference to a dependent dataset has been dropped,
4584 : * this method should return TRUE. Otherwise it *should* return FALSE.
4585 : * (Failure to return the proper value might result in infinite loop)
4586 : *
4587 : * This method can be called several times on a given dataset. After
4588 : * the first time, it should not do anything and return FALSE.
4589 : *
4590 : * The driver implementation may choose to destroy its raster bands,
4591 : * so be careful not to call any method on the raster bands afterwards.
4592 : *
4593 : * Basically the only safe action you can do after calling
4594 : * CloseDependentDatasets() is to call the destructor.
4595 : *
4596 : * Note: the only legitimate caller of CloseDependentDatasets() is
4597 : * GDALDriverManager::~GDALDriverManager()
4598 : *
4599 : * @return TRUE if at least one reference to another dataset has been dropped.
4600 : */
4601 18939 : int GDALDataset::CloseDependentDatasets()
4602 : {
4603 18939 : return oOvManager.CloseDependentDatasets();
4604 : }
4605 :
4606 : /************************************************************************/
4607 : /* ReportError() */
4608 : /************************************************************************/
4609 :
4610 : #ifndef DOXYGEN_XML
4611 : /**
4612 : * \brief Emits an error related to a dataset.
4613 : *
4614 : * This function is a wrapper for regular CPLError(). The only difference
4615 : * with CPLError() is that it prepends the error message with the dataset
4616 : * name.
4617 : *
4618 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4619 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4620 : * @param fmt a printf() style format string. Any additional arguments
4621 : * will be treated as arguments to fill in this format in a manner
4622 : * similar to printf().
4623 : *
4624 : * @since GDAL 1.9.0
4625 : */
4626 :
4627 93 : void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4628 : const char *fmt, ...) const
4629 : {
4630 : va_list args;
4631 93 : va_start(args, fmt);
4632 93 : ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4633 93 : va_end(args);
4634 93 : }
4635 :
4636 : /**
4637 : * \brief Emits an error related to a dataset (static method)
4638 : *
4639 : * This function is a wrapper for regular CPLError(). The only difference
4640 : * with CPLError() is that it prepends the error message with the dataset
4641 : * name.
4642 : *
4643 : * @param pszDSName dataset name.
4644 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4645 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4646 : * @param fmt a printf() style format string. Any additional arguments
4647 : * will be treated as arguments to fill in this format in a manner
4648 : * similar to printf().
4649 : *
4650 : * @since GDAL 3.2.0
4651 : */
4652 :
4653 104 : void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,
4654 : CPLErrorNum err_no, const char *fmt, ...)
4655 : {
4656 : va_list args;
4657 104 : va_start(args, fmt);
4658 104 : ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4659 104 : va_end(args);
4660 104 : }
4661 :
4662 197 : void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,
4663 : CPLErrorNum err_no, const char *fmt,
4664 : va_list args)
4665 : {
4666 197 : pszDSName = CPLGetFilename(pszDSName);
4667 197 : if (pszDSName[0] != '\0')
4668 : {
4669 183 : CPLError(eErrClass, err_no, "%s",
4670 366 : std::string(pszDSName)
4671 183 : .append(": ")
4672 366 : .append(CPLString().vPrintf(fmt, args))
4673 : .c_str());
4674 : }
4675 : else
4676 : {
4677 14 : CPLErrorV(eErrClass, err_no, fmt, args);
4678 : }
4679 197 : }
4680 : #endif
4681 :
4682 : /************************************************************************/
4683 : /* GetMetadata() */
4684 : /************************************************************************/
4685 65600 : char **GDALDataset::GetMetadata(const char *pszDomain)
4686 : {
4687 : #ifndef WITHOUT_DERIVED
4688 65600 : if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
4689 : {
4690 9 : oDerivedMetadataList.Clear();
4691 :
4692 : // First condition: at least one raster band.
4693 9 : if (GetRasterCount() > 0)
4694 : {
4695 : // Check if there is at least one complex band.
4696 9 : bool hasAComplexBand = false;
4697 :
4698 16 : for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4699 : {
4700 9 : if (GDALDataTypeIsComplex(
4701 9 : GetRasterBand(rasterId)->GetRasterDataType()))
4702 : {
4703 2 : hasAComplexBand = true;
4704 2 : break;
4705 : }
4706 : }
4707 :
4708 9 : unsigned int nbSupportedDerivedDS = 0;
4709 : const DerivedDatasetDescription *poDDSDesc =
4710 9 : GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4711 :
4712 9 : int nNumDataset = 1;
4713 72 : for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4714 : ++derivedId)
4715 : {
4716 112 : if (hasAComplexBand ||
4717 112 : CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4718 : "complex")
4719 : {
4720 : oDerivedMetadataList.SetNameValue(
4721 : CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4722 : CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4723 21 : poDDSDesc[derivedId].pszDatasetName,
4724 21 : GetDescription()));
4725 :
4726 : CPLString osDesc(
4727 : CPLSPrintf("%s from %s",
4728 21 : poDDSDesc[derivedId].pszDatasetDescription,
4729 21 : GetDescription()));
4730 : oDerivedMetadataList.SetNameValue(
4731 : CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4732 21 : osDesc.c_str());
4733 :
4734 21 : nNumDataset++;
4735 : }
4736 : }
4737 : }
4738 9 : return oDerivedMetadataList.List();
4739 : }
4740 : #endif
4741 :
4742 65591 : return GDALMajorObject::GetMetadata(pszDomain);
4743 : }
4744 :
4745 : // clang-format off
4746 :
4747 : /**
4748 : * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
4749 : * \brief Set metadata.
4750 : *
4751 : * CAUTION: depending on the format, older values of the updated information
4752 : * might still be found in the file in a "ghost" state, even if no longer
4753 : * accessible through the GDAL API. This is for example the case of the GTiff
4754 : * format (this is not a exhaustive list)
4755 : *
4756 : * The C function GDALSetMetadata() does the same thing as this method.
4757 : *
4758 : * @param papszMetadata the metadata in name=value string list format to
4759 : * apply.
4760 : * @param pszDomain the domain of interest. Use "" or NULL for the default
4761 : * domain.
4762 : * @return CE_None on success, CE_Failure on failure and CE_Warning if the
4763 : * metadata has been accepted, but is likely not maintained persistently
4764 : * by the underlying object between sessions.
4765 : */
4766 :
4767 : /**
4768 : * \fn GDALDataset::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
4769 : * \brief Set single metadata item.
4770 : *
4771 : * CAUTION: depending on the format, older values of the updated information
4772 : * might still be found in the file in a "ghost" state, even if no longer
4773 : * accessible through the GDAL API. This is for example the case of the GTiff
4774 : * format (this is not a exhaustive list)
4775 : *
4776 : * The C function GDALSetMetadataItem() does the same thing as this method.
4777 : *
4778 : * @param pszName the key for the metadata item to fetch.
4779 : * @param pszValue the value to assign to the key.
4780 : * @param pszDomain the domain to set within, use NULL for the default domain.
4781 : *
4782 : * @return CE_None on success, or an error code on failure.
4783 : */
4784 :
4785 : // clang-format on
4786 :
4787 : /************************************************************************/
4788 : /* GetMetadataDomainList() */
4789 : /************************************************************************/
4790 :
4791 840 : char **GDALDataset::GetMetadataDomainList()
4792 : {
4793 840 : char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
4794 :
4795 : // Ensure that we do not duplicate DERIVED domain.
4796 979 : if (GetRasterCount() > 0 &&
4797 139 : CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
4798 : {
4799 : currentDomainList =
4800 139 : CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
4801 : }
4802 840 : return currentDomainList;
4803 : }
4804 :
4805 : /************************************************************************/
4806 : /* GetDriverName() */
4807 : /************************************************************************/
4808 :
4809 : /** Return driver name.
4810 : * @return driver name.
4811 : */
4812 2149 : const char *GDALDataset::GetDriverName()
4813 : {
4814 2149 : if (poDriver)
4815 2137 : return poDriver->GetDescription();
4816 12 : return "";
4817 : }
4818 :
4819 : /************************************************************************/
4820 : /* GDALDatasetReleaseResultSet() */
4821 : /************************************************************************/
4822 :
4823 : /**
4824 : \brief Release results of ExecuteSQL().
4825 :
4826 : This function should only be used to deallocate OGRLayers resulting from
4827 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
4828 : results set before destroying the GDALDataset may cause errors.
4829 :
4830 : This function is the same as the C++ method GDALDataset::ReleaseResultSet()
4831 :
4832 : @since GDAL 2.0
4833 :
4834 : @param hDS the dataset handle.
4835 : @param hLayer the result of a previous ExecuteSQL() call.
4836 :
4837 : */
4838 3593 : void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)
4839 :
4840 : {
4841 3593 : VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
4842 :
4843 : #ifdef OGRAPISPY_ENABLED
4844 3593 : if (bOGRAPISpyEnabled)
4845 6 : OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
4846 : #endif
4847 :
4848 7186 : GDALDataset::FromHandle(hDS)->ReleaseResultSet(
4849 3593 : OGRLayer::FromHandle(hLayer));
4850 : }
4851 :
4852 : /************************************************************************/
4853 : /* GDALDatasetGetLayerCount() */
4854 : /************************************************************************/
4855 :
4856 : /**
4857 : \brief Get the number of layers in this dataset.
4858 :
4859 : This function is the same as the C++ method GDALDataset::GetLayerCount()
4860 :
4861 : @since GDAL 2.0
4862 :
4863 : @param hDS the dataset handle.
4864 : @return layer count.
4865 : */
4866 :
4867 1425 : int GDALDatasetGetLayerCount(GDALDatasetH hDS)
4868 :
4869 : {
4870 1425 : VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
4871 :
4872 : #ifdef OGRAPISPY_ENABLED
4873 1425 : if (bOGRAPISpyEnabled)
4874 2 : OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
4875 : #endif
4876 :
4877 1425 : return GDALDataset::FromHandle(hDS)->GetLayerCount();
4878 : }
4879 :
4880 : /************************************************************************/
4881 : /* GDALDatasetGetLayer() */
4882 : /************************************************************************/
4883 :
4884 : /**
4885 : \brief Fetch a layer by index.
4886 :
4887 : The returned layer remains owned by the
4888 : GDALDataset and should not be deleted by the application.
4889 :
4890 : This function is the same as the C++ method GDALDataset::GetLayer()
4891 :
4892 : @since GDAL 2.0
4893 :
4894 : @param hDS the dataset handle.
4895 : @param iLayer a layer number between 0 and GetLayerCount()-1.
4896 :
4897 : @return the layer, or NULL if iLayer is out of range or an error occurs.
4898 : */
4899 :
4900 9070 : OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)
4901 :
4902 : {
4903 9070 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
4904 :
4905 : OGRLayerH hLayer =
4906 9070 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
4907 :
4908 : #ifdef OGRAPISPY_ENABLED
4909 9070 : if (bOGRAPISpyEnabled)
4910 3 : OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
4911 : #endif
4912 :
4913 9070 : return hLayer;
4914 : }
4915 :
4916 : /************************************************************************/
4917 : /* GDALDatasetGetLayerByName() */
4918 : /************************************************************************/
4919 :
4920 : /**
4921 : \brief Fetch a layer by name.
4922 :
4923 : The returned layer remains owned by the
4924 : GDALDataset and should not be deleted by the application.
4925 :
4926 : This function is the same as the C++ method GDALDataset::GetLayerByName()
4927 :
4928 : @since GDAL 2.0
4929 :
4930 : @param hDS the dataset handle.
4931 : @param pszName the layer name of the layer to fetch.
4932 :
4933 : @return the layer, or NULL if Layer is not found or an error occurs.
4934 : */
4935 :
4936 3547 : OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)
4937 :
4938 : {
4939 3547 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
4940 :
4941 3547 : OGRLayerH hLayer = OGRLayer::ToHandle(
4942 3547 : GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
4943 :
4944 : #ifdef OGRAPISPY_ENABLED
4945 3547 : if (bOGRAPISpyEnabled)
4946 4 : OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
4947 : #endif
4948 :
4949 3547 : return hLayer;
4950 : }
4951 :
4952 : /************************************************************************/
4953 : /* GDALDatasetIsLayerPrivate() */
4954 : /************************************************************************/
4955 :
4956 : /**
4957 : \brief Returns true if the layer at the specified index is deemed a private or
4958 : system table, or an internal detail only.
4959 :
4960 : This function is the same as the C++ method GDALDataset::IsLayerPrivate()
4961 :
4962 : @since GDAL 3.4
4963 :
4964 : @param hDS the dataset handle.
4965 : @param iLayer a layer number between 0 and GetLayerCount()-1.
4966 :
4967 : @return true if the layer is a private or system table.
4968 : */
4969 :
4970 91 : int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)
4971 :
4972 : {
4973 91 : VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);
4974 :
4975 91 : const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);
4976 :
4977 91 : return res ? 1 : 0;
4978 : }
4979 :
4980 : /************************************************************************/
4981 : /* GDALDatasetDeleteLayer() */
4982 : /************************************************************************/
4983 :
4984 : /**
4985 : \brief Delete the indicated layer from the datasource.
4986 :
4987 : If this function is supported
4988 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
4989 :
4990 : This method is the same as the C++ method GDALDataset::DeleteLayer().
4991 :
4992 : @since GDAL 2.0
4993 :
4994 : @param hDS the dataset handle.
4995 : @param iLayer the index of the layer to delete.
4996 :
4997 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
4998 : layers is not supported for this datasource.
4999 :
5000 : */
5001 42 : OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)
5002 :
5003 : {
5004 42 : VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
5005 :
5006 : #ifdef OGRAPISPY_ENABLED
5007 42 : if (bOGRAPISpyEnabled)
5008 2 : OGRAPISpy_DS_DeleteLayer(hDS, iLayer);
5009 : #endif
5010 :
5011 42 : return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
5012 : }
5013 :
5014 : /************************************************************************/
5015 : /* CreateLayer() */
5016 : /************************************************************************/
5017 :
5018 : /**
5019 : \brief This method attempts to create a new layer on the dataset with the
5020 : indicated name, coordinate system, geometry type.
5021 :
5022 : The papszOptions argument
5023 : can be used to control driver specific creation options. These options are
5024 : normally documented in the format specific documentation.
5025 : That function will try to validate the creation option list passed to the
5026 : driver with the GDALValidateCreationOptions() method. This check can be
5027 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5028 : to NO.
5029 :
5030 : Drivers should extend the ICreateLayer() method and not
5031 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5032 : delegating the actual work to ICreateLayer().
5033 :
5034 : This method is the same as the C function GDALDatasetCreateLayer() and the
5035 : deprecated OGR_DS_CreateLayer().
5036 :
5037 : Example:
5038 :
5039 : \code{.cpp}
5040 : #include "gdal.h"
5041 : #include "cpl_string.h"
5042 :
5043 : ...
5044 :
5045 : OGRLayer *poLayer;
5046 : char **papszOptions;
5047 :
5048 : if( !poDS->TestCapability( ODsCCreateLayer ) )
5049 : {
5050 : ...
5051 : }
5052 :
5053 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5054 : poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
5055 : papszOptions );
5056 : CSLDestroy( papszOptions );
5057 :
5058 : if( poLayer == NULL )
5059 : {
5060 : ...
5061 : }
5062 : \endcode
5063 :
5064 : @param pszName the name for the new layer. This should ideally not
5065 : match any existing layer on the datasource.
5066 : @param poSpatialRef the coordinate system to use for the new layer, or NULL if
5067 : no coordinate system is available.
5068 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5069 : are no constraints on the types geometry to be written.
5070 : @param papszOptions a StringList of name=value options. Options are driver
5071 : specific.
5072 :
5073 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5074 :
5075 : */
5076 :
5077 7393 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5078 : const OGRSpatialReference *poSpatialRef,
5079 : OGRwkbGeometryType eGType,
5080 : CSLConstList papszOptions)
5081 :
5082 : {
5083 7393 : if (eGType == wkbNone)
5084 : {
5085 451 : return CreateLayer(pszName, nullptr, papszOptions);
5086 : }
5087 : else
5088 : {
5089 13884 : OGRGeomFieldDefn oGeomFieldDefn("", eGType);
5090 6942 : oGeomFieldDefn.SetSpatialRef(poSpatialRef);
5091 6942 : return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5092 : }
5093 : }
5094 :
5095 : /**
5096 : \brief This method attempts to create a new layer on the dataset with the
5097 : indicated name and geometry field definition.
5098 :
5099 : When poGeomFieldDefn is not null, most drivers should honor
5100 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5101 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5102 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5103 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5104 : very few currently.
5105 :
5106 : Note that even if a geometry coordinate precision is set and a driver honors the
5107 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5108 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5109 : with the coordinate precision. That is they are assumed to be valid once their
5110 : coordinates are rounded to it. If it might not be the case, the user may set
5111 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5112 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5113 : the passed geometries.
5114 :
5115 : The papszOptions argument
5116 : can be used to control driver specific creation options. These options are
5117 : normally documented in the format specific documentation.
5118 : This function will try to validate the creation option list passed to the
5119 : driver with the GDALValidateCreationOptions() method. This check can be
5120 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5121 : to NO.
5122 :
5123 : Drivers should extend the ICreateLayer() method and not
5124 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5125 : delegating the actual work to ICreateLayer().
5126 :
5127 : This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().
5128 :
5129 : @param pszName the name for the new layer. This should ideally not
5130 : match any existing layer on the datasource.
5131 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5132 : or NULL if there is no geometry field.
5133 : @param papszOptions a StringList of name=value options. Options are driver
5134 : specific.
5135 :
5136 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5137 : @since 3.9
5138 :
5139 : */
5140 :
5141 8638 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5142 : const OGRGeomFieldDefn *poGeomFieldDefn,
5143 : CSLConstList papszOptions)
5144 :
5145 : {
5146 8638 : if (CPLTestBool(
5147 : CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
5148 : {
5149 8638 : ValidateLayerCreationOptions(papszOptions);
5150 : }
5151 :
5152 : OGRLayer *poLayer;
5153 8638 : if (poGeomFieldDefn)
5154 : {
5155 7941 : OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);
5156 8035 : if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&
5157 94 : !TestCapability(ODsCCurveGeometries))
5158 : {
5159 23 : oGeomFieldDefn.SetType(
5160 : OGR_GT_GetLinear(poGeomFieldDefn->GetType()));
5161 : }
5162 :
5163 7941 : poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5164 : }
5165 : else
5166 : {
5167 697 : poLayer = ICreateLayer(pszName, nullptr, papszOptions);
5168 : }
5169 : #ifdef DEBUG
5170 8709 : if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
5171 71 : !poLayer->TestCapability(OLCCurveGeometries))
5172 : {
5173 0 : CPLError(CE_Warning, CPLE_AppDefined,
5174 : "Inconsistent driver: Layer geometry type is non-linear, but "
5175 : "TestCapability(OLCCurveGeometries) returns FALSE.");
5176 : }
5177 : #endif
5178 :
5179 8638 : return poLayer;
5180 : }
5181 :
5182 : //! @cond Doxygen_Suppress
5183 :
5184 : // Technical override to avoid ambiguous choice between the old and new
5185 : // new CreateLayer() signatures.
5186 11 : OGRLayer *GDALDataset::CreateLayer(const char *pszName)
5187 : {
5188 22 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5189 22 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5190 : }
5191 :
5192 : // Technical override to avoid ambiguous choice between the old and new
5193 : // new CreateLayer() signatures.
5194 1 : OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)
5195 : {
5196 2 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5197 2 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5198 : }
5199 :
5200 : //!@endcond
5201 :
5202 : /************************************************************************/
5203 : /* GDALDatasetCreateLayer() */
5204 : /************************************************************************/
5205 :
5206 : /**
5207 : \brief This function attempts to create a new layer on the dataset with the
5208 : indicated name, coordinate system, geometry type.
5209 :
5210 : The papszOptions argument can be used to control driver specific creation
5211 : options. These options are normally documented in the format specific
5212 : documentation.
5213 :
5214 : This method is the same as the C++ method GDALDataset::CreateLayer().
5215 :
5216 : Example:
5217 :
5218 : \code{.c}
5219 : #include "gdal.h"
5220 : #include "cpl_string.h"
5221 :
5222 : ...
5223 :
5224 : OGRLayerH hLayer;
5225 : char **papszOptions;
5226 :
5227 : if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
5228 : {
5229 : ...
5230 : }
5231 :
5232 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5233 : hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
5234 : papszOptions );
5235 : CSLDestroy( papszOptions );
5236 :
5237 : if( hLayer == NULL )
5238 : {
5239 : ...
5240 : }
5241 : \endcode
5242 :
5243 : @since GDAL 2.0
5244 :
5245 : @param hDS the dataset handle
5246 : @param pszName the name for the new layer. This should ideally not
5247 : match any existing layer on the datasource.
5248 : @param hSpatialRef the coordinate system to use for the new layer, or NULL if
5249 : no coordinate system is available.
5250 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5251 : are no constraints on the types geometry to be written.
5252 : @param papszOptions a StringList of name=value options. Options are driver
5253 : specific.
5254 :
5255 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5256 :
5257 : */
5258 :
5259 5593 : OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,
5260 : OGRSpatialReferenceH hSpatialRef,
5261 : OGRwkbGeometryType eGType,
5262 : CSLConstList papszOptions)
5263 :
5264 : {
5265 5593 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
5266 :
5267 5593 : if (pszName == nullptr)
5268 : {
5269 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5270 : "Name was NULL in GDALDatasetCreateLayer");
5271 0 : return nullptr;
5272 : }
5273 :
5274 : OGRLayerH hLayer =
5275 11186 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5276 5593 : pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,
5277 : const_cast<char **>(papszOptions)));
5278 :
5279 : #ifdef OGRAPISPY_ENABLED
5280 5593 : if (bOGRAPISpyEnabled)
5281 8 : OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,
5282 : const_cast<char **>(papszOptions), hLayer);
5283 : #endif
5284 :
5285 5593 : return hLayer;
5286 : }
5287 :
5288 : /************************************************************************/
5289 : /* GDALDatasetCreateLayerFromGeomFieldDefn() */
5290 : /************************************************************************/
5291 :
5292 : /**
5293 : \brief This function attempts to create a new layer on the dataset with the
5294 : indicated name and geometry field.
5295 :
5296 : When poGeomFieldDefn is not null, most drivers should honor
5297 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5298 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5299 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5300 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5301 : very few currently.
5302 :
5303 : Note that even if a geometry coordinate precision is set and a driver honors the
5304 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5305 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5306 : with the coordinate precision. That is they are assumed to be valid once their
5307 : coordinates are rounded to it. If it might not be the case, the user may set
5308 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5309 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5310 : the passed geometries.
5311 :
5312 : The papszOptions argument can be used to control driver specific creation
5313 : options. These options are normally documented in the format specific
5314 : documentation.
5315 :
5316 : This method is the same as the C++ method GDALDataset::CreateLayer().
5317 :
5318 : @param hDS the dataset handle
5319 : @param pszName the name for the new layer. This should ideally not
5320 : match any existing layer on the datasource.
5321 : @param hGeomFieldDefn the geometry field definition. May be NULL to indicate
5322 : a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()
5323 : for drivers supporting that interface).
5324 : @param papszOptions a StringList of name=value options. Options are driver
5325 : specific.
5326 :
5327 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5328 :
5329 : @since GDAL 3.9
5330 :
5331 : */
5332 :
5333 : OGRLayerH
5334 16 : GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,
5335 : OGRGeomFieldDefnH hGeomFieldDefn,
5336 : CSLConstList papszOptions)
5337 :
5338 : {
5339 16 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);
5340 :
5341 16 : if (!pszName)
5342 : {
5343 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5344 : "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");
5345 0 : return nullptr;
5346 : }
5347 :
5348 : OGRLayerH hLayer =
5349 32 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5350 16 : pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),
5351 : papszOptions));
5352 16 : return hLayer;
5353 : }
5354 :
5355 : /************************************************************************/
5356 : /* GDALDatasetCopyLayer() */
5357 : /************************************************************************/
5358 :
5359 : /**
5360 : \brief Duplicate an existing layer.
5361 :
5362 : This function creates a new layer, duplicate the field definitions of the
5363 : source layer and then duplicate each features of the source layer.
5364 : The papszOptions argument
5365 : can be used to control driver specific creation options. These options are
5366 : normally documented in the format specific documentation.
5367 : The source layer may come from another dataset.
5368 :
5369 : This method is the same as the C++ method GDALDataset::CopyLayer()
5370 :
5371 : @since GDAL 2.0
5372 :
5373 : @param hDS the dataset handle.
5374 : @param hSrcLayer source layer.
5375 : @param pszNewName the name of the layer to create.
5376 : @param papszOptions a StringList of name=value options. Options are driver
5377 : specific.
5378 :
5379 : @return a handle to the layer, or NULL if an error occurs.
5380 : */
5381 10 : OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,
5382 : const char *pszNewName,
5383 : CSLConstList papszOptions)
5384 :
5385 : {
5386 10 : VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
5387 10 : VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
5388 10 : VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
5389 :
5390 20 : return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(
5391 : OGRLayer::FromHandle(hSrcLayer), pszNewName,
5392 20 : const_cast<char **>(papszOptions)));
5393 : }
5394 :
5395 : /************************************************************************/
5396 : /* GDALDatasetExecuteSQL() */
5397 : /************************************************************************/
5398 :
5399 : /**
5400 : \brief Execute an SQL statement against the data store.
5401 :
5402 : The result of an SQL query is either NULL for statements that are in error,
5403 : or that have no results set, or an OGRLayer pointer representing a results
5404 : set from the query. Note that this OGRLayer is in addition to the layers
5405 : in the data store and must be destroyed with
5406 : ReleaseResultSet() before the dataset is closed
5407 : (destroyed).
5408 :
5409 : This method is the same as the C++ method GDALDataset::ExecuteSQL()
5410 :
5411 : For more information on the SQL dialect supported internally by OGR
5412 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
5413 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
5414 : to the underlying RDBMS.
5415 :
5416 : Starting with OGR 1.10, the <a
5417 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
5418 : also be used.
5419 :
5420 : @since GDAL 2.0
5421 :
5422 : @param hDS the dataset handle.
5423 : @param pszStatement the SQL statement to execute.
5424 : @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
5425 :
5426 : @param pszDialect allows control of the statement dialect. If set to NULL, the
5427 : OGR SQL engine will be used, except for RDBMS drivers that will use their
5428 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
5429 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
5430 :
5431 : @return an OGRLayer containing the results of the query. Deallocate with
5432 : GDALDatasetReleaseResultSet().
5433 :
5434 : */
5435 :
5436 10218 : OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,
5437 : OGRGeometryH hSpatialFilter,
5438 : const char *pszDialect)
5439 :
5440 : {
5441 10218 : VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
5442 :
5443 : OGRLayerH hLayer =
5444 20436 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(
5445 10218 : pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));
5446 :
5447 : #ifdef OGRAPISPY_ENABLED
5448 10218 : if (bOGRAPISpyEnabled)
5449 4 : OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,
5450 : hLayer);
5451 : #endif
5452 :
5453 10218 : return hLayer;
5454 : }
5455 :
5456 : /************************************************************************/
5457 : /* GDALDatasetAbortSQL() */
5458 : /************************************************************************/
5459 :
5460 : /**
5461 : \brief Abort any SQL statement running in the data store.
5462 :
5463 : This function can be safely called from any thread (pending that the dataset
5464 : object is still alive). Driver implementations will make sure that it can be
5465 : called in a thread-safe way.
5466 :
5467 : This might not be implemented by all drivers. At time of writing, only SQLite,
5468 : GPKG and PG drivers implement it
5469 :
5470 : This method is the same as the C++ method GDALDataset::AbortSQL()
5471 :
5472 : @since GDAL 3.2.0
5473 :
5474 : @param hDS the dataset handle.
5475 :
5476 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
5477 : is not supported for this datasource. .
5478 :
5479 : */
5480 :
5481 6 : OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)
5482 :
5483 : {
5484 6 : VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);
5485 6 : return GDALDataset::FromHandle(hDS)->AbortSQL();
5486 : }
5487 :
5488 : /************************************************************************/
5489 : /* GDALDatasetGetStyleTable() */
5490 : /************************************************************************/
5491 :
5492 : /**
5493 : \brief Returns dataset style table.
5494 :
5495 : This function is the same as the C++ method GDALDataset::GetStyleTable()
5496 :
5497 : @since GDAL 2.0
5498 :
5499 : @param hDS the dataset handle
5500 : @return handle to a style table which should not be modified or freed by the
5501 : caller.
5502 : */
5503 :
5504 6 : OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)
5505 :
5506 : {
5507 6 : VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
5508 :
5509 : return reinterpret_cast<OGRStyleTableH>(
5510 6 : GDALDataset::FromHandle(hDS)->GetStyleTable());
5511 : }
5512 :
5513 : /************************************************************************/
5514 : /* GDALDatasetSetStyleTableDirectly() */
5515 : /************************************************************************/
5516 :
5517 : /**
5518 : \brief Set dataset style table.
5519 :
5520 : This function operate exactly as GDALDatasetSetStyleTable() except that it
5521 : assumes ownership of the passed table.
5522 :
5523 : This function is the same as the C++ method
5524 : GDALDataset::SetStyleTableDirectly()
5525 :
5526 : @since GDAL 2.0
5527 :
5528 : @param hDS the dataset handle
5529 : @param hStyleTable style table handle to set
5530 :
5531 : */
5532 :
5533 0 : void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,
5534 : OGRStyleTableH hStyleTable)
5535 :
5536 : {
5537 0 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
5538 :
5539 0 : GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(
5540 0 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5541 : }
5542 :
5543 : /************************************************************************/
5544 : /* GDALDatasetSetStyleTable() */
5545 : /************************************************************************/
5546 :
5547 : /**
5548 : \brief Set dataset style table.
5549 :
5550 : This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
5551 : it assumes ownership of the passed table.
5552 :
5553 : This function is the same as the C++ method GDALDataset::SetStyleTable()
5554 :
5555 : @since GDAL 2.0
5556 :
5557 : @param hDS the dataset handle
5558 : @param hStyleTable style table handle to set
5559 :
5560 : */
5561 :
5562 5 : void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)
5563 :
5564 : {
5565 5 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
5566 5 : VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
5567 :
5568 5 : GDALDataset::FromHandle(hDS)->SetStyleTable(
5569 5 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5570 : }
5571 :
5572 : /************************************************************************/
5573 : /* ValidateLayerCreationOptions() */
5574 : /************************************************************************/
5575 :
5576 : //! @cond Doxygen_Suppress
5577 8638 : int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)
5578 : {
5579 : const char *pszOptionList =
5580 8638 : GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5581 8638 : if (pszOptionList == nullptr && poDriver != nullptr)
5582 : {
5583 : pszOptionList =
5584 8638 : poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5585 : }
5586 17276 : CPLString osDataset;
5587 8638 : osDataset.Printf("dataset %s", GetDescription());
5588 8638 : return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",
5589 17276 : osDataset);
5590 : }
5591 :
5592 : //! @endcond
5593 :
5594 : /************************************************************************/
5595 : /* Release() */
5596 : /************************************************************************/
5597 :
5598 : /**
5599 : \brief Drop a reference to this dataset, and if the reference count drops to one
5600 : close (destroy) the dataset.
5601 :
5602 : This method is the same as the C function OGRReleaseDataSource().
5603 :
5604 : @deprecated. In GDAL 2, use GDALClose() instead
5605 :
5606 : @return OGRERR_NONE on success or an error code.
5607 : */
5608 :
5609 2189 : OGRErr GDALDataset::Release()
5610 :
5611 : {
5612 2189 : ReleaseRef();
5613 2189 : return OGRERR_NONE;
5614 : }
5615 :
5616 : /************************************************************************/
5617 : /* GetRefCount() */
5618 : /************************************************************************/
5619 :
5620 : /**
5621 : \brief Fetch reference count.
5622 :
5623 : This method is the same as the C function OGR_DS_GetRefCount().
5624 :
5625 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5626 :
5627 : @return the current reference count for the datasource object itself.
5628 : */
5629 :
5630 852 : int GDALDataset::GetRefCount() const
5631 : {
5632 852 : return nRefCount;
5633 : }
5634 :
5635 : /************************************************************************/
5636 : /* GetSummaryRefCount() */
5637 : /************************************************************************/
5638 :
5639 : /**
5640 : \brief Fetch reference count of datasource and all owned layers.
5641 :
5642 : This method is the same as the C function OGR_DS_GetSummaryRefCount().
5643 :
5644 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5645 :
5646 : @deprecated
5647 :
5648 : @return the current summary reference count for the datasource and its layers.
5649 : */
5650 :
5651 0 : int GDALDataset::GetSummaryRefCount() const
5652 :
5653 : {
5654 0 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5655 0 : int nSummaryCount = nRefCount;
5656 0 : GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
5657 :
5658 0 : for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)
5659 0 : nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
5660 :
5661 0 : return nSummaryCount;
5662 : }
5663 :
5664 : /************************************************************************/
5665 : /* ICreateLayer() */
5666 : /************************************************************************/
5667 :
5668 : /**
5669 : \brief This method attempts to create a new layer on the dataset with the
5670 : indicated name, coordinate system, geometry type.
5671 :
5672 : This method is reserved to implementation by drivers.
5673 :
5674 : The papszOptions argument can be used to control driver specific creation
5675 : options. These options are normally documented in the format specific
5676 : documentation.
5677 :
5678 : @param pszName the name for the new layer. This should ideally not
5679 : match any existing layer on the datasource.
5680 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5681 : or NULL if there is no geometry field.
5682 : @param papszOptions a StringList of name=value options. Options are driver
5683 : specific.
5684 :
5685 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5686 :
5687 : @since GDAL 2.0 (prototype modified in 3.9)
5688 : */
5689 :
5690 : OGRLayer *
5691 16 : GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,
5692 : CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,
5693 : CPL_UNUSED CSLConstList papszOptions)
5694 :
5695 : {
5696 16 : CPLError(CE_Failure, CPLE_NotSupported,
5697 : "CreateLayer() not supported by this dataset.");
5698 :
5699 16 : return nullptr;
5700 : }
5701 :
5702 : /************************************************************************/
5703 : /* CopyLayer() */
5704 : /************************************************************************/
5705 :
5706 : /**
5707 : \brief Duplicate an existing layer.
5708 :
5709 : This method creates a new layer, duplicate the field definitions of the
5710 : source layer and then duplicate each features of the source layer.
5711 : The papszOptions argument
5712 : can be used to control driver specific creation options. These options are
5713 : normally documented in the format specific documentation.
5714 : The source layer may come from another dataset.
5715 :
5716 : This method is the same as the C function GDALDatasetCopyLayer() and the
5717 : deprecated OGR_DS_CopyLayer().
5718 :
5719 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5720 :
5721 : @param poSrcLayer source layer.
5722 : @param pszNewName the name of the layer to create.
5723 : @param papszOptions a StringList of name=value options. Options are driver
5724 : specific. There is a common option to set output layer
5725 : spatial reference: DST_SRSWKT. The option should be in
5726 : WKT format. Starting with GDAL 3.7, the common option
5727 : COPY_MD can be set to NO to prevent the default copying
5728 : of the metadata from the source layer to the target layer.
5729 :
5730 : @return a handle to the layer, or NULL if an error occurs.
5731 : */
5732 :
5733 126 : OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
5734 : char **papszOptions)
5735 :
5736 : {
5737 : /* -------------------------------------------------------------------- */
5738 : /* Create the layer. */
5739 : /* -------------------------------------------------------------------- */
5740 126 : if (!TestCapability(ODsCCreateLayer))
5741 : {
5742 0 : CPLError(CE_Failure, CPLE_NotSupported,
5743 : "This datasource does not support creation of layers.");
5744 0 : return nullptr;
5745 : }
5746 :
5747 126 : const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
5748 252 : OGRSpatialReference oDstSpaRef(pszSRSWKT);
5749 126 : oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5750 126 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
5751 126 : OGRLayer *poDstLayer = nullptr;
5752 :
5753 252 : CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));
5754 126 : aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr);
5755 126 : aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr);
5756 :
5757 126 : CPLErrorReset();
5758 126 : const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
5759 126 : if (nSrcGeomFieldCount == 1)
5760 : {
5761 74 : OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
5762 74 : if (pszSRSWKT)
5763 5 : oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);
5764 74 : poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,
5765 74 : aosCleanedUpOptions.List());
5766 : }
5767 : else
5768 : {
5769 : poDstLayer =
5770 52 : ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());
5771 : }
5772 :
5773 126 : if (poDstLayer == nullptr)
5774 0 : return nullptr;
5775 :
5776 126 : if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))
5777 : {
5778 125 : char **papszMD = poSrcLayer->GetMetadata();
5779 125 : if (papszMD)
5780 5 : poDstLayer->SetMetadata(papszMD);
5781 : }
5782 :
5783 : /* -------------------------------------------------------------------- */
5784 : /* Add fields. Default to copy all fields, and make sure to */
5785 : /* establish a mapping between indices, rather than names, in */
5786 : /* case the target datasource has altered it (e.g. Shapefile */
5787 : /* limited to 10 char field names). */
5788 : /* -------------------------------------------------------------------- */
5789 126 : const int nSrcFieldCount = poSrcDefn->GetFieldCount();
5790 :
5791 : // Initialize the index-to-index map to -1's.
5792 252 : std::vector<int> anMap(nSrcFieldCount, -1);
5793 :
5794 : // Caution: At the time of writing, the MapInfo driver
5795 : // returns NULL until a field has been added.
5796 126 : OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
5797 126 : int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
5798 271 : for (int iField = 0; iField < nSrcFieldCount; ++iField)
5799 : {
5800 145 : OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
5801 290 : OGRFieldDefn oFieldDefn(poSrcFieldDefn);
5802 :
5803 : // The field may have been already created at layer creation.
5804 145 : int iDstField = -1;
5805 145 : if (poDstFDefn)
5806 145 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
5807 145 : if (iDstField >= 0)
5808 : {
5809 0 : anMap[iField] = iDstField;
5810 : }
5811 145 : else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)
5812 : {
5813 : // Now that we've created a field, GetLayerDefn() won't return NULL.
5814 145 : if (poDstFDefn == nullptr)
5815 0 : poDstFDefn = poDstLayer->GetLayerDefn();
5816 :
5817 : // Sanity check: if it fails, the driver is buggy.
5818 290 : if (poDstFDefn != nullptr &&
5819 145 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
5820 : {
5821 0 : CPLError(CE_Warning, CPLE_AppDefined,
5822 : "The output driver has claimed to have added the %s "
5823 : "field, but it did not!",
5824 : oFieldDefn.GetNameRef());
5825 : }
5826 : else
5827 : {
5828 145 : anMap[iField] = nDstFieldCount;
5829 145 : ++nDstFieldCount;
5830 : }
5831 : }
5832 : }
5833 :
5834 : /* -------------------------------------------------------------------- */
5835 126 : std::unique_ptr<OGRCoordinateTransformation> poCT;
5836 126 : OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
5837 126 : if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&
5838 0 : sourceSRS->IsSame(&oDstSpaRef) == FALSE)
5839 : {
5840 0 : poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));
5841 0 : if (nullptr == poCT)
5842 : {
5843 0 : CPLError(CE_Failure, CPLE_NotSupported,
5844 : "This input/output spatial reference is not supported.");
5845 0 : return nullptr;
5846 : }
5847 : }
5848 : /* -------------------------------------------------------------------- */
5849 : /* Create geometry fields. */
5850 : /* -------------------------------------------------------------------- */
5851 127 : if (nSrcGeomFieldCount > 1 &&
5852 1 : TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
5853 : {
5854 :
5855 3 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5856 : {
5857 2 : if (nullptr == pszSRSWKT)
5858 : {
5859 2 : poDstLayer->CreateGeomField(
5860 2 : poSrcDefn->GetGeomFieldDefn(iField));
5861 : }
5862 : else
5863 : {
5864 : OGRGeomFieldDefn *pDstGeomFieldDefn =
5865 0 : poSrcDefn->GetGeomFieldDefn(iField);
5866 0 : pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
5867 0 : poDstLayer->CreateGeomField(pDstGeomFieldDefn);
5868 : }
5869 : }
5870 : }
5871 :
5872 : /* -------------------------------------------------------------------- */
5873 : /* Check if the destination layer supports transactions and set a */
5874 : /* default number of features in a single transaction. */
5875 : /* -------------------------------------------------------------------- */
5876 : const int nGroupTransactions =
5877 126 : poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
5878 :
5879 : /* -------------------------------------------------------------------- */
5880 : /* Transfer features. */
5881 : /* -------------------------------------------------------------------- */
5882 126 : poSrcLayer->ResetReading();
5883 :
5884 126 : if (nGroupTransactions <= 0)
5885 : {
5886 : while (true)
5887 : {
5888 : auto poFeature =
5889 401 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
5890 :
5891 401 : if (poFeature == nullptr)
5892 123 : break;
5893 :
5894 278 : CPLErrorReset();
5895 : auto poDstFeature =
5896 278 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
5897 :
5898 278 : if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=
5899 : OGRERR_NONE)
5900 : {
5901 0 : CPLError(CE_Failure, CPLE_AppDefined,
5902 : "Unable to translate feature " CPL_FRMT_GIB
5903 : " from layer %s.",
5904 0 : poFeature->GetFID(), poSrcDefn->GetName());
5905 0 : return poDstLayer;
5906 : }
5907 :
5908 278 : if (nullptr != poCT)
5909 : {
5910 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5911 : {
5912 0 : OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
5913 0 : if (nullptr == pGeom)
5914 0 : continue;
5915 :
5916 0 : const OGRErr eErr = pGeom->transform(poCT.get());
5917 0 : if (eErr == OGRERR_NONE)
5918 0 : continue;
5919 :
5920 0 : CPLError(CE_Failure, CPLE_AppDefined,
5921 : "Unable to transform geometry " CPL_FRMT_GIB
5922 : " from layer %s.",
5923 0 : poFeature->GetFID(), poSrcDefn->GetName());
5924 0 : return poDstLayer;
5925 : }
5926 : }
5927 :
5928 278 : poDstFeature->SetFID(poFeature->GetFID());
5929 :
5930 278 : CPLErrorReset();
5931 278 : if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)
5932 : {
5933 0 : return poDstLayer;
5934 : }
5935 278 : }
5936 : }
5937 : else
5938 : {
5939 3 : std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;
5940 : try
5941 : {
5942 3 : apoDstFeatures.resize(nGroupTransactions);
5943 : }
5944 0 : catch (const std::exception &e)
5945 : {
5946 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
5947 0 : return poDstLayer;
5948 : }
5949 3 : bool bStopTransfer = false;
5950 6 : while (!bStopTransfer)
5951 : {
5952 : /* --------------------------------------------------------------------
5953 : */
5954 : /* Fill the array with features. */
5955 : /* --------------------------------------------------------------------
5956 : */
5957 : // Number of features in the temporary array.
5958 3 : int nFeatCount = 0; // Used after for.
5959 33 : for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)
5960 : {
5961 : auto poFeature =
5962 33 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
5963 :
5964 33 : if (poFeature == nullptr)
5965 : {
5966 3 : bStopTransfer = true;
5967 3 : break;
5968 : }
5969 :
5970 30 : CPLErrorReset();
5971 30 : apoDstFeatures[nFeatCount] =
5972 60 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
5973 :
5974 60 : if (apoDstFeatures[nFeatCount]->SetFrom(
5975 60 : poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)
5976 : {
5977 0 : CPLError(CE_Failure, CPLE_AppDefined,
5978 : "Unable to translate feature " CPL_FRMT_GIB
5979 : " from layer %s.",
5980 0 : poFeature->GetFID(), poSrcDefn->GetName());
5981 0 : bStopTransfer = true;
5982 0 : poFeature.reset();
5983 0 : break;
5984 : }
5985 :
5986 30 : if (nullptr != poCT)
5987 : {
5988 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5989 : {
5990 : OGRGeometry *pGeom =
5991 0 : apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);
5992 0 : if (nullptr == pGeom)
5993 0 : continue;
5994 :
5995 0 : const OGRErr eErr = pGeom->transform(poCT.get());
5996 0 : if (eErr == OGRERR_NONE)
5997 0 : continue;
5998 :
5999 0 : CPLError(CE_Failure, CPLE_AppDefined,
6000 : "Unable to transform geometry " CPL_FRMT_GIB
6001 : " from layer %s.",
6002 0 : poFeature->GetFID(), poSrcDefn->GetName());
6003 0 : bStopTransfer = true;
6004 0 : poFeature.reset();
6005 0 : break;
6006 : }
6007 : }
6008 :
6009 30 : if (poFeature)
6010 : {
6011 30 : apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());
6012 : }
6013 : }
6014 :
6015 3 : CPLErrorReset();
6016 3 : bool bStopTransaction = false;
6017 6 : while (!bStopTransaction)
6018 : {
6019 3 : bStopTransaction = true;
6020 3 : if (poDstLayer->StartTransaction() != OGRERR_NONE)
6021 0 : break;
6022 33 : for (int i = 0; i < nFeatCount; ++i)
6023 : {
6024 30 : if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=
6025 : OGRERR_NONE)
6026 : {
6027 0 : bStopTransfer = true;
6028 0 : bStopTransaction = false;
6029 0 : break;
6030 : }
6031 30 : apoDstFeatures[i].reset();
6032 : }
6033 3 : if (bStopTransaction)
6034 : {
6035 3 : if (poDstLayer->CommitTransaction() != OGRERR_NONE)
6036 0 : break;
6037 : }
6038 : else
6039 : {
6040 0 : poDstLayer->RollbackTransaction();
6041 : }
6042 : }
6043 : }
6044 : }
6045 :
6046 126 : return poDstLayer;
6047 : }
6048 :
6049 : /************************************************************************/
6050 : /* DeleteLayer() */
6051 : /************************************************************************/
6052 :
6053 : /**
6054 : \fn GDALDataset::DeleteLayer(int)
6055 : \brief Delete the indicated layer from the datasource.
6056 :
6057 : If this method is supported
6058 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
6059 :
6060 : This method is the same as the C function GDALDatasetDeleteLayer() and the
6061 : deprecated OGR_DS_DeleteLayer().
6062 :
6063 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6064 :
6065 : @param iLayer the index of the layer to delete.
6066 :
6067 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
6068 : layers is not supported for this datasource.
6069 :
6070 : */
6071 :
6072 405 : OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)
6073 :
6074 : {
6075 405 : CPLError(CE_Failure, CPLE_NotSupported,
6076 : "DeleteLayer() not supported by this dataset.");
6077 :
6078 405 : return OGRERR_UNSUPPORTED_OPERATION;
6079 : }
6080 :
6081 : /************************************************************************/
6082 : /* GetLayerByName() */
6083 : /************************************************************************/
6084 :
6085 : /**
6086 : \brief Fetch a layer by name.
6087 :
6088 : The returned layer remains owned by the
6089 : GDALDataset and should not be deleted by the application.
6090 :
6091 : This method is the same as the C function GDALDatasetGetLayerByName() and the
6092 : deprecated OGR_DS_GetLayerByName().
6093 :
6094 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6095 :
6096 : @param pszName the layer name of the layer to fetch.
6097 :
6098 : @return the layer, or NULL if Layer is not found or an error occurs.
6099 : */
6100 :
6101 29722 : OGRLayer *GDALDataset::GetLayerByName(const char *pszName)
6102 :
6103 : {
6104 59444 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
6105 :
6106 29722 : if (!pszName)
6107 0 : return nullptr;
6108 :
6109 : // First a case sensitive check.
6110 935203 : for (int i = 0; i < GetLayerCount(); ++i)
6111 : {
6112 916786 : OGRLayer *poLayer = GetLayer(i);
6113 :
6114 916786 : if (strcmp(pszName, poLayer->GetName()) == 0)
6115 11305 : return poLayer;
6116 : }
6117 :
6118 : // Then case insensitive.
6119 895985 : for (int i = 0; i < GetLayerCount(); ++i)
6120 : {
6121 877752 : OGRLayer *poLayer = GetLayer(i);
6122 :
6123 877752 : if (EQUAL(pszName, poLayer->GetName()))
6124 184 : return poLayer;
6125 : }
6126 :
6127 18233 : return nullptr;
6128 : }
6129 :
6130 : //! @cond Doxygen_Suppress
6131 : /************************************************************************/
6132 : /* ProcessSQLCreateIndex() */
6133 : /* */
6134 : /* The correct syntax for creating an index in our dialect of */
6135 : /* SQL is: */
6136 : /* */
6137 : /* CREATE INDEX ON <layername> USING <columnname> */
6138 : /************************************************************************/
6139 :
6140 28 : OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)
6141 :
6142 : {
6143 28 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6144 :
6145 : /* -------------------------------------------------------------------- */
6146 : /* Do some general syntax checking. */
6147 : /* -------------------------------------------------------------------- */
6148 56 : if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||
6149 84 : !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||
6150 28 : !EQUAL(papszTokens[4], "USING"))
6151 : {
6152 0 : CSLDestroy(papszTokens);
6153 0 : CPLError(CE_Failure, CPLE_AppDefined,
6154 : "Syntax error in CREATE INDEX command.\n"
6155 : "Was '%s'\n"
6156 : "Should be of form 'CREATE INDEX ON <table> USING <field>'",
6157 : pszSQLCommand);
6158 0 : return OGRERR_FAILURE;
6159 : }
6160 :
6161 : /* -------------------------------------------------------------------- */
6162 : /* Find the named layer. */
6163 : /* -------------------------------------------------------------------- */
6164 28 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6165 28 : if (poLayer == nullptr)
6166 : {
6167 0 : CPLError(CE_Failure, CPLE_AppDefined,
6168 : "CREATE INDEX ON failed, no such layer as `%s'.",
6169 0 : papszTokens[3]);
6170 0 : CSLDestroy(papszTokens);
6171 0 : return OGRERR_FAILURE;
6172 : }
6173 :
6174 : /* -------------------------------------------------------------------- */
6175 : /* Does this layer even support attribute indexes? */
6176 : /* -------------------------------------------------------------------- */
6177 28 : if (poLayer->GetIndex() == nullptr)
6178 : {
6179 0 : CPLError(CE_Failure, CPLE_AppDefined,
6180 : "CREATE INDEX ON not supported by this driver.");
6181 0 : CSLDestroy(papszTokens);
6182 0 : return OGRERR_FAILURE;
6183 : }
6184 :
6185 : /* -------------------------------------------------------------------- */
6186 : /* Find the named field. */
6187 : /* -------------------------------------------------------------------- */
6188 28 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6189 :
6190 28 : CSLDestroy(papszTokens);
6191 :
6192 28 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6193 : {
6194 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6195 : pszSQLCommand);
6196 0 : return OGRERR_FAILURE;
6197 : }
6198 :
6199 : /* -------------------------------------------------------------------- */
6200 : /* Attempt to create the index. */
6201 : /* -------------------------------------------------------------------- */
6202 28 : OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
6203 28 : if (eErr == OGRERR_NONE)
6204 : {
6205 28 : eErr = poLayer->GetIndex()->IndexAllFeatures(i);
6206 : }
6207 : else
6208 : {
6209 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
6210 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
6211 : }
6212 :
6213 28 : return eErr;
6214 : }
6215 :
6216 : /************************************************************************/
6217 : /* ProcessSQLDropIndex() */
6218 : /* */
6219 : /* The correct syntax for dropping one or more indexes in */
6220 : /* the OGR SQL dialect is: */
6221 : /* */
6222 : /* DROP INDEX ON <layername> [USING <columnname>] */
6223 : /************************************************************************/
6224 :
6225 10 : OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)
6226 :
6227 : {
6228 10 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6229 :
6230 : /* -------------------------------------------------------------------- */
6231 : /* Do some general syntax checking. */
6232 : /* -------------------------------------------------------------------- */
6233 20 : if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||
6234 10 : !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||
6235 30 : !EQUAL(papszTokens[2], "ON") ||
6236 10 : (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))
6237 : {
6238 0 : CSLDestroy(papszTokens);
6239 0 : CPLError(CE_Failure, CPLE_AppDefined,
6240 : "Syntax error in DROP INDEX command.\n"
6241 : "Was '%s'\n"
6242 : "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
6243 : pszSQLCommand);
6244 0 : return OGRERR_FAILURE;
6245 : }
6246 :
6247 : /* -------------------------------------------------------------------- */
6248 : /* Find the named layer. */
6249 : /* -------------------------------------------------------------------- */
6250 10 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6251 10 : if (poLayer == nullptr)
6252 : {
6253 0 : CPLError(CE_Failure, CPLE_AppDefined,
6254 : "DROP INDEX ON failed, no such layer as `%s'.",
6255 0 : papszTokens[3]);
6256 0 : CSLDestroy(papszTokens);
6257 0 : return OGRERR_FAILURE;
6258 : }
6259 :
6260 : /* -------------------------------------------------------------------- */
6261 : /* Does this layer even support attribute indexes? */
6262 : /* -------------------------------------------------------------------- */
6263 10 : if (poLayer->GetIndex() == nullptr)
6264 : {
6265 0 : CPLError(CE_Failure, CPLE_AppDefined,
6266 : "Indexes not supported by this driver.");
6267 0 : CSLDestroy(papszTokens);
6268 0 : return OGRERR_FAILURE;
6269 : }
6270 :
6271 : /* -------------------------------------------------------------------- */
6272 : /* If we were not given a field name, drop all indexes. */
6273 : /* -------------------------------------------------------------------- */
6274 10 : if (CSLCount(papszTokens) == 4)
6275 : {
6276 0 : for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)
6277 : {
6278 : OGRAttrIndex *poAttrIndex;
6279 :
6280 0 : poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
6281 0 : if (poAttrIndex != nullptr)
6282 : {
6283 0 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6284 0 : if (eErr != OGRERR_NONE)
6285 : {
6286 0 : CSLDestroy(papszTokens);
6287 0 : return eErr;
6288 : }
6289 : }
6290 : }
6291 :
6292 0 : CSLDestroy(papszTokens);
6293 0 : return OGRERR_NONE;
6294 : }
6295 :
6296 : /* -------------------------------------------------------------------- */
6297 : /* Find the named field. */
6298 : /* -------------------------------------------------------------------- */
6299 10 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6300 10 : CSLDestroy(papszTokens);
6301 :
6302 10 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6303 : {
6304 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6305 : pszSQLCommand);
6306 0 : return OGRERR_FAILURE;
6307 : }
6308 :
6309 : /* -------------------------------------------------------------------- */
6310 : /* Attempt to drop the index. */
6311 : /* -------------------------------------------------------------------- */
6312 10 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6313 :
6314 10 : return eErr;
6315 : }
6316 :
6317 : /************************************************************************/
6318 : /* ProcessSQLDropTable() */
6319 : /* */
6320 : /* The correct syntax for dropping a table (layer) in the OGR SQL */
6321 : /* dialect is: */
6322 : /* */
6323 : /* DROP TABLE <layername> */
6324 : /************************************************************************/
6325 :
6326 500 : OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)
6327 :
6328 : {
6329 500 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6330 :
6331 : /* -------------------------------------------------------------------- */
6332 : /* Do some general syntax checking. */
6333 : /* -------------------------------------------------------------------- */
6334 1000 : if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||
6335 500 : !EQUAL(papszTokens[1], "TABLE"))
6336 : {
6337 0 : CSLDestroy(papszTokens);
6338 0 : CPLError(CE_Failure, CPLE_AppDefined,
6339 : "Syntax error in DROP TABLE command.\n"
6340 : "Was '%s'\n"
6341 : "Should be of form 'DROP TABLE <table>'",
6342 : pszSQLCommand);
6343 0 : return OGRERR_FAILURE;
6344 : }
6345 :
6346 : /* -------------------------------------------------------------------- */
6347 : /* Find the named layer. */
6348 : /* -------------------------------------------------------------------- */
6349 500 : OGRLayer *poLayer = nullptr;
6350 :
6351 500 : int i = 0; // Used after for.
6352 40199 : for (; i < GetLayerCount(); ++i)
6353 : {
6354 40199 : poLayer = GetLayer(i);
6355 :
6356 40199 : if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))
6357 500 : break;
6358 39699 : poLayer = nullptr;
6359 : }
6360 :
6361 500 : if (poLayer == nullptr)
6362 : {
6363 0 : CPLError(CE_Failure, CPLE_AppDefined,
6364 0 : "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
6365 0 : CSLDestroy(papszTokens);
6366 0 : return OGRERR_FAILURE;
6367 : }
6368 :
6369 500 : CSLDestroy(papszTokens);
6370 :
6371 : /* -------------------------------------------------------------------- */
6372 : /* Delete it. */
6373 : /* -------------------------------------------------------------------- */
6374 :
6375 500 : return DeleteLayer(i);
6376 : }
6377 :
6378 : //! @endcond
6379 :
6380 : /************************************************************************/
6381 : /* GDALDatasetParseSQLType() */
6382 : /************************************************************************/
6383 :
6384 : /* All arguments will be altered */
6385 6 : static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
6386 : int &nPrecision)
6387 : {
6388 6 : char *pszParenthesis = strchr(pszType, '(');
6389 6 : if (pszParenthesis)
6390 : {
6391 4 : nWidth = atoi(pszParenthesis + 1);
6392 4 : *pszParenthesis = '\0';
6393 4 : char *pszComma = strchr(pszParenthesis + 1, ',');
6394 4 : if (pszComma)
6395 2 : nPrecision = atoi(pszComma + 1);
6396 : }
6397 :
6398 6 : OGRFieldType eType = OFTString;
6399 6 : if (EQUAL(pszType, "INTEGER"))
6400 0 : eType = OFTInteger;
6401 6 : else if (EQUAL(pszType, "INTEGER[]"))
6402 0 : eType = OFTIntegerList;
6403 6 : else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||
6404 4 : EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
6405 4 : EQUAL(pszType, "REAL") /* unofficial alias */)
6406 2 : eType = OFTReal;
6407 4 : else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||
6408 4 : EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
6409 4 : EQUAL(pszType, "REAL[]") /* unofficial alias */)
6410 0 : eType = OFTRealList;
6411 4 : else if (EQUAL(pszType, "CHARACTER") ||
6412 0 : EQUAL(pszType, "TEXT") /* unofficial alias */ ||
6413 0 : EQUAL(pszType, "STRING") /* unofficial alias */ ||
6414 0 : EQUAL(pszType, "VARCHAR") /* unofficial alias */)
6415 4 : eType = OFTString;
6416 0 : else if (EQUAL(pszType, "TEXT[]") ||
6417 0 : EQUAL(pszType, "STRING[]") /* unofficial alias */ ||
6418 0 : EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
6419 0 : eType = OFTStringList;
6420 0 : else if (EQUAL(pszType, "DATE"))
6421 0 : eType = OFTDate;
6422 0 : else if (EQUAL(pszType, "TIME"))
6423 0 : eType = OFTTime;
6424 0 : else if (EQUAL(pszType, "TIMESTAMP") ||
6425 0 : EQUAL(pszType, "DATETIME") /* unofficial alias */)
6426 0 : eType = OFTDateTime;
6427 : else
6428 0 : CPLError(CE_Warning, CPLE_NotSupported,
6429 : "Unsupported column type '%s'. Defaulting to VARCHAR",
6430 : pszType);
6431 :
6432 6 : return eType;
6433 : }
6434 :
6435 : /************************************************************************/
6436 : /* ProcessSQLAlterTableAddColumn() */
6437 : /* */
6438 : /* The correct syntax for adding a column in the OGR SQL */
6439 : /* dialect is: */
6440 : /* */
6441 : /* ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
6442 : /************************************************************************/
6443 :
6444 : //! @cond Doxygen_Suppress
6445 2 : OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)
6446 :
6447 : {
6448 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6449 :
6450 : /* -------------------------------------------------------------------- */
6451 : /* Do some general syntax checking. */
6452 : /* -------------------------------------------------------------------- */
6453 2 : const char *pszLayerName = nullptr;
6454 2 : const char *pszColumnName = nullptr;
6455 2 : int iTypeIndex = 0;
6456 2 : const int nTokens = CSLCount(papszTokens);
6457 :
6458 2 : if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6459 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&
6460 2 : EQUAL(papszTokens[4], "COLUMN"))
6461 : {
6462 1 : pszLayerName = papszTokens[2];
6463 1 : pszColumnName = papszTokens[5];
6464 1 : iTypeIndex = 6;
6465 : }
6466 1 : else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&
6467 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))
6468 : {
6469 1 : pszLayerName = papszTokens[2];
6470 1 : pszColumnName = papszTokens[4];
6471 1 : iTypeIndex = 5;
6472 : }
6473 : else
6474 : {
6475 0 : CSLDestroy(papszTokens);
6476 0 : CPLError(CE_Failure, CPLE_AppDefined,
6477 : "Syntax error in ALTER TABLE ADD COLUMN command.\n"
6478 : "Was '%s'\n"
6479 : "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
6480 : "<columnname> <columntype>'",
6481 : pszSQLCommand);
6482 0 : return OGRERR_FAILURE;
6483 : }
6484 :
6485 : /* -------------------------------------------------------------------- */
6486 : /* Merge type components into a single string if there were split */
6487 : /* with spaces */
6488 : /* -------------------------------------------------------------------- */
6489 4 : CPLString osType;
6490 6 : for (int i = iTypeIndex; i < nTokens; ++i)
6491 : {
6492 4 : osType += papszTokens[i];
6493 4 : CPLFree(papszTokens[i]);
6494 : }
6495 2 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6496 2 : papszTokens[iTypeIndex + 1] = nullptr;
6497 :
6498 : /* -------------------------------------------------------------------- */
6499 : /* Find the named layer. */
6500 : /* -------------------------------------------------------------------- */
6501 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6502 2 : if (poLayer == nullptr)
6503 : {
6504 0 : CPLError(CE_Failure, CPLE_AppDefined,
6505 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6506 : pszLayerName);
6507 0 : CSLDestroy(papszTokens);
6508 0 : return OGRERR_FAILURE;
6509 : }
6510 :
6511 : /* -------------------------------------------------------------------- */
6512 : /* Add column. */
6513 : /* -------------------------------------------------------------------- */
6514 :
6515 2 : int nWidth = 0;
6516 2 : int nPrecision = 0;
6517 2 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6518 4 : OGRFieldDefn oFieldDefn(pszColumnName, eType);
6519 2 : oFieldDefn.SetWidth(nWidth);
6520 2 : oFieldDefn.SetPrecision(nPrecision);
6521 :
6522 2 : CSLDestroy(papszTokens);
6523 :
6524 2 : return poLayer->CreateField(&oFieldDefn);
6525 : }
6526 :
6527 : /************************************************************************/
6528 : /* ProcessSQLAlterTableDropColumn() */
6529 : /* */
6530 : /* The correct syntax for dropping a column in the OGR SQL */
6531 : /* dialect is: */
6532 : /* */
6533 : /* ALTER TABLE <layername> DROP [COLUMN] <columnname> */
6534 : /************************************************************************/
6535 :
6536 2 : OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)
6537 :
6538 : {
6539 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6540 :
6541 : /* -------------------------------------------------------------------- */
6542 : /* Do some general syntax checking. */
6543 : /* -------------------------------------------------------------------- */
6544 2 : const char *pszLayerName = nullptr;
6545 2 : const char *pszColumnName = nullptr;
6546 3 : if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&
6547 4 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&
6548 1 : EQUAL(papszTokens[4], "COLUMN"))
6549 : {
6550 1 : pszLayerName = papszTokens[2];
6551 1 : pszColumnName = papszTokens[5];
6552 : }
6553 2 : else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&
6554 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))
6555 : {
6556 1 : pszLayerName = papszTokens[2];
6557 1 : pszColumnName = papszTokens[4];
6558 : }
6559 : else
6560 : {
6561 0 : CSLDestroy(papszTokens);
6562 0 : CPLError(CE_Failure, CPLE_AppDefined,
6563 : "Syntax error in ALTER TABLE DROP COLUMN command.\n"
6564 : "Was '%s'\n"
6565 : "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
6566 : "<columnname>'",
6567 : pszSQLCommand);
6568 0 : return OGRERR_FAILURE;
6569 : }
6570 :
6571 : /* -------------------------------------------------------------------- */
6572 : /* Find the named layer. */
6573 : /* -------------------------------------------------------------------- */
6574 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6575 2 : if (poLayer == nullptr)
6576 : {
6577 0 : CPLError(CE_Failure, CPLE_AppDefined,
6578 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6579 : pszLayerName);
6580 0 : CSLDestroy(papszTokens);
6581 0 : return OGRERR_FAILURE;
6582 : }
6583 :
6584 : /* -------------------------------------------------------------------- */
6585 : /* Find the field. */
6586 : /* -------------------------------------------------------------------- */
6587 :
6588 2 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6589 2 : if (nFieldIndex < 0)
6590 : {
6591 0 : CPLError(CE_Failure, CPLE_AppDefined,
6592 : "%s failed, no such field as `%s'.", pszSQLCommand,
6593 : pszColumnName);
6594 0 : CSLDestroy(papszTokens);
6595 0 : return OGRERR_FAILURE;
6596 : }
6597 :
6598 : /* -------------------------------------------------------------------- */
6599 : /* Remove it. */
6600 : /* -------------------------------------------------------------------- */
6601 :
6602 2 : CSLDestroy(papszTokens);
6603 :
6604 2 : return poLayer->DeleteField(nFieldIndex);
6605 : }
6606 :
6607 : /************************************************************************/
6608 : /* ProcessSQLAlterTableRenameColumn() */
6609 : /* */
6610 : /* The correct syntax for renaming a column in the OGR SQL */
6611 : /* dialect is: */
6612 : /* */
6613 : /* ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
6614 : /************************************************************************/
6615 :
6616 2 : OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)
6617 :
6618 : {
6619 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6620 :
6621 : /* -------------------------------------------------------------------- */
6622 : /* Do some general syntax checking. */
6623 : /* -------------------------------------------------------------------- */
6624 2 : const char *pszLayerName = nullptr;
6625 2 : const char *pszOldColName = nullptr;
6626 2 : const char *pszNewColName = nullptr;
6627 3 : if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&
6628 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&
6629 3 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))
6630 : {
6631 1 : pszLayerName = papszTokens[2];
6632 1 : pszOldColName = papszTokens[5];
6633 1 : pszNewColName = papszTokens[7];
6634 : }
6635 2 : else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&
6636 1 : EQUAL(papszTokens[1], "TABLE") &&
6637 2 : EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))
6638 : {
6639 1 : pszLayerName = papszTokens[2];
6640 1 : pszOldColName = papszTokens[4];
6641 1 : pszNewColName = papszTokens[6];
6642 : }
6643 : else
6644 : {
6645 0 : CSLDestroy(papszTokens);
6646 0 : CPLError(CE_Failure, CPLE_AppDefined,
6647 : "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
6648 : "Was '%s'\n"
6649 : "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
6650 : "<columnname> TO <newname>'",
6651 : pszSQLCommand);
6652 0 : return OGRERR_FAILURE;
6653 : }
6654 :
6655 : /* -------------------------------------------------------------------- */
6656 : /* Find the named layer. */
6657 : /* -------------------------------------------------------------------- */
6658 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6659 2 : if (poLayer == nullptr)
6660 : {
6661 0 : CPLError(CE_Failure, CPLE_AppDefined,
6662 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6663 : pszLayerName);
6664 0 : CSLDestroy(papszTokens);
6665 0 : return OGRERR_FAILURE;
6666 : }
6667 :
6668 : /* -------------------------------------------------------------------- */
6669 : /* Find the field. */
6670 : /* -------------------------------------------------------------------- */
6671 :
6672 : const int nFieldIndex =
6673 2 : poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
6674 2 : if (nFieldIndex < 0)
6675 : {
6676 0 : CPLError(CE_Failure, CPLE_AppDefined,
6677 : "%s failed, no such field as `%s'.", pszSQLCommand,
6678 : pszOldColName);
6679 0 : CSLDestroy(papszTokens);
6680 0 : return OGRERR_FAILURE;
6681 : }
6682 :
6683 : /* -------------------------------------------------------------------- */
6684 : /* Rename column. */
6685 : /* -------------------------------------------------------------------- */
6686 : OGRFieldDefn *poOldFieldDefn =
6687 2 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6688 4 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6689 2 : oNewFieldDefn.SetName(pszNewColName);
6690 :
6691 2 : CSLDestroy(papszTokens);
6692 :
6693 2 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6694 2 : ALTER_NAME_FLAG);
6695 : }
6696 :
6697 : /************************************************************************/
6698 : /* ProcessSQLAlterTableAlterColumn() */
6699 : /* */
6700 : /* The correct syntax for altering the type of a column in the */
6701 : /* OGR SQL dialect is: */
6702 : /* */
6703 : /* ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
6704 : /************************************************************************/
6705 :
6706 4 : OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)
6707 :
6708 : {
6709 4 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6710 :
6711 : /* -------------------------------------------------------------------- */
6712 : /* Do some general syntax checking. */
6713 : /* -------------------------------------------------------------------- */
6714 4 : const char *pszLayerName = nullptr;
6715 4 : const char *pszColumnName = nullptr;
6716 4 : int iTypeIndex = 0;
6717 4 : const int nTokens = CSLCount(papszTokens);
6718 :
6719 4 : if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&
6720 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6721 2 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))
6722 : {
6723 2 : pszLayerName = papszTokens[2];
6724 2 : pszColumnName = papszTokens[5];
6725 2 : iTypeIndex = 7;
6726 : }
6727 2 : else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6728 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6729 2 : EQUAL(papszTokens[5], "TYPE"))
6730 : {
6731 2 : pszLayerName = papszTokens[2];
6732 2 : pszColumnName = papszTokens[4];
6733 2 : iTypeIndex = 6;
6734 : }
6735 : else
6736 : {
6737 0 : CSLDestroy(papszTokens);
6738 0 : CPLError(CE_Failure, CPLE_AppDefined,
6739 : "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
6740 : "Was '%s'\n"
6741 : "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
6742 : "<columnname> TYPE <columntype>'",
6743 : pszSQLCommand);
6744 0 : return OGRERR_FAILURE;
6745 : }
6746 :
6747 : /* -------------------------------------------------------------------- */
6748 : /* Merge type components into a single string if there were split */
6749 : /* with spaces */
6750 : /* -------------------------------------------------------------------- */
6751 8 : CPLString osType;
6752 8 : for (int i = iTypeIndex; i < nTokens; ++i)
6753 : {
6754 4 : osType += papszTokens[i];
6755 4 : CPLFree(papszTokens[i]);
6756 : }
6757 4 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6758 4 : papszTokens[iTypeIndex + 1] = nullptr;
6759 :
6760 : /* -------------------------------------------------------------------- */
6761 : /* Find the named layer. */
6762 : /* -------------------------------------------------------------------- */
6763 4 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6764 4 : if (poLayer == nullptr)
6765 : {
6766 0 : CPLError(CE_Failure, CPLE_AppDefined,
6767 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6768 : pszLayerName);
6769 0 : CSLDestroy(papszTokens);
6770 0 : return OGRERR_FAILURE;
6771 : }
6772 :
6773 : /* -------------------------------------------------------------------- */
6774 : /* Find the field. */
6775 : /* -------------------------------------------------------------------- */
6776 :
6777 : const int nFieldIndex =
6778 4 : poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6779 4 : if (nFieldIndex < 0)
6780 : {
6781 0 : CPLError(CE_Failure, CPLE_AppDefined,
6782 : "%s failed, no such field as `%s'.", pszSQLCommand,
6783 : pszColumnName);
6784 0 : CSLDestroy(papszTokens);
6785 0 : return OGRERR_FAILURE;
6786 : }
6787 :
6788 : /* -------------------------------------------------------------------- */
6789 : /* Alter column. */
6790 : /* -------------------------------------------------------------------- */
6791 :
6792 : OGRFieldDefn *poOldFieldDefn =
6793 4 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6794 8 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6795 :
6796 4 : int nWidth = 0;
6797 4 : int nPrecision = 0;
6798 4 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6799 4 : oNewFieldDefn.SetType(eType);
6800 4 : oNewFieldDefn.SetWidth(nWidth);
6801 4 : oNewFieldDefn.SetPrecision(nPrecision);
6802 :
6803 4 : int l_nFlags = 0;
6804 4 : if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
6805 2 : l_nFlags |= ALTER_TYPE_FLAG;
6806 4 : if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
6807 0 : poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
6808 4 : l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
6809 :
6810 4 : CSLDestroy(papszTokens);
6811 :
6812 4 : if (l_nFlags == 0)
6813 0 : return OGRERR_NONE;
6814 :
6815 4 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
6816 : }
6817 :
6818 : //! @endcond
6819 :
6820 : /************************************************************************/
6821 : /* ExecuteSQL() */
6822 : /************************************************************************/
6823 :
6824 : /**
6825 : \brief Execute an SQL statement against the data store.
6826 :
6827 : The result of an SQL query is either NULL for statements that are in error,
6828 : or that have no results set, or an OGRLayer pointer representing a results
6829 : set from the query. Note that this OGRLayer is in addition to the layers
6830 : in the data store and must be destroyed with
6831 : ReleaseResultSet() before the dataset is closed
6832 : (destroyed).
6833 :
6834 : This method is the same as the C function GDALDatasetExecuteSQL() and the
6835 : deprecated OGR_DS_ExecuteSQL().
6836 :
6837 : For more information on the SQL dialect supported internally by OGR
6838 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
6839 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
6840 : to the underlying RDBMS.
6841 :
6842 : Starting with OGR 1.10, the <a
6843 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
6844 : also be used.
6845 :
6846 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6847 :
6848 : @param pszStatement the SQL statement to execute.
6849 : @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
6850 : @param pszDialect allows control of the statement dialect. If set to NULL, the
6851 : OGR SQL engine will be used, except for RDBMS drivers that will use their
6852 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
6853 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
6854 :
6855 : @return an OGRLayer containing the results of the query. Deallocate with
6856 : ReleaseResultSet().
6857 :
6858 : */
6859 :
6860 3483 : OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,
6861 : OGRGeometry *poSpatialFilter,
6862 : const char *pszDialect)
6863 :
6864 : {
6865 3483 : return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
6866 : }
6867 :
6868 : //! @cond Doxygen_Suppress
6869 : OGRLayer *
6870 3491 : GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
6871 : const char *pszDialect,
6872 : swq_select_parse_options *poSelectParseOptions)
6873 :
6874 : {
6875 3491 : if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))
6876 : {
6877 : #ifdef SQLITE_ENABLED
6878 644 : return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
6879 644 : pszDialect);
6880 : #else
6881 : CPLError(CE_Failure, CPLE_NotSupported,
6882 : "The SQLite driver needs to be compiled to support the "
6883 : "SQLite SQL dialect");
6884 : return nullptr;
6885 : #endif
6886 : }
6887 :
6888 2847 : if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
6889 11 : !EQUAL(pszDialect, "OGRSQL"))
6890 : {
6891 2 : std::string osDialectList = "'OGRSQL'";
6892 : #ifdef SQLITE_ENABLED
6893 1 : osDialectList += ", 'SQLITE'";
6894 : #endif
6895 : const char *pszDialects =
6896 1 : GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);
6897 1 : if (pszDialects)
6898 : {
6899 : const CPLStringList aosTokens(
6900 0 : CSLTokenizeString2(pszDialects, " ", 0));
6901 0 : for (int i = 0; i < aosTokens.size(); ++i)
6902 : {
6903 0 : if (!EQUAL(aosTokens[i], "OGRSQL") &&
6904 0 : !EQUAL(aosTokens[i], "SQLITE"))
6905 : {
6906 0 : osDialectList += ", '";
6907 0 : osDialectList += aosTokens[i];
6908 0 : osDialectList += "'";
6909 : }
6910 : }
6911 : }
6912 1 : CPLError(CE_Warning, CPLE_NotSupported,
6913 : "Dialect '%s' is unsupported. Only supported dialects are %s. "
6914 : "Defaulting to OGRSQL",
6915 : pszDialect, osDialectList.c_str());
6916 : }
6917 :
6918 : /* -------------------------------------------------------------------- */
6919 : /* Handle CREATE INDEX statements specially. */
6920 : /* -------------------------------------------------------------------- */
6921 2847 : if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))
6922 : {
6923 28 : ProcessSQLCreateIndex(pszStatement);
6924 28 : return nullptr;
6925 : }
6926 :
6927 : /* -------------------------------------------------------------------- */
6928 : /* Handle DROP INDEX statements specially. */
6929 : /* -------------------------------------------------------------------- */
6930 2819 : if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))
6931 : {
6932 10 : ProcessSQLDropIndex(pszStatement);
6933 10 : return nullptr;
6934 : }
6935 :
6936 : /* -------------------------------------------------------------------- */
6937 : /* Handle DROP TABLE statements specially. */
6938 : /* -------------------------------------------------------------------- */
6939 2809 : if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))
6940 : {
6941 500 : ProcessSQLDropTable(pszStatement);
6942 500 : return nullptr;
6943 : }
6944 :
6945 : /* -------------------------------------------------------------------- */
6946 : /* Handle ALTER TABLE statements specially. */
6947 : /* -------------------------------------------------------------------- */
6948 2309 : if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))
6949 : {
6950 11 : char **papszTokens = CSLTokenizeString(pszStatement);
6951 11 : const int nTokens = CSLCount(papszTokens);
6952 11 : if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))
6953 : {
6954 2 : ProcessSQLAlterTableAddColumn(pszStatement);
6955 2 : CSLDestroy(papszTokens);
6956 2 : return nullptr;
6957 : }
6958 9 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))
6959 : {
6960 2 : ProcessSQLAlterTableDropColumn(pszStatement);
6961 2 : CSLDestroy(papszTokens);
6962 2 : return nullptr;
6963 : }
6964 7 : else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&
6965 1 : EQUAL(papszTokens[4], "TO"))
6966 : {
6967 1 : const char *pszSrcTableName = papszTokens[2];
6968 1 : const char *pszDstTableName = papszTokens[5];
6969 1 : auto poSrcLayer = GetLayerByName(pszSrcTableName);
6970 1 : if (poSrcLayer)
6971 : {
6972 1 : CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));
6973 : }
6974 : else
6975 : {
6976 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");
6977 : }
6978 1 : CSLDestroy(papszTokens);
6979 1 : return nullptr;
6980 : }
6981 6 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))
6982 : {
6983 2 : ProcessSQLAlterTableRenameColumn(pszStatement);
6984 2 : CSLDestroy(papszTokens);
6985 2 : return nullptr;
6986 : }
6987 4 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))
6988 : {
6989 4 : ProcessSQLAlterTableAlterColumn(pszStatement);
6990 4 : CSLDestroy(papszTokens);
6991 4 : return nullptr;
6992 : }
6993 : else
6994 : {
6995 0 : CPLError(CE_Failure, CPLE_AppDefined,
6996 : "Unsupported ALTER TABLE command : %s", pszStatement);
6997 0 : CSLDestroy(papszTokens);
6998 0 : return nullptr;
6999 : }
7000 : }
7001 :
7002 : /* -------------------------------------------------------------------- */
7003 : /* Preparse the SQL statement. */
7004 : /* -------------------------------------------------------------------- */
7005 2298 : swq_select *psSelectInfo = new swq_select();
7006 2298 : swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
7007 2298 : if (poSelectParseOptions != nullptr)
7008 8 : poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
7009 2298 : if (psSelectInfo->preparse(pszStatement,
7010 2298 : poCustomFuncRegistrar != nullptr) != CE_None)
7011 : {
7012 114 : delete psSelectInfo;
7013 114 : return nullptr;
7014 : }
7015 :
7016 : /* -------------------------------------------------------------------- */
7017 : /* If there is no UNION ALL, build result layer. */
7018 : /* -------------------------------------------------------------------- */
7019 2184 : if (psSelectInfo->poOtherSelect == nullptr)
7020 : {
7021 2179 : return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
7022 2179 : pszDialect, poSelectParseOptions);
7023 : }
7024 :
7025 : /* -------------------------------------------------------------------- */
7026 : /* Build result union layer. */
7027 : /* -------------------------------------------------------------------- */
7028 5 : int nSrcLayers = 0;
7029 5 : OGRLayer **papoSrcLayers = nullptr;
7030 :
7031 5 : do
7032 : {
7033 10 : swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
7034 10 : psSelectInfo->poOtherSelect = nullptr;
7035 :
7036 10 : OGRLayer *poLayer = BuildLayerFromSelectInfo(
7037 : psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
7038 10 : if (poLayer == nullptr)
7039 : {
7040 : // Each source layer owns an independent select info.
7041 0 : for (int i = 0; i < nSrcLayers; ++i)
7042 0 : delete papoSrcLayers[i];
7043 0 : CPLFree(papoSrcLayers);
7044 :
7045 : // So we just have to destroy the remaining select info.
7046 0 : delete psNextSelectInfo;
7047 :
7048 0 : return nullptr;
7049 : }
7050 : else
7051 : {
7052 20 : papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
7053 10 : papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
7054 10 : papoSrcLayers[nSrcLayers] = poLayer;
7055 10 : ++nSrcLayers;
7056 :
7057 10 : psSelectInfo = psNextSelectInfo;
7058 : }
7059 10 : } while (psSelectInfo != nullptr);
7060 :
7061 5 : return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
7062 : }
7063 :
7064 : //! @endcond
7065 :
7066 : /************************************************************************/
7067 : /* AbortSQL() */
7068 : /************************************************************************/
7069 :
7070 : /**
7071 : \brief Abort any SQL statement running in the data store.
7072 :
7073 : This function can be safely called from any thread (pending that the dataset
7074 : object is still alive). Driver implementations will make sure that it can be
7075 : called in a thread-safe way.
7076 :
7077 : This might not be implemented by all drivers. At time of writing, only SQLite,
7078 : GPKG and PG drivers implement it
7079 :
7080 : This method is the same as the C method GDALDatasetAbortSQL()
7081 :
7082 : @since GDAL 3.2.0
7083 :
7084 :
7085 : */
7086 :
7087 0 : OGRErr GDALDataset::AbortSQL()
7088 : {
7089 0 : CPLError(CE_Failure, CPLE_NotSupported,
7090 : "AbortSQL is not supported for this driver.");
7091 0 : return OGRERR_UNSUPPORTED_OPERATION;
7092 : }
7093 :
7094 : /************************************************************************/
7095 : /* BuildLayerFromSelectInfo() */
7096 : /************************************************************************/
7097 :
7098 : struct GDALSQLParseInfo
7099 : {
7100 : swq_field_list sFieldList;
7101 : int nExtraDSCount;
7102 : GDALDataset **papoExtraDS;
7103 : char *pszWHERE;
7104 : };
7105 :
7106 2189 : OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
7107 : swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
7108 : const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
7109 : {
7110 4378 : std::unique_ptr<swq_select> psSelectInfoUnique(psSelectInfo);
7111 :
7112 2189 : std::unique_ptr<OGRGenSQLResultsLayer> poResults;
7113 : GDALSQLParseInfo *psParseInfo =
7114 2189 : BuildParseInfo(psSelectInfoUnique.get(), poSelectParseOptions);
7115 :
7116 2189 : if (psParseInfo)
7117 : {
7118 2155 : const auto nErrorCounter = CPLGetErrorCounter();
7119 4310 : poResults = std::make_unique<OGRGenSQLResultsLayer>(
7120 2155 : this, std::move(psSelectInfoUnique), poSpatialFilter,
7121 4310 : psParseInfo->pszWHERE, pszDialect);
7122 2232 : if (CPLGetErrorCounter() > nErrorCounter &&
7123 77 : CPLGetLastErrorType() != CE_None)
7124 77 : poResults.reset();
7125 : }
7126 :
7127 2189 : DestroyParseInfo(psParseInfo);
7128 :
7129 4378 : return poResults.release();
7130 : }
7131 :
7132 : /************************************************************************/
7133 : /* DestroyParseInfo() */
7134 : /************************************************************************/
7135 :
7136 : //! @cond Doxygen_Suppress
7137 2257 : void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
7138 : {
7139 2257 : if (psParseInfo == nullptr)
7140 34 : return;
7141 :
7142 2223 : CPLFree(psParseInfo->sFieldList.names);
7143 2223 : CPLFree(psParseInfo->sFieldList.types);
7144 2223 : CPLFree(psParseInfo->sFieldList.table_ids);
7145 2223 : CPLFree(psParseInfo->sFieldList.ids);
7146 :
7147 : // Release the datasets we have opened with OGROpenShared()
7148 : // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
7149 : // has taken a reference on them, which it will release in its
7150 : // destructor.
7151 2230 : for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)
7152 7 : GDALClose(psParseInfo->papoExtraDS[iEDS]);
7153 :
7154 2223 : CPLFree(psParseInfo->papoExtraDS);
7155 2223 : CPLFree(psParseInfo->pszWHERE);
7156 2223 : CPLFree(psParseInfo);
7157 : }
7158 :
7159 : /************************************************************************/
7160 : /* BuildParseInfo() */
7161 : /************************************************************************/
7162 :
7163 : GDALSQLParseInfo *
7164 2223 : GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
7165 : swq_select_parse_options *poSelectParseOptions)
7166 : {
7167 2223 : int nFirstLayerFirstSpecialFieldIndex = 0;
7168 :
7169 : GDALSQLParseInfo *psParseInfo =
7170 2223 : static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
7171 :
7172 : /* -------------------------------------------------------------------- */
7173 : /* Validate that all the source tables are recognized, count */
7174 : /* fields. */
7175 : /* -------------------------------------------------------------------- */
7176 2223 : int nFieldCount = 0;
7177 :
7178 4515 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7179 : {
7180 2294 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7181 2294 : GDALDataset *poTableDS = this;
7182 :
7183 2294 : if (psTableDef->data_source != nullptr)
7184 : {
7185 7 : poTableDS = GDALDataset::FromHandle(
7186 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7187 7 : if (poTableDS == nullptr)
7188 : {
7189 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
7190 0 : CPLError(CE_Failure, CPLE_AppDefined,
7191 : "Unable to open secondary datasource "
7192 : "`%s' required by JOIN.",
7193 : psTableDef->data_source);
7194 :
7195 0 : DestroyParseInfo(psParseInfo);
7196 0 : return nullptr;
7197 : }
7198 :
7199 : // Keep in an array to release at the end of this function.
7200 14 : psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
7201 7 : psParseInfo->papoExtraDS,
7202 7 : sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
7203 7 : psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
7204 : }
7205 :
7206 : OGRLayer *poSrcLayer =
7207 2294 : poTableDS->GetLayerByName(psTableDef->table_name);
7208 :
7209 2294 : if (poSrcLayer == nullptr)
7210 : {
7211 2 : CPLError(CE_Failure, CPLE_AppDefined,
7212 : "SELECT from table %s failed, no such table/featureclass.",
7213 : psTableDef->table_name);
7214 :
7215 2 : DestroyParseInfo(psParseInfo);
7216 2 : return nullptr;
7217 : }
7218 :
7219 2292 : nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
7220 2292 : if (iTable == 0 ||
7221 34 : (poSelectParseOptions &&
7222 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7223 2255 : nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7224 :
7225 2292 : const char *pszFID = poSrcLayer->GetFIDColumn();
7226 2902 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7227 610 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7228 560 : nFieldCount++;
7229 : }
7230 :
7231 : /* -------------------------------------------------------------------- */
7232 : /* Build the field list for all indicated tables. */
7233 : /* -------------------------------------------------------------------- */
7234 :
7235 2221 : psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
7236 2221 : psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
7237 :
7238 2221 : psParseInfo->sFieldList.count = 0;
7239 2221 : psParseInfo->sFieldList.names = static_cast<char **>(
7240 2221 : CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7241 4442 : psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
7242 2221 : sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7243 2221 : psParseInfo->sFieldList.table_ids = static_cast<int *>(
7244 2221 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7245 2221 : psParseInfo->sFieldList.ids = static_cast<int *>(
7246 2221 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7247 :
7248 2221 : bool bIsFID64 = false;
7249 4513 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7250 : {
7251 2292 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7252 2292 : GDALDataset *poTableDS = this;
7253 :
7254 2292 : if (psTableDef->data_source != nullptr)
7255 : {
7256 7 : poTableDS = GDALDataset::FromHandle(
7257 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7258 7 : CPLAssert(poTableDS != nullptr);
7259 7 : poTableDS->Dereference();
7260 : }
7261 :
7262 : OGRLayer *poSrcLayer =
7263 2292 : poTableDS->GetLayerByName(psTableDef->table_name);
7264 :
7265 2292 : for (int iField = 0;
7266 18506 : iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)
7267 : {
7268 : OGRFieldDefn *poFDefn =
7269 16214 : poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
7270 16214 : const int iOutField = psParseInfo->sFieldList.count++;
7271 32428 : psParseInfo->sFieldList.names[iOutField] =
7272 16214 : const_cast<char *>(poFDefn->GetNameRef());
7273 16214 : if (poFDefn->GetType() == OFTInteger)
7274 : {
7275 4202 : if (poFDefn->GetSubType() == OFSTBoolean)
7276 160 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7277 : else
7278 4042 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7279 : }
7280 12012 : else if (poFDefn->GetType() == OFTInteger64)
7281 : {
7282 708 : if (poFDefn->GetSubType() == OFSTBoolean)
7283 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7284 : else
7285 708 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7286 : }
7287 11304 : else if (poFDefn->GetType() == OFTReal)
7288 2669 : psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
7289 8635 : else if (poFDefn->GetType() == OFTString)
7290 5581 : psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
7291 3054 : else if (poFDefn->GetType() == OFTTime)
7292 83 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
7293 2971 : else if (poFDefn->GetType() == OFTDate)
7294 143 : psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
7295 2828 : else if (poFDefn->GetType() == OFTDateTime)
7296 939 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
7297 : else
7298 1889 : psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
7299 :
7300 16214 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7301 16214 : psParseInfo->sFieldList.ids[iOutField] = iField;
7302 : }
7303 :
7304 2292 : if (iTable == 0)
7305 : {
7306 2221 : nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
7307 : }
7308 :
7309 2292 : if (iTable == 0 ||
7310 34 : (poSelectParseOptions &&
7311 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7312 : {
7313 :
7314 2255 : for (int iField = 0;
7315 4160 : iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7316 : iField++)
7317 : {
7318 : OGRGeomFieldDefn *poFDefn =
7319 1905 : poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
7320 1905 : const int iOutField = psParseInfo->sFieldList.count++;
7321 3810 : psParseInfo->sFieldList.names[iOutField] =
7322 1905 : const_cast<char *>(poFDefn->GetNameRef());
7323 1905 : if (*psParseInfo->sFieldList.names[iOutField] == '\0')
7324 1092 : psParseInfo->sFieldList.names[iOutField] =
7325 : const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
7326 1905 : psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
7327 :
7328 1905 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7329 1905 : psParseInfo->sFieldList.ids[iOutField] =
7330 1905 : GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
7331 : poSrcLayer->GetLayerDefn(), iField);
7332 : }
7333 : }
7334 :
7335 2293 : if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7336 1 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7337 : {
7338 1 : bIsFID64 = true;
7339 : }
7340 : }
7341 :
7342 : /* -------------------------------------------------------------------- */
7343 : /* Expand '*' in 'SELECT *' now before we add the pseudo fields */
7344 : /* -------------------------------------------------------------------- */
7345 2221 : const bool bAlwaysPrefixWithTableName =
7346 2263 : poSelectParseOptions &&
7347 42 : poSelectParseOptions->bAlwaysPrefixWithTableName;
7348 2221 : if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
7349 2221 : bAlwaysPrefixWithTableName) != CE_None)
7350 : {
7351 2 : DestroyParseInfo(psParseInfo);
7352 2 : return nullptr;
7353 : }
7354 :
7355 13314 : for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
7356 : {
7357 11095 : psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
7358 11095 : const_cast<char *>(SpecialFieldNames[iField]);
7359 11095 : psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
7360 11095 : (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
7361 : : SpecialFieldTypes[iField];
7362 11095 : psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
7363 11095 : psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
7364 11095 : nFirstLayerFirstSpecialFieldIndex + iField;
7365 11095 : psParseInfo->sFieldList.count++;
7366 : }
7367 :
7368 : /* In the case a layer has an explicit FID column name, then add it */
7369 : /* so it can be selected */
7370 4509 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7371 : {
7372 2290 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7373 2290 : GDALDataset *poTableDS = this;
7374 :
7375 2290 : if (psTableDef->data_source != nullptr)
7376 : {
7377 7 : poTableDS = GDALDataset::FromHandle(
7378 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7379 7 : CPLAssert(poTableDS != nullptr);
7380 7 : poTableDS->Dereference();
7381 : }
7382 :
7383 : OGRLayer *poSrcLayer =
7384 2290 : poTableDS->GetLayerByName(psTableDef->table_name);
7385 :
7386 2290 : const char *pszFID = poSrcLayer->GetFIDColumn();
7387 2900 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7388 610 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7389 : {
7390 560 : const int iOutField = psParseInfo->sFieldList.count++;
7391 560 : psParseInfo->sFieldList.names[iOutField] =
7392 : const_cast<char *>(pszFID);
7393 560 : if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7394 0 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7395 : {
7396 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7397 : }
7398 : else
7399 : {
7400 560 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7401 : }
7402 560 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7403 1120 : psParseInfo->sFieldList.ids[iOutField] =
7404 560 : poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
7405 : }
7406 : }
7407 :
7408 : /* -------------------------------------------------------------------- */
7409 : /* Finish the parse operation. */
7410 : /* -------------------------------------------------------------------- */
7411 2219 : if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
7412 : CE_None)
7413 : {
7414 30 : DestroyParseInfo(psParseInfo);
7415 30 : return nullptr;
7416 : }
7417 :
7418 : /* -------------------------------------------------------------------- */
7419 : /* Extract the WHERE expression to use separately. */
7420 : /* -------------------------------------------------------------------- */
7421 2189 : if (psSelectInfo->where_expr != nullptr)
7422 : {
7423 952 : psParseInfo->pszWHERE =
7424 952 : psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
7425 : // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
7426 : }
7427 :
7428 2189 : return psParseInfo;
7429 : }
7430 :
7431 : //! @endcond
7432 :
7433 : /************************************************************************/
7434 : /* ReleaseResultSet() */
7435 : /************************************************************************/
7436 :
7437 : /**
7438 : \brief Release results of ExecuteSQL().
7439 :
7440 : This method should only be used to deallocate OGRLayers resulting from
7441 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
7442 : results set before destroying the GDALDataset may cause errors.
7443 :
7444 : This method is the same as the C function GDALDatasetReleaseResultSet() and the
7445 : deprecated OGR_DS_ReleaseResultSet().
7446 :
7447 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7448 :
7449 : @param poResultsSet the result of a previous ExecuteSQL() call.
7450 : */
7451 :
7452 2103 : void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)
7453 :
7454 : {
7455 2103 : delete poResultsSet;
7456 2103 : }
7457 :
7458 : /************************************************************************/
7459 : /* GetStyleTable() */
7460 : /************************************************************************/
7461 :
7462 : /**
7463 : \brief Returns dataset style table.
7464 :
7465 : This method is the same as the C function GDALDatasetGetStyleTable() and the
7466 : deprecated OGR_DS_GetStyleTable().
7467 :
7468 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7469 :
7470 : @return pointer to a style table which should not be modified or freed by the
7471 : caller.
7472 : */
7473 :
7474 731 : OGRStyleTable *GDALDataset::GetStyleTable()
7475 : {
7476 731 : return m_poStyleTable;
7477 : }
7478 :
7479 : /************************************************************************/
7480 : /* SetStyleTableDirectly() */
7481 : /************************************************************************/
7482 :
7483 : /**
7484 : \brief Set dataset style table.
7485 :
7486 : This method operate exactly as SetStyleTable() except that it
7487 : assumes ownership of the passed table.
7488 :
7489 : This method is the same as the C function GDALDatasetSetStyleTableDirectly()
7490 : and the deprecated OGR_DS_SetStyleTableDirectly().
7491 :
7492 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7493 :
7494 : @param poStyleTable pointer to style table to set
7495 :
7496 : */
7497 0 : void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
7498 : {
7499 0 : if (m_poStyleTable)
7500 0 : delete m_poStyleTable;
7501 0 : m_poStyleTable = poStyleTable;
7502 0 : }
7503 :
7504 : /************************************************************************/
7505 : /* SetStyleTable() */
7506 : /************************************************************************/
7507 :
7508 : /**
7509 : \brief Set dataset style table.
7510 :
7511 : This method operate exactly as SetStyleTableDirectly() except
7512 : that it does not assume ownership of the passed table.
7513 :
7514 : This method is the same as the C function GDALDatasetSetStyleTable() and the
7515 : deprecated OGR_DS_SetStyleTable().
7516 :
7517 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7518 :
7519 : @param poStyleTable pointer to style table to set
7520 :
7521 : */
7522 :
7523 727 : void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
7524 : {
7525 727 : if (m_poStyleTable)
7526 0 : delete m_poStyleTable;
7527 727 : if (poStyleTable)
7528 1 : m_poStyleTable = poStyleTable->Clone();
7529 727 : }
7530 :
7531 : /************************************************************************/
7532 : /* IsGenericSQLDialect() */
7533 : /************************************************************************/
7534 :
7535 : //! @cond Doxygen_Suppress
7536 1746 : int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
7537 : {
7538 3178 : return pszDialect != nullptr &&
7539 3178 : (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
7540 : }
7541 :
7542 : //! @endcond
7543 :
7544 : /************************************************************************/
7545 : /* GetLayerCount() */
7546 : /************************************************************************/
7547 :
7548 : /**
7549 : \brief Get the number of layers in this dataset.
7550 :
7551 : This method is the same as the C function GDALDatasetGetLayerCount(),
7552 : and the deprecated OGR_DS_GetLayerCount().
7553 :
7554 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7555 :
7556 : @return layer count.
7557 : */
7558 :
7559 87354 : int GDALDataset::GetLayerCount()
7560 : {
7561 87354 : return 0;
7562 : }
7563 :
7564 : /************************************************************************/
7565 : /* GetLayer() */
7566 : /************************************************************************/
7567 :
7568 : /**
7569 : \fn GDALDataset::GetLayer(int)
7570 : \brief Fetch a layer by index.
7571 :
7572 : The returned layer remains owned by the
7573 : GDALDataset and should not be deleted by the application.
7574 :
7575 : See GetLayers() for a C++ iterator version of this method.
7576 :
7577 : This method is the same as the C function GDALDatasetGetLayer() and the
7578 : deprecated OGR_DS_GetLayer().
7579 :
7580 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7581 :
7582 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7583 :
7584 : @return the layer, or NULL if iLayer is out of range or an error occurs.
7585 :
7586 : @see GetLayers()
7587 : */
7588 :
7589 0 : OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer)
7590 : {
7591 0 : return nullptr;
7592 : }
7593 :
7594 : /************************************************************************/
7595 : /* IsLayerPrivate() */
7596 : /************************************************************************/
7597 :
7598 : /**
7599 : \fn GDALDataset::IsLayerPrivate(int)
7600 : \brief Returns true if the layer at the specified index is deemed a private or
7601 : system table, or an internal detail only.
7602 :
7603 : This method is the same as the C function GDALDatasetIsLayerPrivate().
7604 :
7605 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7606 :
7607 : @return true if the layer is a private or system table.
7608 :
7609 : @since GDAL 3.4
7610 : */
7611 :
7612 731 : bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const
7613 : {
7614 731 : return false;
7615 : }
7616 :
7617 : /************************************************************************/
7618 : /* ResetReading() */
7619 : /************************************************************************/
7620 :
7621 : /**
7622 : \brief Reset feature reading to start on the first feature.
7623 :
7624 : This affects GetNextFeature().
7625 :
7626 : Depending on drivers, this may also have the side effect of calling
7627 : OGRLayer::ResetReading() on the layers of this dataset.
7628 :
7629 : This method is the same as the C function GDALDatasetResetReading().
7630 :
7631 : @since GDAL 2.2
7632 : */
7633 5 : void GDALDataset::ResetReading()
7634 : {
7635 5 : if (!m_poPrivate)
7636 0 : return;
7637 5 : m_poPrivate->nCurrentLayerIdx = 0;
7638 5 : m_poPrivate->nLayerCount = -1;
7639 5 : m_poPrivate->poCurrentLayer = nullptr;
7640 5 : m_poPrivate->nFeatureReadInLayer = 0;
7641 5 : m_poPrivate->nFeatureReadInDataset = 0;
7642 5 : m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
7643 5 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
7644 : }
7645 :
7646 : /************************************************************************/
7647 : /* GDALDatasetResetReading() */
7648 : /************************************************************************/
7649 :
7650 : /**
7651 : \brief Reset feature reading to start on the first feature.
7652 :
7653 : This affects GDALDatasetGetNextFeature().
7654 :
7655 : Depending on drivers, this may also have the side effect of calling
7656 : OGR_L_ResetReading() on the layers of this dataset.
7657 :
7658 : This method is the same as the C++ method GDALDataset::ResetReading()
7659 :
7660 : @param hDS dataset handle
7661 : @since GDAL 2.2
7662 : */
7663 8 : void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)
7664 : {
7665 8 : VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
7666 :
7667 8 : return GDALDataset::FromHandle(hDS)->ResetReading();
7668 : }
7669 :
7670 : /************************************************************************/
7671 : /* GetNextFeature() */
7672 : /************************************************************************/
7673 :
7674 : /**
7675 : \brief Fetch the next available feature from this dataset.
7676 :
7677 : This method is intended for the few drivers where OGRLayer::GetNextFeature()
7678 : is not efficient, but in general OGRLayer::GetNextFeature() is a more
7679 : natural API.
7680 :
7681 : See GetFeatures() for a C++ iterator version of this method.
7682 :
7683 : The returned feature becomes the responsibility of the caller to
7684 : delete with OGRFeature::DestroyFeature().
7685 :
7686 : Depending on the driver, this method may return features from layers in a
7687 : non sequential way. This is what may happen when the
7688 : ODsCRandomLayerRead capability is declared (for example for the
7689 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7690 : advised to use GDALDataset::GetNextFeature() instead of
7691 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7692 : implementation.
7693 :
7694 : The default implementation, used by most drivers, will
7695 : however iterate over each layer, and then over each feature within this
7696 : layer.
7697 :
7698 : This method takes into account spatial and attribute filters set on layers that
7699 : will be iterated upon.
7700 :
7701 : The ResetReading() method can be used to start at the beginning again.
7702 :
7703 : Depending on drivers, this may also have the side effect of calling
7704 : OGRLayer::GetNextFeature() on the layers of this dataset.
7705 :
7706 : This method is the same as the C function GDALDatasetGetNextFeature().
7707 :
7708 : @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
7709 : layer to which the object belongs to, or NULL.
7710 : It is possible that the output of *ppoBelongingLayer
7711 : to be NULL despite the feature not being NULL.
7712 : @param pdfProgressPct a pointer to a double variable to receive the
7713 : percentage progress (in [0,1] range), or NULL.
7714 : On return, the pointed value might be negative if
7715 : determining the progress is not possible.
7716 : @param pfnProgress a progress callback to report progress (for
7717 : GetNextFeature() calls that might have a long
7718 : duration) and offer cancellation possibility, or NULL.
7719 : @param pProgressData user data provided to pfnProgress, or NULL
7720 : @return a feature, or NULL if no more features are available.
7721 : @since GDAL 2.2
7722 : @see GetFeatures()
7723 : */
7724 :
7725 47 : OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,
7726 : double *pdfProgressPct,
7727 : GDALProgressFunc pfnProgress,
7728 : void *pProgressData)
7729 : {
7730 47 : if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)
7731 : {
7732 2 : if (ppoBelongingLayer != nullptr)
7733 2 : *ppoBelongingLayer = nullptr;
7734 2 : if (pdfProgressPct != nullptr)
7735 1 : *pdfProgressPct = 1.0;
7736 2 : if (pfnProgress != nullptr)
7737 0 : pfnProgress(1.0, "", pProgressData);
7738 2 : return nullptr;
7739 : }
7740 :
7741 45 : if (m_poPrivate->poCurrentLayer == nullptr &&
7742 6 : (pdfProgressPct != nullptr || pfnProgress != nullptr))
7743 : {
7744 1 : if (m_poPrivate->nLayerCount < 0)
7745 : {
7746 1 : m_poPrivate->nLayerCount = GetLayerCount();
7747 : }
7748 :
7749 1 : if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)
7750 : {
7751 1 : m_poPrivate->nTotalFeatures = 0;
7752 5 : for (int i = 0; i < m_poPrivate->nLayerCount; i++)
7753 : {
7754 4 : OGRLayer *poLayer = GetLayer(i);
7755 8 : if (poLayer == nullptr ||
7756 4 : !poLayer->TestCapability(OLCFastFeatureCount))
7757 : {
7758 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7759 0 : break;
7760 : }
7761 4 : GIntBig nCount = poLayer->GetFeatureCount(FALSE);
7762 4 : if (nCount < 0)
7763 : {
7764 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7765 0 : break;
7766 : }
7767 4 : m_poPrivate->nTotalFeatures += nCount;
7768 : }
7769 : }
7770 : }
7771 :
7772 : while (true)
7773 : {
7774 56 : if (m_poPrivate->poCurrentLayer == nullptr)
7775 : {
7776 36 : m_poPrivate->poCurrentLayer =
7777 18 : GetLayer(m_poPrivate->nCurrentLayerIdx);
7778 18 : if (m_poPrivate->poCurrentLayer == nullptr)
7779 : {
7780 5 : m_poPrivate->nCurrentLayerIdx = -1;
7781 5 : if (ppoBelongingLayer != nullptr)
7782 5 : *ppoBelongingLayer = nullptr;
7783 5 : if (pdfProgressPct != nullptr)
7784 1 : *pdfProgressPct = 1.0;
7785 5 : return nullptr;
7786 : }
7787 13 : m_poPrivate->poCurrentLayer->ResetReading();
7788 13 : m_poPrivate->nFeatureReadInLayer = 0;
7789 13 : if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)
7790 : {
7791 0 : if (m_poPrivate->poCurrentLayer->TestCapability(
7792 0 : OLCFastFeatureCount))
7793 0 : m_poPrivate->nTotalFeaturesInLayer =
7794 0 : m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
7795 : else
7796 0 : m_poPrivate->nTotalFeaturesInLayer = 0;
7797 : }
7798 : }
7799 51 : OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
7800 51 : if (poFeature == nullptr)
7801 : {
7802 11 : m_poPrivate->nCurrentLayerIdx++;
7803 11 : m_poPrivate->poCurrentLayer = nullptr;
7804 11 : continue;
7805 : }
7806 :
7807 40 : m_poPrivate->nFeatureReadInLayer++;
7808 40 : m_poPrivate->nFeatureReadInDataset++;
7809 40 : if (pdfProgressPct != nullptr || pfnProgress != nullptr)
7810 : {
7811 4 : double dfPct = 0.0;
7812 4 : if (m_poPrivate->nTotalFeatures > 0)
7813 : {
7814 4 : dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
7815 4 : m_poPrivate->nTotalFeatures;
7816 : }
7817 : else
7818 : {
7819 0 : dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /
7820 0 : m_poPrivate->nLayerCount;
7821 0 : if (m_poPrivate->nTotalFeaturesInLayer > 0)
7822 : {
7823 0 : dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
7824 0 : m_poPrivate->nTotalFeaturesInLayer /
7825 0 : m_poPrivate->nLayerCount;
7826 : }
7827 : }
7828 4 : if (pdfProgressPct)
7829 4 : *pdfProgressPct = dfPct;
7830 4 : if (pfnProgress)
7831 0 : pfnProgress(dfPct, "", nullptr);
7832 : }
7833 :
7834 40 : if (ppoBelongingLayer != nullptr)
7835 40 : *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
7836 40 : return poFeature;
7837 11 : }
7838 : }
7839 :
7840 : /************************************************************************/
7841 : /* GDALDatasetGetNextFeature() */
7842 : /************************************************************************/
7843 : /**
7844 : \brief Fetch the next available feature from this dataset.
7845 :
7846 : This method is intended for the few drivers where OGR_L_GetNextFeature()
7847 : is not efficient, but in general OGR_L_GetNextFeature() is a more
7848 : natural API.
7849 :
7850 : The returned feature becomes the responsibility of the caller to
7851 : delete with OGRFeature::DestroyFeature().
7852 :
7853 : Depending on the driver, this method may return features from layers in a
7854 : non sequential way. This is what may happen when the
7855 : ODsCRandomLayerRead capability is declared (for example for the
7856 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7857 : advised to use GDALDataset::GetNextFeature() instead of
7858 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7859 : implementation.
7860 :
7861 : The default implementation, used by most drivers, will
7862 : however iterate over each layer, and then over each feature within this
7863 : layer.
7864 :
7865 : This method takes into account spatial and attribute filters set on layers that
7866 : will be iterated upon.
7867 :
7868 : The ResetReading() method can be used to start at the beginning again.
7869 :
7870 : Depending on drivers, this may also have the side effect of calling
7871 : OGRLayer::GetNextFeature() on the layers of this dataset.
7872 :
7873 : This method is the same as the C++ method GDALDataset::GetNextFeature()
7874 :
7875 : @param hDS dataset handle.
7876 : @param phBelongingLayer a pointer to a OGRLayer* variable to receive the
7877 : layer to which the object belongs to, or NULL.
7878 : It is possible that the output of *ppoBelongingLayer
7879 : to be NULL despite the feature not being NULL.
7880 : @param pdfProgressPct a pointer to a double variable to receive the
7881 : percentage progress (in [0,1] range), or NULL.
7882 : On return, the pointed value might be negative if
7883 : determining the progress is not possible.
7884 : @param pfnProgress a progress callback to report progress (for
7885 : GetNextFeature() calls that might have a long
7886 : duration) and offer cancellation possibility, or NULL
7887 : @param pProgressData user data provided to pfnProgress, or NULL
7888 : @return a feature, or NULL if no more features are available.
7889 : @since GDAL 2.2
7890 : */
7891 1833 : OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,
7892 : OGRLayerH *phBelongingLayer,
7893 : double *pdfProgressPct,
7894 : GDALProgressFunc pfnProgress,
7895 : void *pProgressData)
7896 : {
7897 1833 : VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
7898 :
7899 3666 : return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(
7900 : reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
7901 3666 : pfnProgress, pProgressData));
7902 : }
7903 :
7904 : /************************************************************************/
7905 : /* TestCapability() */
7906 : /************************************************************************/
7907 :
7908 : /**
7909 : \fn GDALDataset::TestCapability( const char * pszCap )
7910 : \brief Test if capability is available.
7911 :
7912 : One of the following dataset capability names can be passed into this
7913 : method, and a TRUE or FALSE value will be returned indicating whether or not
7914 : the capability is available for this object.
7915 :
7916 : <ul>
7917 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7918 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7919 : layers.<p>
7920 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7921 : datasource support CreateGeomField() just after layer creation.<p>
7922 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7923 : geometries.<p>
7924 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7925 : transactions.<p>
7926 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7927 : transactions through emulation.<p>
7928 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7929 : GetNextFeature() implementation, potentially returning features from
7930 : layers in a non sequential way.<p>
7931 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7932 : CreateFeature() on layers in a non sequential way.<p>
7933 : </ul>
7934 :
7935 : The \#define macro forms of the capability names should be used in preference
7936 : to the strings themselves to avoid misspelling.
7937 :
7938 : This method is the same as the C function GDALDatasetTestCapability() and the
7939 : deprecated OGR_DS_TestCapability().
7940 :
7941 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7942 :
7943 : @param pszCap the capability to test.
7944 :
7945 : @return TRUE if capability available otherwise FALSE.
7946 : */
7947 :
7948 240 : int GDALDataset::TestCapability(CPL_UNUSED const char *pszCap)
7949 : {
7950 240 : return FALSE;
7951 : }
7952 :
7953 : /************************************************************************/
7954 : /* GDALDatasetTestCapability() */
7955 : /************************************************************************/
7956 :
7957 : /**
7958 : \brief Test if capability is available.
7959 :
7960 : One of the following dataset capability names can be passed into this
7961 : function, and a TRUE or FALSE value will be returned indicating whether or not
7962 : the capability is available for this object.
7963 :
7964 : <ul>
7965 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7966 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7967 : layers.<p>
7968 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7969 : datasource support CreateGeomField() just after layer creation.<p>
7970 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7971 : geometries.<p>
7972 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7973 : transactions.<p>
7974 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7975 : transactions through emulation.<p>
7976 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7977 : GetNextFeature() implementation, potentially returning features from
7978 : layers in a non sequential way.<p>
7979 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7980 : CreateFeature() on layers in a non sequential way.<p>
7981 : </ul>
7982 :
7983 : The \#define macro forms of the capability names should be used in preference
7984 : to the strings themselves to avoid misspelling.
7985 :
7986 : This function is the same as the C++ method GDALDataset::TestCapability()
7987 :
7988 : @since GDAL 2.0
7989 :
7990 : @param hDS the dataset handle.
7991 : @param pszCap the capability to test.
7992 :
7993 : @return TRUE if capability available otherwise FALSE.
7994 : */
7995 115 : int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)
7996 :
7997 : {
7998 115 : VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
7999 115 : VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
8000 :
8001 115 : return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
8002 : }
8003 :
8004 : /************************************************************************/
8005 : /* StartTransaction() */
8006 : /************************************************************************/
8007 :
8008 : /**
8009 : \fn GDALDataset::StartTransaction(int)
8010 : \brief For datasources which support transactions, StartTransaction creates a
8011 : `transaction.
8012 :
8013 : If starting the transaction fails, will return
8014 : OGRERR_FAILURE. Datasources which do not support transactions will
8015 : always return OGRERR_UNSUPPORTED_OPERATION.
8016 :
8017 : Nested transactions are not supported.
8018 :
8019 : All changes done after the start of the transaction are definitely applied in
8020 : the datasource if CommitTransaction() is called. They may be canceled by
8021 : calling RollbackTransaction() instead.
8022 :
8023 : At the time of writing, transactions only apply on vector layers.
8024 :
8025 : Datasets that support transactions will advertise the ODsCTransactions
8026 : capability. Use of transactions at dataset level is generally preferred to
8027 : transactions at layer level, whose scope is rarely limited to the layer from
8028 : which it was started.
8029 :
8030 : In case StartTransaction() fails, neither CommitTransaction() or
8031 : RollbackTransaction() should be called.
8032 :
8033 : If an error occurs after a successful StartTransaction(), the whole transaction
8034 : may or may not be implicitly canceled, depending on drivers. (e.g. the PG
8035 : driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
8036 : an explicit call to RollbackTransaction() should be done to keep things
8037 : balanced.
8038 :
8039 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8040 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8041 : with significant overhead, in which case the user must explicitly allow for
8042 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8043 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8044 : ODsCTransactions).
8045 :
8046 : This function is the same as the C function GDALDatasetStartTransaction().
8047 :
8048 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8049 : transaction
8050 : mechanism is acceptable.
8051 :
8052 : @return OGRERR_NONE on success.
8053 : @since GDAL 2.0
8054 : */
8055 :
8056 37 : OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
8057 : {
8058 37 : return OGRERR_UNSUPPORTED_OPERATION;
8059 : }
8060 :
8061 : /************************************************************************/
8062 : /* GDALDatasetStartTransaction() */
8063 : /************************************************************************/
8064 :
8065 : /**
8066 : \brief For datasources which support transactions, StartTransaction creates a
8067 : transaction.
8068 :
8069 : If starting the transaction fails, will return
8070 : OGRERR_FAILURE. Datasources which do not support transactions will
8071 : always return OGRERR_UNSUPPORTED_OPERATION.
8072 :
8073 : Nested transactions are not supported.
8074 :
8075 : All changes done after the start of the transaction are definitely applied in
8076 : the datasource if CommitTransaction() is called. They may be canceled by
8077 : calling RollbackTransaction() instead.
8078 :
8079 : At the time of writing, transactions only apply on vector layers.
8080 :
8081 : Datasets that support transactions will advertise the ODsCTransactions
8082 : capability.
8083 : Use of transactions at dataset level is generally preferred to transactions at
8084 : layer level, whose scope is rarely limited to the layer from which it was
8085 : started.
8086 :
8087 : In case StartTransaction() fails, neither CommitTransaction() or
8088 : RollbackTransaction() should be called.
8089 :
8090 : If an error occurs after a successful StartTransaction(), the whole
8091 : transaction may or may not be implicitly canceled, depending on drivers. (e.g.
8092 : the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
8093 : error, an explicit call to RollbackTransaction() should be done to keep things
8094 : balanced.
8095 :
8096 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8097 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8098 : with significant overhead, in which case the user must explicitly allow for
8099 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8100 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8101 : ODsCTransactions).
8102 :
8103 : This function is the same as the C++ method GDALDataset::StartTransaction()
8104 :
8105 : @param hDS the dataset handle.
8106 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8107 : transaction
8108 : mechanism is acceptable.
8109 :
8110 : @return OGRERR_NONE on success.
8111 : @since GDAL 2.0
8112 : */
8113 88 : OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
8114 : {
8115 88 : VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
8116 : OGRERR_INVALID_HANDLE);
8117 :
8118 : #ifdef OGRAPISPY_ENABLED
8119 88 : if (bOGRAPISpyEnabled)
8120 2 : OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
8121 : #endif
8122 :
8123 88 : return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
8124 : }
8125 :
8126 : /************************************************************************/
8127 : /* CommitTransaction() */
8128 : /************************************************************************/
8129 :
8130 : /**
8131 : \brief For datasources which support transactions, CommitTransaction commits a
8132 : transaction.
8133 :
8134 : If no transaction is active, or the commit fails, will return
8135 : OGRERR_FAILURE. Datasources which do not support transactions will
8136 : always return OGRERR_UNSUPPORTED_OPERATION.
8137 :
8138 : Depending on drivers, this may or may not abort layer sequential readings that
8139 : are active.
8140 :
8141 : This function is the same as the C function GDALDatasetCommitTransaction().
8142 :
8143 : @return OGRERR_NONE on success.
8144 : @since GDAL 2.0
8145 : */
8146 37 : OGRErr GDALDataset::CommitTransaction()
8147 : {
8148 37 : return OGRERR_UNSUPPORTED_OPERATION;
8149 : }
8150 :
8151 : /************************************************************************/
8152 : /* GDALDatasetCommitTransaction() */
8153 : /************************************************************************/
8154 :
8155 : /**
8156 : \brief For datasources which support transactions, CommitTransaction commits a
8157 : transaction.
8158 :
8159 : If no transaction is active, or the commit fails, will return
8160 : OGRERR_FAILURE. Datasources which do not support transactions will
8161 : always return OGRERR_UNSUPPORTED_OPERATION.
8162 :
8163 : Depending on drivers, this may or may not abort layer sequential readings that
8164 : are active.
8165 :
8166 : This function is the same as the C++ method GDALDataset::CommitTransaction()
8167 :
8168 : @return OGRERR_NONE on success.
8169 : @since GDAL 2.0
8170 : */
8171 46 : OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
8172 : {
8173 46 : VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
8174 : OGRERR_INVALID_HANDLE);
8175 :
8176 : #ifdef OGRAPISPY_ENABLED
8177 46 : if (bOGRAPISpyEnabled)
8178 2 : OGRAPISpy_Dataset_CommitTransaction(hDS);
8179 : #endif
8180 :
8181 46 : return GDALDataset::FromHandle(hDS)->CommitTransaction();
8182 : }
8183 :
8184 : /************************************************************************/
8185 : /* RollbackTransaction() */
8186 : /************************************************************************/
8187 :
8188 : /**
8189 : \brief For datasources which support transactions, RollbackTransaction will
8190 : roll back a datasource to its state before the start of the current
8191 : transaction.
8192 : If no transaction is active, or the rollback fails, will return
8193 : OGRERR_FAILURE. Datasources which do not support transactions will
8194 : always return OGRERR_UNSUPPORTED_OPERATION.
8195 :
8196 : This function is the same as the C function GDALDatasetRollbackTransaction().
8197 :
8198 : @return OGRERR_NONE on success.
8199 : @since GDAL 2.0
8200 : */
8201 2 : OGRErr GDALDataset::RollbackTransaction()
8202 : {
8203 2 : return OGRERR_UNSUPPORTED_OPERATION;
8204 : }
8205 :
8206 : /************************************************************************/
8207 : /* GDALDatasetRollbackTransaction() */
8208 : /************************************************************************/
8209 :
8210 : /**
8211 : \brief For datasources which support transactions, RollbackTransaction will
8212 : roll back a datasource to its state before the start of the current
8213 : transaction.
8214 : If no transaction is active, or the rollback fails, will return
8215 : OGRERR_FAILURE. Datasources which do not support transactions will
8216 : always return OGRERR_UNSUPPORTED_OPERATION.
8217 :
8218 : This function is the same as the C++ method GDALDataset::RollbackTransaction().
8219 :
8220 : @return OGRERR_NONE on success.
8221 : @since GDAL 2.0
8222 : */
8223 43 : OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
8224 : {
8225 43 : VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
8226 : OGRERR_INVALID_HANDLE);
8227 :
8228 : #ifdef OGRAPISPY_ENABLED
8229 43 : if (bOGRAPISpyEnabled)
8230 2 : OGRAPISpy_Dataset_RollbackTransaction(hDS);
8231 : #endif
8232 :
8233 43 : return GDALDataset::FromHandle(hDS)->RollbackTransaction();
8234 : }
8235 :
8236 : //! @cond Doxygen_Suppress
8237 :
8238 : /************************************************************************/
8239 : /* ShareLockWithParentDataset() */
8240 : /************************************************************************/
8241 :
8242 : /* To be used typically by the GTiff driver to link overview datasets */
8243 : /* with their main dataset, so that they share the same lock */
8244 : /* Cf https://github.com/OSGeo/gdal/issues/1488 */
8245 : /* The parent dataset should remain alive while the this dataset is alive */
8246 :
8247 2200 : void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)
8248 : {
8249 2200 : if (m_poPrivate != nullptr)
8250 : {
8251 2200 : m_poPrivate->poParentDataset = poParentDataset;
8252 : }
8253 2200 : }
8254 :
8255 : /************************************************************************/
8256 : /* SetQueryLoggerFunc() */
8257 : /************************************************************************/
8258 :
8259 0 : bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,
8260 : CPL_UNUSED void *context)
8261 : {
8262 0 : return false;
8263 : }
8264 :
8265 : /************************************************************************/
8266 : /* EnterReadWrite() */
8267 : /************************************************************************/
8268 :
8269 6902910 : int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
8270 : {
8271 13805700 : if (m_poPrivate == nullptr ||
8272 6902880 : IsThreadSafe(GDAL_OF_RASTER | (nOpenFlags & GDAL_OF_UPDATE)))
8273 11753 : return FALSE;
8274 :
8275 6891080 : if (m_poPrivate->poParentDataset)
8276 38404 : return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
8277 :
8278 6852670 : if (eAccess == GA_Update)
8279 : {
8280 1658860 : if (m_poPrivate->eStateReadWriteMutex ==
8281 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8282 : {
8283 : // In case dead-lock would occur, which is not impossible,
8284 : // this can be used to prevent it, but at the risk of other
8285 : // issues.
8286 7710 : if (CPLTestBool(
8287 : CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
8288 : {
8289 7710 : m_poPrivate->eStateReadWriteMutex =
8290 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
8291 : }
8292 : else
8293 : {
8294 0 : m_poPrivate->eStateReadWriteMutex =
8295 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8296 : }
8297 : }
8298 1658860 : if (m_poPrivate->eStateReadWriteMutex ==
8299 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)
8300 : {
8301 : // There should be no race related to creating this mutex since
8302 : // it should be first created through IWriteBlock() / IRasterIO()
8303 : // and then GDALRasterBlock might call it from another thread.
8304 : #ifdef DEBUG_VERBOSE
8305 : CPLDebug("GDAL",
8306 : "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
8307 : CPLGetPID(), GetDescription());
8308 : #endif
8309 1040020 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8310 :
8311 : const int nCountMutex =
8312 1040050 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
8313 1040020 : if (nCountMutex == 0 && eRWFlag == GF_Read)
8314 : {
8315 335155 : CPLReleaseMutex(m_poPrivate->hMutex);
8316 865926 : for (int i = 0; i < nBands; i++)
8317 : {
8318 530771 : auto blockCache = papoBands[i]->poBandBlockCache;
8319 530771 : if (blockCache)
8320 489292 : blockCache->WaitCompletionPendingTasks();
8321 : }
8322 335155 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8323 : }
8324 :
8325 1040020 : return TRUE;
8326 : }
8327 : }
8328 5812660 : return FALSE;
8329 : }
8330 :
8331 : /************************************************************************/
8332 : /* LeaveReadWrite() */
8333 : /************************************************************************/
8334 :
8335 1066960 : void GDALDataset::LeaveReadWrite()
8336 : {
8337 1066960 : if (m_poPrivate)
8338 : {
8339 1066960 : if (m_poPrivate->poParentDataset)
8340 : {
8341 26932 : m_poPrivate->poParentDataset->LeaveReadWrite();
8342 26932 : return;
8343 : }
8344 :
8345 1040030 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
8346 1040000 : CPLReleaseMutex(m_poPrivate->hMutex);
8347 : #ifdef DEBUG_VERBOSE
8348 : CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
8349 : CPLGetPID(), GetDescription());
8350 : #endif
8351 : }
8352 : }
8353 :
8354 : /************************************************************************/
8355 : /* InitRWLock() */
8356 : /************************************************************************/
8357 :
8358 3651600 : void GDALDataset::InitRWLock()
8359 : {
8360 3651600 : if (m_poPrivate)
8361 : {
8362 3651600 : if (m_poPrivate->poParentDataset)
8363 : {
8364 7056 : m_poPrivate->poParentDataset->InitRWLock();
8365 7056 : return;
8366 : }
8367 :
8368 3644550 : if (m_poPrivate->eStateReadWriteMutex ==
8369 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8370 : {
8371 1 : if (EnterReadWrite(GF_Write))
8372 1 : LeaveReadWrite();
8373 : }
8374 : }
8375 : }
8376 :
8377 : /************************************************************************/
8378 : /* DisableReadWriteMutex() */
8379 : /************************************************************************/
8380 :
8381 : // The mutex logic is broken in multi-threaded situations, for example
8382 : // with 2 WarpedVRT datasets being read at the same time. In that
8383 : // particular case, the mutex is not needed, so allow the VRTWarpedDataset code
8384 : // to disable it.
8385 16369 : void GDALDataset::DisableReadWriteMutex()
8386 : {
8387 16369 : if (m_poPrivate)
8388 : {
8389 16368 : if (m_poPrivate->poParentDataset)
8390 : {
8391 0 : m_poPrivate->poParentDataset->DisableReadWriteMutex();
8392 0 : return;
8393 : }
8394 :
8395 16368 : m_poPrivate->eStateReadWriteMutex =
8396 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8397 : }
8398 : }
8399 :
8400 : /************************************************************************/
8401 : /* TemporarilyDropReadWriteLock() */
8402 : /************************************************************************/
8403 :
8404 3170960 : void GDALDataset::TemporarilyDropReadWriteLock()
8405 : {
8406 3170960 : if (m_poPrivate == nullptr)
8407 0 : return;
8408 :
8409 3170960 : if (m_poPrivate->poParentDataset)
8410 : {
8411 23080 : m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
8412 23080 : return;
8413 : }
8414 :
8415 3147880 : if (m_poPrivate->hMutex)
8416 : {
8417 : #ifdef DEBUG_VERBOSE
8418 : CPLDebug("GDAL",
8419 : "[Thread " CPL_FRMT_GIB "] "
8420 : "Temporarily drop RW mutex for %s",
8421 : CPLGetPID(), GetDescription());
8422 : #endif
8423 301932 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8424 : const int nCount =
8425 301932 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8426 : #ifdef DEBUG_EXTRA
8427 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
8428 : #endif
8429 918573 : for (int i = 0; i < nCount + 1; i++)
8430 : {
8431 : // The mutex is recursive
8432 : // coverity[double_unlock]
8433 616638 : CPLReleaseMutex(m_poPrivate->hMutex);
8434 : }
8435 : }
8436 : }
8437 :
8438 : /************************************************************************/
8439 : /* ReacquireReadWriteLock() */
8440 : /************************************************************************/
8441 :
8442 3171100 : void GDALDataset::ReacquireReadWriteLock()
8443 : {
8444 3171100 : if (m_poPrivate == nullptr)
8445 0 : return;
8446 :
8447 3171100 : if (m_poPrivate->poParentDataset)
8448 : {
8449 23080 : m_poPrivate->poParentDataset->ReacquireReadWriteLock();
8450 23080 : return;
8451 : }
8452 :
8453 3148020 : if (m_poPrivate->hMutex)
8454 : {
8455 : #ifdef DEBUG_VERBOSE
8456 : CPLDebug("GDAL",
8457 : "[Thread " CPL_FRMT_GIB "] "
8458 : "Reacquire temporarily dropped RW mutex for %s",
8459 : CPLGetPID(), GetDescription());
8460 : #endif
8461 301934 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8462 : const int nCount =
8463 301934 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8464 : #ifdef DEBUG_EXTRA
8465 : CPLAssert(nCount ==
8466 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
8467 : #endif
8468 301934 : if (nCount == 0)
8469 11462 : CPLReleaseMutex(m_poPrivate->hMutex);
8470 326168 : for (int i = 0; i < nCount - 1; i++)
8471 : {
8472 : // The mutex is recursive
8473 : // coverity[double_lock]
8474 24234 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8475 : }
8476 : }
8477 : }
8478 :
8479 : /************************************************************************/
8480 : /* AcquireMutex() */
8481 : /************************************************************************/
8482 :
8483 196 : int GDALDataset::AcquireMutex()
8484 : {
8485 196 : if (m_poPrivate == nullptr)
8486 0 : return 0;
8487 196 : if (m_poPrivate->poParentDataset)
8488 : {
8489 0 : return m_poPrivate->poParentDataset->AcquireMutex();
8490 : }
8491 :
8492 196 : return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8493 : }
8494 :
8495 : /************************************************************************/
8496 : /* ReleaseMutex() */
8497 : /************************************************************************/
8498 :
8499 196 : void GDALDataset::ReleaseMutex()
8500 : {
8501 196 : if (m_poPrivate)
8502 : {
8503 196 : if (m_poPrivate->poParentDataset)
8504 : {
8505 0 : m_poPrivate->poParentDataset->ReleaseMutex();
8506 0 : return;
8507 : }
8508 :
8509 196 : CPLReleaseMutex(m_poPrivate->hMutex);
8510 : }
8511 : }
8512 :
8513 : //! @endcond
8514 :
8515 : /************************************************************************/
8516 : /* GDALDataset::Features::Iterator::Private */
8517 : /************************************************************************/
8518 :
8519 : struct GDALDataset::Features::Iterator::Private
8520 : {
8521 : GDALDataset::FeatureLayerPair m_oPair{};
8522 : GDALDataset *m_poDS = nullptr;
8523 : bool m_bEOF = true;
8524 : };
8525 :
8526 4 : GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8527 4 : : m_poPrivate(new GDALDataset::Features::Iterator::Private())
8528 : {
8529 4 : m_poPrivate->m_poDS = poDS;
8530 4 : if (bStart)
8531 : {
8532 2 : poDS->ResetReading();
8533 4 : m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(
8534 2 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8535 2 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8536 : }
8537 4 : }
8538 :
8539 : GDALDataset::Features::Iterator::~Iterator() = default;
8540 :
8541 : const GDALDataset::FeatureLayerPair &
8542 20 : GDALDataset::Features::Iterator::operator*() const
8543 : {
8544 20 : return m_poPrivate->m_oPair;
8545 : }
8546 :
8547 20 : GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()
8548 : {
8549 40 : m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(
8550 20 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8551 20 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8552 20 : return *this;
8553 : }
8554 :
8555 22 : bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const
8556 : {
8557 22 : return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
8558 : }
8559 :
8560 : /************************************************************************/
8561 : /* GetFeatures() */
8562 : /************************************************************************/
8563 :
8564 : /** Function that return an iterable object over features in the dataset
8565 : * layer.
8566 : *
8567 : * This is a C++ iterator friendly version of GetNextFeature().
8568 : *
8569 : * Using this iterator for standard range-based loops is safe, but
8570 : * due to implementation limitations, you shouldn't try to access
8571 : * (dereference) more than one iterator step at a time, since the
8572 : * FeatureLayerPair reference which is returned is reused.
8573 : *
8574 : * Typical use is:
8575 : * \code{.cpp}
8576 : * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
8577 : * {
8578 : * std::cout << "Feature of layer " <<
8579 : * oFeatureLayerPair.layer->GetName() << std::endl;
8580 : * oFeatureLayerPair.feature->DumpReadable();
8581 : * }
8582 : * \endcode
8583 : *
8584 : * @see GetNextFeature()
8585 : *
8586 : * @since GDAL 2.3
8587 : */
8588 2 : GDALDataset::Features GDALDataset::GetFeatures()
8589 : {
8590 2 : return Features(this);
8591 : }
8592 :
8593 : /************************************************************************/
8594 : /* begin() */
8595 : /************************************************************************/
8596 :
8597 : /**
8598 : \brief Return beginning of feature iterator.
8599 :
8600 : @since GDAL 2.3
8601 : */
8602 :
8603 2 : const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
8604 : {
8605 2 : return {m_poSelf, true};
8606 : }
8607 :
8608 : /************************************************************************/
8609 : /* end() */
8610 : /************************************************************************/
8611 :
8612 : /**
8613 : \brief Return end of feature iterator.
8614 :
8615 : @since GDAL 2.3
8616 : */
8617 :
8618 2 : const GDALDataset::Features::Iterator GDALDataset::Features::end() const
8619 : {
8620 2 : return {m_poSelf, false};
8621 : }
8622 :
8623 : /************************************************************************/
8624 : /* GDALDataset::Layers::Iterator::Private */
8625 : /************************************************************************/
8626 :
8627 : struct GDALDataset::Layers::Iterator::Private
8628 : {
8629 : OGRLayer *m_poLayer = nullptr;
8630 : int m_iCurLayer = 0;
8631 : int m_nLayerCount = 0;
8632 : GDALDataset *m_poDS = nullptr;
8633 : };
8634 :
8635 2 : GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())
8636 : {
8637 2 : }
8638 :
8639 : // False positive of cppcheck 1.72
8640 : // cppcheck-suppress uninitMemberVar
8641 9 : GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)
8642 9 : : m_poPrivate(new Private(*(oOther.m_poPrivate)))
8643 : {
8644 9 : }
8645 :
8646 5 : GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept
8647 5 : : m_poPrivate(std::move(oOther.m_poPrivate))
8648 : {
8649 5 : }
8650 :
8651 26 : GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8652 26 : : m_poPrivate(new Private())
8653 : {
8654 26 : m_poPrivate->m_poDS = poDS;
8655 26 : m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
8656 26 : if (bStart)
8657 : {
8658 14 : if (m_poPrivate->m_nLayerCount)
8659 13 : m_poPrivate->m_poLayer = poDS->GetLayer(0);
8660 : }
8661 : else
8662 : {
8663 12 : m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
8664 : }
8665 26 : }
8666 :
8667 : GDALDataset::Layers::Iterator::~Iterator() = default;
8668 :
8669 : // False positive of cppcheck 1.72
8670 : // cppcheck-suppress operatorEqVarError
8671 : GDALDataset::Layers::Iterator &
8672 1 : GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)
8673 : {
8674 1 : *m_poPrivate = *oOther.m_poPrivate;
8675 1 : return *this;
8676 : }
8677 :
8678 1 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(
8679 : GDALDataset::Layers::Iterator &&oOther) noexcept
8680 : {
8681 1 : m_poPrivate = std::move(oOther.m_poPrivate);
8682 1 : return *this;
8683 : }
8684 :
8685 36 : OGRLayer *GDALDataset::Layers::Iterator::operator*() const
8686 : {
8687 36 : return m_poPrivate->m_poLayer;
8688 : }
8689 :
8690 36 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()
8691 : {
8692 36 : m_poPrivate->m_iCurLayer++;
8693 36 : if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
8694 : {
8695 27 : m_poPrivate->m_poLayer =
8696 27 : m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
8697 : }
8698 : else
8699 : {
8700 9 : m_poPrivate->m_poLayer = nullptr;
8701 : }
8702 36 : return *this;
8703 : }
8704 :
8705 2 : GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
8706 : {
8707 2 : GDALDataset::Layers::Iterator temp = *this;
8708 2 : ++(*this);
8709 2 : return temp;
8710 : }
8711 :
8712 42 : bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const
8713 : {
8714 42 : return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
8715 : }
8716 :
8717 : /************************************************************************/
8718 : /* GetLayers() */
8719 : /************************************************************************/
8720 :
8721 : /** Function that returns an iterable object over layers in the dataset.
8722 : *
8723 : * This is a C++ iterator friendly version of GetLayer().
8724 : *
8725 : * Typical use is:
8726 : * \code{.cpp}
8727 : * for( auto&& poLayer: poDS->GetLayers() )
8728 : * {
8729 : * std::cout << "Layer << poLayer->GetName() << std::endl;
8730 : * }
8731 : * \endcode
8732 : *
8733 : * @see GetLayer()
8734 : *
8735 : * @since GDAL 2.3
8736 : */
8737 17 : GDALDataset::Layers GDALDataset::GetLayers()
8738 : {
8739 17 : return Layers(this);
8740 : }
8741 :
8742 : /************************************************************************/
8743 : /* begin() */
8744 : /************************************************************************/
8745 :
8746 : /**
8747 : \brief Return beginning of layer iterator.
8748 :
8749 : @since GDAL 2.3
8750 : */
8751 :
8752 14 : GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
8753 : {
8754 14 : return {m_poSelf, true};
8755 : }
8756 :
8757 : /************************************************************************/
8758 : /* end() */
8759 : /************************************************************************/
8760 :
8761 : /**
8762 : \brief Return end of layer iterator.
8763 :
8764 : @since GDAL 2.3
8765 : */
8766 :
8767 12 : GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
8768 : {
8769 12 : return {m_poSelf, false};
8770 : }
8771 :
8772 : /************************************************************************/
8773 : /* size() */
8774 : /************************************************************************/
8775 :
8776 : /**
8777 : \brief Get the number of layers in this dataset.
8778 :
8779 : @return layer count.
8780 :
8781 : @since GDAL 2.3
8782 : */
8783 :
8784 1 : size_t GDALDataset::Layers::size() const
8785 : {
8786 1 : return static_cast<size_t>(m_poSelf->GetLayerCount());
8787 : }
8788 :
8789 : /************************************************************************/
8790 : /* operator[]() */
8791 : /************************************************************************/
8792 : /**
8793 : \brief Fetch a layer by index.
8794 :
8795 : The returned layer remains owned by the
8796 : GDALDataset and should not be deleted by the application.
8797 :
8798 : @param iLayer a layer number between 0 and size()-1.
8799 :
8800 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
8801 :
8802 : @since GDAL 2.3
8803 : */
8804 :
8805 9 : OGRLayer *GDALDataset::Layers::operator[](int iLayer)
8806 : {
8807 9 : return m_poSelf->GetLayer(iLayer);
8808 : }
8809 :
8810 : /************************************************************************/
8811 : /* operator[]() */
8812 : /************************************************************************/
8813 : /**
8814 : \brief Fetch a layer by index.
8815 :
8816 : The returned layer remains owned by the
8817 : GDALDataset and should not be deleted by the application.
8818 :
8819 : @param iLayer a layer number between 0 and size()-1.
8820 :
8821 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
8822 :
8823 : @since GDAL 2.3
8824 : */
8825 :
8826 1 : OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)
8827 : {
8828 1 : return m_poSelf->GetLayer(static_cast<int>(iLayer));
8829 : }
8830 :
8831 : /************************************************************************/
8832 : /* operator[]() */
8833 : /************************************************************************/
8834 : /**
8835 : \brief Fetch a layer by name.
8836 :
8837 : The returned layer remains owned by the
8838 : GDALDataset and should not be deleted by the application.
8839 :
8840 : @param pszLayerName layer name
8841 :
8842 : @return the layer, or nullptr if pszLayerName does not match with a layer
8843 :
8844 : @since GDAL 2.3
8845 : */
8846 :
8847 1 : OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)
8848 : {
8849 1 : return m_poSelf->GetLayerByName(pszLayerName);
8850 : }
8851 :
8852 : /************************************************************************/
8853 : /* GDALDataset::Bands::Iterator::Private */
8854 : /************************************************************************/
8855 :
8856 : struct GDALDataset::Bands::Iterator::Private
8857 : {
8858 : GDALRasterBand *m_poBand = nullptr;
8859 : int m_iCurBand = 0;
8860 : int m_nBandCount = 0;
8861 : GDALDataset *m_poDS = nullptr;
8862 : };
8863 :
8864 6 : GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8865 6 : : m_poPrivate(new GDALDataset::Bands::Iterator::Private())
8866 : {
8867 6 : m_poPrivate->m_poDS = poDS;
8868 6 : m_poPrivate->m_nBandCount = poDS->GetRasterCount();
8869 6 : if (bStart)
8870 : {
8871 3 : if (m_poPrivate->m_nBandCount)
8872 3 : m_poPrivate->m_poBand = poDS->GetRasterBand(1);
8873 : }
8874 : else
8875 : {
8876 3 : m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
8877 : }
8878 6 : }
8879 :
8880 : GDALDataset::Bands::Iterator::~Iterator() = default;
8881 :
8882 5 : GDALRasterBand *GDALDataset::Bands::Iterator::operator*()
8883 : {
8884 5 : return m_poPrivate->m_poBand;
8885 : }
8886 :
8887 3 : GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()
8888 : {
8889 3 : m_poPrivate->m_iCurBand++;
8890 3 : if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
8891 : {
8892 2 : m_poPrivate->m_poBand =
8893 2 : m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
8894 : }
8895 : else
8896 : {
8897 1 : m_poPrivate->m_poBand = nullptr;
8898 : }
8899 3 : return *this;
8900 : }
8901 :
8902 6 : bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const
8903 : {
8904 6 : return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
8905 : }
8906 :
8907 : /************************************************************************/
8908 : /* GetBands() */
8909 : /************************************************************************/
8910 :
8911 : /** Function that returns an iterable object over GDALRasterBand in the dataset.
8912 : *
8913 : * This is a C++ iterator friendly version of GetRasterBand().
8914 : *
8915 : * Typical use is:
8916 : * \code{.cpp}
8917 : * for( auto&& poBand: poDS->GetBands() )
8918 : * {
8919 : * std::cout << "Band << poBand->GetDescription() << std::endl;
8920 : * }
8921 : * \endcode
8922 : *
8923 : * @see GetRasterBand()
8924 : *
8925 : * @since GDAL 2.3
8926 : */
8927 7 : GDALDataset::Bands GDALDataset::GetBands()
8928 : {
8929 7 : return Bands(this);
8930 : }
8931 :
8932 : /************************************************************************/
8933 : /* begin() */
8934 : /************************************************************************/
8935 :
8936 : /**
8937 : \brief Return beginning of band iterator.
8938 :
8939 : @since GDAL 2.3
8940 : */
8941 :
8942 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
8943 : {
8944 3 : return {m_poSelf, true};
8945 : }
8946 :
8947 : /************************************************************************/
8948 : /* end() */
8949 : /************************************************************************/
8950 :
8951 : /**
8952 : \brief Return end of band iterator.
8953 :
8954 : @since GDAL 2.3
8955 : */
8956 :
8957 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
8958 : {
8959 3 : return {m_poSelf, false};
8960 : }
8961 :
8962 : /************************************************************************/
8963 : /* size() */
8964 : /************************************************************************/
8965 :
8966 : /**
8967 : \brief Get the number of raster bands in this dataset.
8968 :
8969 : @return raster band count.
8970 :
8971 : @since GDAL 2.3
8972 : */
8973 :
8974 2 : size_t GDALDataset::Bands::size() const
8975 : {
8976 2 : return static_cast<size_t>(m_poSelf->GetRasterCount());
8977 : }
8978 :
8979 : /************************************************************************/
8980 : /* operator[]() */
8981 : /************************************************************************/
8982 : /**
8983 : \brief Fetch a raster band by index.
8984 :
8985 : The returned band remains owned by the
8986 : GDALDataset and should not be deleted by the application.
8987 :
8988 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
8989 : consistent with the conventions of C/C++, i.e. starting at 0.
8990 :
8991 : @param iBand a band index between 0 and size()-1.
8992 :
8993 : @return the band, or nullptr if iBand is out of range or an error occurs.
8994 :
8995 : @since GDAL 2.3
8996 : */
8997 :
8998 1 : GDALRasterBand *GDALDataset::Bands::operator[](int iBand)
8999 : {
9000 1 : return m_poSelf->GetRasterBand(1 + iBand);
9001 : }
9002 :
9003 : /************************************************************************/
9004 : /* operator[]() */
9005 : /************************************************************************/
9006 :
9007 : /**
9008 : \brief Fetch a raster band by index.
9009 :
9010 : The returned band remains owned by the
9011 : GDALDataset and should not be deleted by the application.
9012 :
9013 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9014 : consistent with the conventions of C/C++, i.e. starting at 0.
9015 :
9016 : @param iBand a band index between 0 and size()-1.
9017 :
9018 : @return the band, or nullptr if iBand is out of range or an error occurs.
9019 :
9020 : @since GDAL 2.3
9021 : */
9022 :
9023 1 : GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)
9024 : {
9025 1 : return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
9026 : }
9027 :
9028 : /************************************************************************/
9029 : /* GetRootGroup() */
9030 : /************************************************************************/
9031 :
9032 : /**
9033 : \brief Return the root GDALGroup of this dataset.
9034 :
9035 : Only valid for multidimensional datasets.
9036 :
9037 : This is the same as the C function GDALDatasetGetRootGroup().
9038 :
9039 : @since GDAL 3.1
9040 : */
9041 :
9042 2587 : std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
9043 : {
9044 2587 : return nullptr;
9045 : }
9046 :
9047 : /************************************************************************/
9048 : /* GetRawBinaryLayout() */
9049 : /************************************************************************/
9050 :
9051 : //! @cond Doxygen_Suppress
9052 : /**
9053 : \brief Return the layout of a dataset that can be considered as a raw binary
9054 : format.
9055 :
9056 : @param sLayout Structure that will be set if the dataset is a raw binary one.
9057 : @return true if the dataset is a raw binary one.
9058 : @since GDAL 3.1
9059 : */
9060 :
9061 0 : bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)
9062 : {
9063 0 : CPL_IGNORE_RET_VAL(sLayout);
9064 0 : return false;
9065 : }
9066 :
9067 : //! @endcond
9068 :
9069 : /************************************************************************/
9070 : /* ClearStatistics() */
9071 : /************************************************************************/
9072 :
9073 : /**
9074 : \brief Clear statistics
9075 :
9076 : Only implemented for now in PAM supported datasets
9077 :
9078 : This is the same as the C function GDALDatasetClearStatistics().
9079 :
9080 : @since GDAL 3.2
9081 : */
9082 :
9083 4 : void GDALDataset::ClearStatistics()
9084 : {
9085 8 : auto poRootGroup = GetRootGroup();
9086 4 : if (poRootGroup)
9087 1 : poRootGroup->ClearStatistics();
9088 4 : }
9089 :
9090 : /************************************************************************/
9091 : /* GDALDatasetClearStatistics() */
9092 : /************************************************************************/
9093 :
9094 : /**
9095 : \brief Clear statistics
9096 :
9097 : This is the same as the C++ method GDALDataset::ClearStatistics().
9098 :
9099 : @since GDAL 3.2
9100 : */
9101 :
9102 2 : void GDALDatasetClearStatistics(GDALDatasetH hDS)
9103 : {
9104 2 : VALIDATE_POINTER0(hDS, __func__);
9105 2 : GDALDataset::FromHandle(hDS)->ClearStatistics();
9106 : }
9107 :
9108 : /************************************************************************/
9109 : /* GetFieldDomainNames() */
9110 : /************************************************************************/
9111 :
9112 : /** Returns a list of the names of all field domains stored in the dataset.
9113 : *
9114 : * @note The default implementation assumes that drivers fully populate
9115 : * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect
9116 : * then a specialized implementation of GetFieldDomainNames() must be
9117 : * implemented.
9118 : *
9119 : * @param papszOptions Driver specific options determining how attributes
9120 : * should be retrieved. Pass nullptr for default behavior.
9121 : *
9122 : * @return list of field domain names
9123 : * @since GDAL 3.5
9124 : */
9125 : std::vector<std::string>
9126 41 : GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const
9127 : {
9128 :
9129 41 : std::vector<std::string> names;
9130 41 : names.reserve(m_oMapFieldDomains.size());
9131 53 : for (const auto &it : m_oMapFieldDomains)
9132 : {
9133 12 : names.emplace_back(it.first);
9134 : }
9135 41 : return names;
9136 : }
9137 :
9138 : /************************************************************************/
9139 : /* GDALDatasetGetFieldDomainNames() */
9140 : /************************************************************************/
9141 :
9142 : /** Returns a list of the names of all field domains stored in the dataset.
9143 : *
9144 : * This is the same as the C++ method GDALDataset::GetFieldDomainNames().
9145 : *
9146 : * @param hDS Dataset handle.
9147 : * @param papszOptions Driver specific options determining how attributes
9148 : * should be retrieved. Pass nullptr for default behavior.
9149 : *
9150 : * @return list of field domain names, to be freed with CSLDestroy()
9151 : * @since GDAL 3.5
9152 : */
9153 33 : char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,
9154 : CSLConstList papszOptions)
9155 : {
9156 33 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9157 : auto names =
9158 66 : GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);
9159 66 : CPLStringList res;
9160 141 : for (const auto &name : names)
9161 : {
9162 108 : res.AddString(name.c_str());
9163 : }
9164 33 : return res.StealList();
9165 : }
9166 :
9167 : /************************************************************************/
9168 : /* GetFieldDomain() */
9169 : /************************************************************************/
9170 :
9171 : /** Get a field domain from its name.
9172 : *
9173 : * @return the field domain, or nullptr if not found.
9174 : * @since GDAL 3.3
9175 : */
9176 291 : const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const
9177 : {
9178 291 : const auto iter = m_oMapFieldDomains.find(name);
9179 291 : if (iter == m_oMapFieldDomains.end())
9180 126 : return nullptr;
9181 165 : return iter->second.get();
9182 : }
9183 :
9184 : /************************************************************************/
9185 : /* GDALDatasetGetFieldDomain() */
9186 : /************************************************************************/
9187 :
9188 : /** Get a field domain from its name.
9189 : *
9190 : * This is the same as the C++ method GDALDataset::GetFieldDomain().
9191 : *
9192 : * @param hDS Dataset handle.
9193 : * @param pszName Name of field domain.
9194 : * @return the field domain (ownership remains to the dataset), or nullptr if
9195 : * not found.
9196 : * @since GDAL 3.3
9197 : */
9198 117 : OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)
9199 : {
9200 117 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9201 117 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9202 117 : return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(
9203 117 : GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
9204 : }
9205 :
9206 : /************************************************************************/
9207 : /* AddFieldDomain() */
9208 : /************************************************************************/
9209 :
9210 : /** Add a field domain to the dataset.
9211 : *
9212 : * Only a few drivers will support this operation, and some of them might only
9213 : * support it only for some types of field domains.
9214 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9215 : * support this operation. A dataset having at least some support for this
9216 : * operation should report the ODsCAddFieldDomain dataset capability.
9217 : *
9218 : * Anticipated failures will not be emitted through the CPLError()
9219 : * infrastructure, but will be reported in the failureReason output parameter.
9220 : *
9221 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9222 : * default implementation of GetFieldDomainNames() to work correctly, or
9223 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9224 : * implemented.
9225 : *
9226 : * @param domain The domain definition.
9227 : * @param failureReason Output parameter. Will contain an error message if
9228 : * an error occurs.
9229 : * @return true in case of success.
9230 : * @since GDAL 3.3
9231 : */
9232 0 : bool GDALDataset::AddFieldDomain(
9233 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9234 : std::string &failureReason)
9235 : {
9236 0 : failureReason = "AddFieldDomain not supported by this driver";
9237 0 : return false;
9238 : }
9239 :
9240 : /************************************************************************/
9241 : /* GDALDatasetAddFieldDomain() */
9242 : /************************************************************************/
9243 :
9244 : /** Add a field domain to the dataset.
9245 : *
9246 : * Only a few drivers will support this operation, and some of them might only
9247 : * support it only for some types of field domains.
9248 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9249 : * support this operation. A dataset having at least some support for this
9250 : * operation should report the ODsCAddFieldDomain dataset capability.
9251 : *
9252 : * Anticipated failures will not be emitted through the CPLError()
9253 : * infrastructure, but will be reported in the ppszFailureReason output
9254 : * parameter.
9255 : *
9256 : * @param hDS Dataset handle.
9257 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9258 : * the passed object is copied.
9259 : * @param ppszFailureReason Output parameter. Will contain an error message if
9260 : * an error occurs (*ppszFailureReason to be freed
9261 : * with CPLFree). May be NULL.
9262 : * @return true in case of success.
9263 : * @since GDAL 3.3
9264 : */
9265 35 : bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,
9266 : char **ppszFailureReason)
9267 : {
9268 35 : VALIDATE_POINTER1(hDS, __func__, false);
9269 35 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9270 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9271 70 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9272 35 : if (poDomain == nullptr)
9273 0 : return false;
9274 35 : std::string failureReason;
9275 70 : const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(
9276 35 : std::move(poDomain), failureReason);
9277 35 : if (ppszFailureReason)
9278 : {
9279 0 : *ppszFailureReason =
9280 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9281 : }
9282 35 : return bRet;
9283 : }
9284 :
9285 : /************************************************************************/
9286 : /* DeleteFieldDomain() */
9287 : /************************************************************************/
9288 :
9289 : /** Removes a field domain from the dataset.
9290 : *
9291 : * Only a few drivers will support this operation.
9292 : *
9293 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9294 : * support this operation. A dataset having at least some support for this
9295 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9296 : *
9297 : * Anticipated failures will not be emitted through the CPLError()
9298 : * infrastructure, but will be reported in the failureReason output parameter.
9299 : *
9300 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9301 : * default implementation of GetFieldDomainNames() to work correctly, or
9302 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9303 : * implemented.
9304 : *
9305 : * @param name The domain name.
9306 : * @param failureReason Output parameter. Will contain an error message if
9307 : * an error occurs.
9308 : * @return true in case of success.
9309 : * @since GDAL 3.5
9310 : */
9311 0 : bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,
9312 : std::string &failureReason)
9313 : {
9314 0 : failureReason = "DeleteFieldDomain not supported by this driver";
9315 0 : return false;
9316 : }
9317 :
9318 : /************************************************************************/
9319 : /* GDALDatasetDeleteFieldDomain() */
9320 : /************************************************************************/
9321 :
9322 : /** Removes a field domain from the dataset.
9323 : *
9324 : * Only a few drivers will support this operation.
9325 : *
9326 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9327 : * support this operation. A dataset having at least some support for this
9328 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9329 : *
9330 : * Anticipated failures will not be emitted through the CPLError()
9331 : * infrastructure, but will be reported in the ppszFailureReason output
9332 : * parameter.
9333 : *
9334 : * @param hDS Dataset handle.
9335 : * @param pszName The domain name.
9336 : * @param ppszFailureReason Output parameter. Will contain an error message if
9337 : * an error occurs (*ppszFailureReason to be freed
9338 : * with CPLFree). May be NULL.
9339 : * @return true in case of success.
9340 : * @since GDAL 3.3
9341 : */
9342 10 : bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,
9343 : char **ppszFailureReason)
9344 : {
9345 10 : VALIDATE_POINTER1(hDS, __func__, false);
9346 10 : VALIDATE_POINTER1(pszName, __func__, false);
9347 10 : std::string failureReason;
9348 : const bool bRet =
9349 10 : GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);
9350 10 : if (ppszFailureReason)
9351 : {
9352 0 : *ppszFailureReason =
9353 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9354 : }
9355 10 : return bRet;
9356 : }
9357 :
9358 : /************************************************************************/
9359 : /* UpdateFieldDomain() */
9360 : /************************************************************************/
9361 :
9362 : /** Updates an existing field domain by replacing its definition.
9363 : *
9364 : * The existing field domain with matching name will be replaced.
9365 : *
9366 : * Only a few drivers will support this operation, and some of them might only
9367 : * support it only for some types of field domains.
9368 : * At the time of writing (GDAL 3.5), only the Memory driver
9369 : * supports this operation. A dataset having at least some support for this
9370 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9371 : *
9372 : * Anticipated failures will not be emitted through the CPLError()
9373 : * infrastructure, but will be reported in the failureReason output parameter.
9374 : *
9375 : * @param domain The domain definition.
9376 : * @param failureReason Output parameter. Will contain an error message if
9377 : * an error occurs.
9378 : * @return true in case of success.
9379 : * @since GDAL 3.5
9380 : */
9381 0 : bool GDALDataset::UpdateFieldDomain(
9382 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9383 : std::string &failureReason)
9384 : {
9385 0 : failureReason = "UpdateFieldDomain not supported by this driver";
9386 0 : return false;
9387 : }
9388 :
9389 : /************************************************************************/
9390 : /* GDALDatasetUpdateFieldDomain() */
9391 : /************************************************************************/
9392 :
9393 : /** Updates an existing field domain by replacing its definition.
9394 : *
9395 : * The existing field domain with matching name will be replaced.
9396 : *
9397 : * Only a few drivers will support this operation, and some of them might only
9398 : * support it only for some types of field domains.
9399 : * At the time of writing (GDAL 3.5), only the Memory driver
9400 : * supports this operation. A dataset having at least some support for this
9401 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9402 : *
9403 : * Anticipated failures will not be emitted through the CPLError()
9404 : * infrastructure, but will be reported in the failureReason output parameter.
9405 : *
9406 : * @param hDS Dataset handle.
9407 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9408 : * the passed object is copied.
9409 : * @param ppszFailureReason Output parameter. Will contain an error message if
9410 : * an error occurs (*ppszFailureReason to be freed
9411 : * with CPLFree). May be NULL.
9412 : * @return true in case of success.
9413 : * @since GDAL 3.5
9414 : */
9415 5 : bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,
9416 : OGRFieldDomainH hFieldDomain,
9417 : char **ppszFailureReason)
9418 : {
9419 5 : VALIDATE_POINTER1(hDS, __func__, false);
9420 5 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9421 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9422 10 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9423 5 : if (poDomain == nullptr)
9424 0 : return false;
9425 5 : std::string failureReason;
9426 10 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(
9427 5 : std::move(poDomain), failureReason);
9428 5 : if (ppszFailureReason)
9429 : {
9430 0 : *ppszFailureReason =
9431 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9432 : }
9433 5 : return bRet;
9434 : }
9435 :
9436 : /************************************************************************/
9437 : /* GetRelationshipNames() */
9438 : /************************************************************************/
9439 :
9440 : /** Returns a list of the names of all relationships stored in the dataset.
9441 : *
9442 : * @param papszOptions Driver specific options determining how relationships
9443 : * should be retrieved. Pass nullptr for default behavior.
9444 : *
9445 : * @return list of relationship names
9446 : * @since GDAL 3.6
9447 : */
9448 : std::vector<std::string>
9449 136 : GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const
9450 : {
9451 136 : return {};
9452 : }
9453 :
9454 : /************************************************************************/
9455 : /* GDALDatasetGetRelationshipNames() */
9456 : /************************************************************************/
9457 :
9458 : /** Returns a list of the names of all relationships stored in the dataset.
9459 : *
9460 : * This is the same as the C++ method GDALDataset::GetRelationshipNames().
9461 : *
9462 : * @param hDS Dataset handle.
9463 : * @param papszOptions Driver specific options determining how relationships
9464 : * should be retrieved. Pass nullptr for default behavior.
9465 : *
9466 : * @return list of relationship names, to be freed with CSLDestroy()
9467 : * @since GDAL 3.6
9468 : */
9469 46 : char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,
9470 : CSLConstList papszOptions)
9471 : {
9472 46 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9473 : auto names =
9474 92 : GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);
9475 92 : CPLStringList res;
9476 146 : for (const auto &name : names)
9477 : {
9478 100 : res.AddString(name.c_str());
9479 : }
9480 46 : return res.StealList();
9481 : }
9482 :
9483 : /************************************************************************/
9484 : /* GetRelationship() */
9485 : /************************************************************************/
9486 :
9487 : /** Get a relationship from its name.
9488 : *
9489 : * @return the relationship, or nullptr if not found.
9490 : * @since GDAL 3.6
9491 : */
9492 : const GDALRelationship *
9493 0 : GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const
9494 : {
9495 0 : return nullptr;
9496 : }
9497 :
9498 : /************************************************************************/
9499 : /* GDALDatasetGetRelationship() */
9500 : /************************************************************************/
9501 :
9502 : /** Get a relationship from its name.
9503 : *
9504 : * This is the same as the C++ method GDALDataset::GetRelationship().
9505 : *
9506 : * @param hDS Dataset handle.
9507 : * @param pszName Name of relationship.
9508 : * @return the relationship (ownership remains to the dataset), or nullptr if
9509 : * not found.
9510 : * @since GDAL 3.6
9511 : */
9512 52 : GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,
9513 : const char *pszName)
9514 : {
9515 52 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9516 52 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9517 52 : return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(
9518 52 : GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));
9519 : }
9520 :
9521 : /************************************************************************/
9522 : /* AddRelationship() */
9523 : /************************************************************************/
9524 :
9525 : /** Add a relationship to the dataset.
9526 : *
9527 : * Only a few drivers will support this operation, and some of them might only
9528 : * support it only for some types of relationships.
9529 : *
9530 : * A dataset having at least some support for this
9531 : * operation should report the GDsCAddRelationship dataset capability.
9532 : *
9533 : * Anticipated failures will not be emitted through the CPLError()
9534 : * infrastructure, but will be reported in the failureReason output parameter.
9535 : *
9536 : * When adding a many-to-many relationship
9537 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9538 : * mapping table name (see GDALRelationship::GetMappingTableName) to instruct
9539 : * the driver to create an appropriately named and structured mapping table.
9540 : * Some dataset formats require particular naming conventions and field
9541 : * structures for the mapping table, and delegating the construction of the
9542 : * mapping table to the driver will avoid these pitfalls.
9543 : *
9544 : * @param relationship The relationship definition.
9545 : * @param failureReason Output parameter. Will contain an error message if
9546 : * an error occurs.
9547 : * @return true in case of success.
9548 : * @since GDAL 3.6
9549 : */
9550 0 : bool GDALDataset::AddRelationship(
9551 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9552 : std::string &failureReason)
9553 : {
9554 0 : failureReason = "AddRelationship not supported by this driver";
9555 0 : return false;
9556 : }
9557 :
9558 : /************************************************************************/
9559 : /* GDALDatasetAddRelationship() */
9560 : /************************************************************************/
9561 :
9562 : /** Add a relationship to the dataset.
9563 : *
9564 : * Only a few drivers will support this operation, and some of them might only
9565 : * support it only for some types of relationships.
9566 : *
9567 : * A dataset having at least some support for this
9568 : * operation should report the GDsCAddRelationship dataset capability.
9569 : *
9570 : * Anticipated failures will not be emitted through the CPLError()
9571 : * infrastructure, but will be reported in the failureReason output parameter.
9572 : *
9573 : * When adding a many-to-many relationship
9574 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9575 : * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the
9576 : * driver to create an appropriately named and structured mapping table. Some
9577 : * dataset formats require particular naming conventions and field structures
9578 : * for the mapping table, and delegating the construction of the mapping table
9579 : * to the driver will avoid these pitfalls.
9580 : *
9581 : * @param hDS Dataset handle.
9582 : * @param hRelationship The relationship definition. Contrary to the C++
9583 : * version, the passed object is copied.
9584 : * @param ppszFailureReason Output parameter. Will contain an error message if
9585 : * an error occurs (*ppszFailureReason to be freed
9586 : * with CPLFree). May be NULL.
9587 : * @return true in case of success.
9588 : * @since GDAL 3.6
9589 : */
9590 42 : bool GDALDatasetAddRelationship(GDALDatasetH hDS,
9591 : GDALRelationshipH hRelationship,
9592 : char **ppszFailureReason)
9593 : {
9594 42 : VALIDATE_POINTER1(hDS, __func__, false);
9595 42 : VALIDATE_POINTER1(hRelationship, __func__, false);
9596 : std::unique_ptr<GDALRelationship> poRelationship(
9597 84 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9598 42 : std::string failureReason;
9599 84 : const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(
9600 42 : std::move(poRelationship), failureReason);
9601 42 : if (ppszFailureReason)
9602 : {
9603 0 : *ppszFailureReason =
9604 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9605 : }
9606 42 : return bRet;
9607 : }
9608 :
9609 : /************************************************************************/
9610 : /* DeleteRelationship() */
9611 : /************************************************************************/
9612 :
9613 : /** Removes a relationship from the dataset.
9614 : *
9615 : * Only a few drivers will support this operation.
9616 : *
9617 : * A dataset having at least some support for this
9618 : * operation should report the GDsCDeleteRelationship dataset capability.
9619 : *
9620 : * Anticipated failures will not be emitted through the CPLError()
9621 : * infrastructure, but will be reported in the failureReason output parameter.
9622 : *
9623 : * @param name The relationship name.
9624 : * @param failureReason Output parameter. Will contain an error message if
9625 : * an error occurs.
9626 : * @return true in case of success.
9627 : * @since GDAL 3.6
9628 : */
9629 0 : bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,
9630 : std::string &failureReason)
9631 : {
9632 0 : failureReason = "DeleteRelationship not supported by this driver";
9633 0 : return false;
9634 : }
9635 :
9636 : /************************************************************************/
9637 : /* GDALDatasetDeleteRelationship() */
9638 : /************************************************************************/
9639 :
9640 : /** Removes a relationship from the dataset.
9641 : *
9642 : * Only a few drivers will support this operation.
9643 : *
9644 : * A dataset having at least some support for this
9645 : * operation should report the GDsCDeleteRelationship dataset capability.
9646 : *
9647 : * Anticipated failures will not be emitted through the CPLError()
9648 : * infrastructure, but will be reported in the ppszFailureReason output
9649 : * parameter.
9650 : *
9651 : * @param hDS Dataset handle.
9652 : * @param pszName The relationship name.
9653 : * @param ppszFailureReason Output parameter. Will contain an error message if
9654 : * an error occurs (*ppszFailureReason to be freed
9655 : * with CPLFree). May be NULL.
9656 : * @return true in case of success.
9657 : * @since GDAL 3.6
9658 : */
9659 6 : bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,
9660 : char **ppszFailureReason)
9661 : {
9662 6 : VALIDATE_POINTER1(hDS, __func__, false);
9663 6 : VALIDATE_POINTER1(pszName, __func__, false);
9664 6 : std::string failureReason;
9665 12 : const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(
9666 6 : pszName, failureReason);
9667 6 : if (ppszFailureReason)
9668 : {
9669 0 : *ppszFailureReason =
9670 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9671 : }
9672 6 : return bRet;
9673 : }
9674 :
9675 : /************************************************************************/
9676 : /* UpdateRelationship() */
9677 : /************************************************************************/
9678 :
9679 : /** Updates an existing relationship by replacing its definition.
9680 : *
9681 : * The existing relationship with matching name will be replaced.
9682 : *
9683 : * Only a few drivers will support this operation, and some of them might only
9684 : * support it only for some types of relationships.
9685 : * A dataset having at least some support for this
9686 : * operation should report the GDsCUpdateRelationship dataset capability.
9687 : *
9688 : * Anticipated failures will not be emitted through the CPLError()
9689 : * infrastructure, but will be reported in the failureReason output parameter.
9690 : *
9691 : * @param relationship The relationship definition.
9692 : * @param failureReason Output parameter. Will contain an error message if
9693 : * an error occurs.
9694 : * @return true in case of success.
9695 : * @since GDAL 3.6
9696 : */
9697 0 : bool GDALDataset::UpdateRelationship(
9698 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9699 : std::string &failureReason)
9700 : {
9701 0 : failureReason = "UpdateRelationship not supported by this driver";
9702 0 : return false;
9703 : }
9704 :
9705 : /************************************************************************/
9706 : /* GDALDatasetUpdateRelationship() */
9707 : /************************************************************************/
9708 :
9709 : /** Updates an existing relationship by replacing its definition.
9710 : *
9711 : * The existing relationship with matching name will be replaced.
9712 : *
9713 : * Only a few drivers will support this operation, and some of them might only
9714 : * support it only for some types of relationships.
9715 : * A dataset having at least some support for this
9716 : * operation should report the GDsCUpdateRelationship dataset capability.
9717 : *
9718 : * Anticipated failures will not be emitted through the CPLError()
9719 : * infrastructure, but will be reported in the failureReason output parameter.
9720 : *
9721 : * @param hDS Dataset handle.
9722 : * @param hRelationship The relationship definition. Contrary to the C++
9723 : * version, the passed object is copied.
9724 : * @param ppszFailureReason Output parameter. Will contain an error message if
9725 : * an error occurs (*ppszFailureReason to be freed
9726 : * with CPLFree). May be NULL.
9727 : * @return true in case of success.
9728 : * @since GDAL 3.5
9729 : */
9730 9 : bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,
9731 : GDALRelationshipH hRelationship,
9732 : char **ppszFailureReason)
9733 : {
9734 9 : VALIDATE_POINTER1(hDS, __func__, false);
9735 9 : VALIDATE_POINTER1(hRelationship, __func__, false);
9736 : std::unique_ptr<GDALRelationship> poRelationship(
9737 18 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9738 9 : std::string failureReason;
9739 18 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(
9740 9 : std::move(poRelationship), failureReason);
9741 9 : if (ppszFailureReason)
9742 : {
9743 0 : *ppszFailureReason =
9744 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9745 : }
9746 9 : return bRet;
9747 : }
9748 :
9749 : /************************************************************************/
9750 : /* GDALDatasetSetQueryLoggerFunc() */
9751 : /************************************************************************/
9752 :
9753 : /**
9754 : * Sets the SQL query logger callback.
9755 : *
9756 : * When supported by the driver, the callback will be called with
9757 : * the executed SQL text, the error message, the execution time in milliseconds,
9758 : * the number of records fetched/affected and the client status data.
9759 : *
9760 : * A value of -1 in the execution time or in the number of records indicates
9761 : * that the values are unknown.
9762 : *
9763 : * @param hDS Dataset handle.
9764 : * @param pfnQueryLoggerFunc Callback function
9765 : * @param poQueryLoggerArg Opaque client status data
9766 : * @return true in case of success.
9767 : * @since GDAL 3.7
9768 : */
9769 1 : bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,
9770 : GDALQueryLoggerFunc pfnQueryLoggerFunc,
9771 : void *poQueryLoggerArg)
9772 : {
9773 1 : VALIDATE_POINTER1(hDS, __func__, false);
9774 2 : return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,
9775 1 : poQueryLoggerArg);
9776 : }
9777 :
9778 : //! @cond Doxygen_Suppress
9779 :
9780 : /************************************************************************/
9781 : /* SetEnableOverviews() */
9782 : /************************************************************************/
9783 :
9784 7373 : void GDALDataset::SetEnableOverviews(bool bEnable)
9785 : {
9786 7373 : if (m_poPrivate)
9787 : {
9788 7373 : m_poPrivate->m_bOverviewsEnabled = bEnable;
9789 : }
9790 7373 : }
9791 :
9792 : /************************************************************************/
9793 : /* AreOverviewsEnabled() */
9794 : /************************************************************************/
9795 :
9796 1339780 : bool GDALDataset::AreOverviewsEnabled() const
9797 : {
9798 1339780 : return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
9799 : }
9800 :
9801 : /************************************************************************/
9802 : /* IsAllBands() */
9803 : /************************************************************************/
9804 :
9805 67 : bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const
9806 : {
9807 67 : if (nBands != nBandCount)
9808 1 : return false;
9809 66 : if (panBandList)
9810 : {
9811 3 : for (int i = 0; i < nBandCount; ++i)
9812 : {
9813 2 : if (panBandList[i] != i + 1)
9814 1 : return false;
9815 : }
9816 : }
9817 65 : return true;
9818 : }
9819 :
9820 : //! @endcond
9821 :
9822 : /************************************************************************/
9823 : /* GetCompressionFormats() */
9824 : /************************************************************************/
9825 :
9826 : /** Return the compression formats that can be natively obtained for the
9827 : * window of interest and requested bands.
9828 : *
9829 : * For example, a tiled dataset may be able to return data in a compressed
9830 : * format if the window of interest matches exactly a tile. For some formats,
9831 : * drivers may also be able to merge several tiles together (not currently
9832 : * implemented though).
9833 : *
9834 : * Each format string is a pseudo MIME type, whose first part can be passed
9835 : * as the pszFormat argument of ReadCompressedData(), with additional
9836 : * parameters specified as key=value with a semi-colon separator.
9837 : *
9838 : * The amount and types of optional parameters passed after the MIME type is
9839 : * format dependent, and driver dependent (some drivers might not be able to
9840 : * return those extra information without doing a rather costly processing).
9841 : *
9842 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9843 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9844 : * consequently "JPEG" can be passed as the pszFormat argument of
9845 : * ReadCompressedData(). For JPEG, implementations can use the
9846 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9847 : * above from a JPEG codestream.
9848 : *
9849 : * Several values might be returned. For example,
9850 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9851 : * if the JPEGXL codestream includes a JPEG reconstruction box.
9852 : *
9853 : * In the general case this method will return an empty list.
9854 : *
9855 : * This is the same as C function GDALDatasetGetCompressionFormats().
9856 : *
9857 : * @param nXOff The pixel offset to the top left corner of the region
9858 : * of the band to be accessed. This would be zero to start from the left side.
9859 : *
9860 : * @param nYOff The line offset to the top left corner of the region
9861 : * of the band to be accessed. This would be zero to start from the top.
9862 : *
9863 : * @param nXSize The width of the region of the band to be accessed in pixels.
9864 : *
9865 : * @param nYSize The height of the region of the band to be accessed in lines.
9866 : *
9867 : * @param nBandCount the number of bands being requested.
9868 : *
9869 : * @param panBandList the list of nBandCount band numbers.
9870 : * Note band numbers are 1 based. This may be NULL to select the first
9871 : * nBandCount bands.
9872 : *
9873 : * @return a list of compatible formats (which may be empty)
9874 : *
9875 : * For example, to check if native compression format(s) are available on the
9876 : * whole image:
9877 : * \code{.cpp}
9878 : * const CPLStringList aosFormats =
9879 : * poDataset->GetCompressionFormats(0, 0,
9880 : * poDataset->GetRasterXSize(),
9881 : * poDataset->GetRasterYSize(),
9882 : * poDataset->GetRasterCount(),
9883 : * nullptr);
9884 : * for( const char* pszFormat: aosFormats )
9885 : * {
9886 : * // Remove optional parameters and just print out the MIME type.
9887 : * const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));
9888 : * printf("Found format %s\n, aosTokens[0]);
9889 : * }
9890 : * \endcode
9891 : *
9892 : * @since GDAL 3.7
9893 : */
9894 : CPLStringList
9895 0 : GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
9896 : CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
9897 : CPL_UNUSED int nBandCount,
9898 : CPL_UNUSED const int *panBandList)
9899 : {
9900 0 : return CPLStringList();
9901 : }
9902 :
9903 : /************************************************************************/
9904 : /* GDALDatasetGetCompressionFormats() */
9905 : /************************************************************************/
9906 :
9907 : /** Return the compression formats that can be natively obtained for the
9908 : * window of interest and requested bands.
9909 : *
9910 : * For example, a tiled dataset may be able to return data in a compressed
9911 : * format if the window of interest matches exactly a tile. For some formats,
9912 : * drivers may also be able to merge several tiles together (not currently
9913 : * implemented though).
9914 : *
9915 : * Each format string is a pseudo MIME type, whose first part can be passed
9916 : * as the pszFormat argument of ReadCompressedData(), with additional
9917 : * parameters specified as key=value with a semi-colon separator.
9918 : *
9919 : * The amount and types of optional parameters passed after the MIME type is
9920 : * format dependent, and driver dependent (some drivers might not be able to
9921 : * return those extra information without doing a rather costly processing).
9922 : *
9923 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9924 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9925 : * consequently "JPEG" can be passed as the pszFormat argument of
9926 : * ReadCompressedData(). For JPEG, implementations can use the
9927 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9928 : * above from a JPEG codestream.
9929 : *
9930 : * Several values might be returned. For example,
9931 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9932 : * if the JPEGXL codestream includes a JPEG reconstruction box.
9933 : *
9934 : * In the general case this method will return an empty list.
9935 : *
9936 : * This is the same as C++ method GDALDataset::GetCompressionFormats().
9937 : *
9938 : * @param hDS Dataset handle.
9939 : *
9940 : * @param nXOff The pixel offset to the top left corner of the region
9941 : * of the band to be accessed. This would be zero to start from the left side.
9942 : *
9943 : * @param nYOff The line offset to the top left corner of the region
9944 : * of the band to be accessed. This would be zero to start from the top.
9945 : *
9946 : * @param nXSize The width of the region of the band to be accessed in pixels.
9947 : *
9948 : * @param nYSize The height of the region of the band to be accessed in lines.
9949 : *
9950 : * @param nBandCount the number of bands being requested.
9951 : *
9952 : * @param panBandList the list of nBandCount band numbers.
9953 : * Note band numbers are 1 based. This may be NULL to select the first
9954 : * nBandCount bands.
9955 : *
9956 : * @return a list of compatible formats (which may be empty) that should be
9957 : * freed with CSLDestroy(), or nullptr.
9958 : *
9959 : * @since GDAL 3.7
9960 : */
9961 9 : char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,
9962 : int nXSize, int nYSize, int nBandCount,
9963 : const int *panBandList)
9964 : {
9965 9 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9966 9 : return GDALDataset::FromHandle(hDS)
9967 9 : ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,
9968 9 : panBandList)
9969 9 : .StealList();
9970 : }
9971 :
9972 : /************************************************************************/
9973 : /* ReadCompressedData() */
9974 : /************************************************************************/
9975 :
9976 : /** Return the compressed content that can be natively obtained for the
9977 : * window of interest and requested bands.
9978 : *
9979 : * For example, a tiled dataset may be able to return data in compressed format
9980 : * if the window of interest matches exactly a tile. For some formats, drivers
9981 : * may also be example to merge several tiles together (not currently
9982 : * implemented though).
9983 : *
9984 : * The implementation should make sure that the content returned forms a valid
9985 : * standalone file. For example, for the GeoTIFF implementation of this method,
9986 : * when extracting a JPEG tile, the method will automatically add the content
9987 : * of the JPEG Huffman and/or quantization tables that might be stored in the
9988 : * TIFF JpegTables tag, and not in tile data itself.
9989 : *
9990 : * In the general case this method will return CE_Failure.
9991 : *
9992 : * This is the same as C function GDALDatasetReadCompressedData().
9993 : *
9994 : * @param pszFormat Requested compression format (e.g. "JPEG",
9995 : * "WEBP", "JXL"). This is the MIME type of one of the values
9996 : * returned by GetCompressionFormats(). The format string is designed to
9997 : * potentially include at a later point key=value optional parameters separated
9998 : * by a semi-colon character. At time of writing, none are implemented.
9999 : * ReadCompressedData() implementations should verify optional parameters and
10000 : * return CE_Failure if they cannot support one of them.
10001 : *
10002 : * @param nXOff The pixel offset to the top left corner of the region
10003 : * of the band to be accessed. This would be zero to start from the left side.
10004 : *
10005 : * @param nYOff The line offset to the top left corner of the region
10006 : * of the band to be accessed. This would be zero to start from the top.
10007 : *
10008 : * @param nXSize The width of the region of the band to be accessed in pixels.
10009 : *
10010 : * @param nYSize The height of the region of the band to be accessed in lines.
10011 : *
10012 : * @param nBandCount the number of bands being requested.
10013 : *
10014 : * @param panBandList the list of nBandCount band numbers.
10015 : * Note band numbers are 1 based. This may be NULL to select the first
10016 : * nBandCount bands.
10017 : *
10018 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10019 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10020 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10021 : * buffer will be filled with the compressed data, provided that pnBufferSize
10022 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10023 : * of *ppBuffer, is sufficiently large to hold the data.
10024 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10025 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10026 : * free it with VSIFree().
10027 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10028 : * but *pnBufferSize will be updated with an upper bound of the size that would
10029 : * be necessary to hold it (if pnBufferSize != nullptr).
10030 : *
10031 : * @param pnBufferSize Output buffer size, or nullptr.
10032 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10033 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10034 : * method is successful, *pnBufferSize will be updated with the actual size
10035 : * used.
10036 : *
10037 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10038 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10039 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10040 : * *ppszDetailedFormat might contain strings like
10041 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10042 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10043 : * The string will contain at least as much information as what
10044 : * GetCompressionFormats() returns, and potentially more when
10045 : * ppBuffer != nullptr.
10046 : *
10047 : * @return CE_None in case of success, CE_Failure otherwise.
10048 : *
10049 : * For example, to request JPEG content on the whole image and let GDAL deal
10050 : * with the buffer allocation.
10051 : * \code{.cpp}
10052 : * void* pBuffer = nullptr;
10053 : * size_t nBufferSize = 0;
10054 : * CPLErr eErr =
10055 : * poDataset->ReadCompressedData("JPEG",
10056 : * 0, 0,
10057 : * poDataset->GetRasterXSize(),
10058 : * poDataset->GetRasterYSize(),
10059 : * poDataset->GetRasterCount(),
10060 : * nullptr, // panBandList
10061 : * &pBuffer,
10062 : * &nBufferSize,
10063 : * nullptr // ppszDetailedFormat
10064 : * );
10065 : * if (eErr == CE_None)
10066 : * {
10067 : * CPLAssert(pBuffer != nullptr);
10068 : * CPLAssert(nBufferSize > 0);
10069 : * VSILFILE* fp = VSIFOpenL("my.jpeg", "wb");
10070 : * if (fp)
10071 : * {
10072 : * VSIFWriteL(pBuffer, nBufferSize, 1, fp);
10073 : * VSIFCloseL(fp);
10074 : * }
10075 : * VSIFree(pBuffer);
10076 : * }
10077 : * \endcode
10078 : *
10079 : * Or to manage the buffer allocation on your side:
10080 : * \code{.cpp}
10081 : * size_t nUpperBoundBufferSize = 0;
10082 : * CPLErr eErr =
10083 : * poDataset->ReadCompressedData("JPEG",
10084 : * 0, 0,
10085 : * poDataset->GetRasterXSize(),
10086 : * poDataset->GetRasterYSize(),
10087 : * poDataset->GetRasterCount(),
10088 : * nullptr, // panBandList
10089 : * nullptr, // ppBuffer,
10090 : * &nUpperBoundBufferSize,
10091 : * nullptr // ppszDetailedFormat
10092 : * );
10093 : * if (eErr == CE_None)
10094 : * {
10095 : * std::vector<uint8_t> myBuffer;
10096 : * myBuffer.resize(nUpperBoundBufferSize);
10097 : * void* pBuffer = myBuffer.data();
10098 : * size_t nActualSize = nUpperBoundBufferSize;
10099 : * char* pszDetailedFormat = nullptr;
10100 : * // We also request detailed format, but we could have passed it to
10101 : * // nullptr as well.
10102 : * eErr =
10103 : * poDataset->ReadCompressedData("JPEG",
10104 : * 0, 0,
10105 : * poDataset->GetRasterXSize(),
10106 : * poDataset->GetRasterYSize(),
10107 : * poDataset->GetRasterCount(),
10108 : * nullptr, // panBandList
10109 : * &pBuffer,
10110 : * &nActualSize,
10111 : * &pszDetailedFormat);
10112 : * if (eErr == CE_None)
10113 : * {
10114 : * CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified
10115 : * CPLAssert(nActualSize <= nUpperBoundBufferSize);
10116 : * myBuffer.resize(nActualSize);
10117 : * // do something useful
10118 : * VSIFree(pszDetailedFormat);
10119 : * }
10120 : * }
10121 : * \endcode
10122 : *
10123 : * @since GDAL 3.7
10124 : */
10125 418 : CPLErr GDALDataset::ReadCompressedData(
10126 : CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,
10127 : CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10128 : CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,
10129 : CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,
10130 : CPL_UNUSED char **ppszDetailedFormat)
10131 : {
10132 418 : return CE_Failure;
10133 : }
10134 :
10135 : /************************************************************************/
10136 : /* GDALDatasetReadCompressedData() */
10137 : /************************************************************************/
10138 :
10139 : /** Return the compressed content that can be natively obtained for the
10140 : * window of interest and requested bands.
10141 : *
10142 : * For example, a tiled dataset may be able to return data in compressed format
10143 : * if the window of interest matches exactly a tile. For some formats, drivers
10144 : * may also be example to merge several tiles together (not currently
10145 : * implemented though).
10146 : *
10147 : * The implementation should make sure that the content returned forms a valid
10148 : * standalone file. For example, for the GeoTIFF implementation of this method,
10149 : * when extracting a JPEG tile, the method will automatically adds the content
10150 : * of the JPEG Huffman and/or quantization tables that might be stored in the
10151 : * TIFF JpegTables tag, and not in tile data itself.
10152 : *
10153 : * In the general case this method will return CE_Failure.
10154 : *
10155 : * This is the same as C++ method GDALDataset:ReadCompressedData().
10156 : *
10157 : * @param hDS Dataset handle.
10158 : *
10159 : * @param pszFormat Requested compression format (e.g. "JPEG",
10160 : * "WEBP", "JXL"). This is the MIME type of one of the values
10161 : * returned by GetCompressionFormats(). The format string is designed to
10162 : * potentially include at a later point key=value optional parameters separated
10163 : * by a semi-colon character. At time of writing, none are implemented.
10164 : * ReadCompressedData() implementations should verify optional parameters and
10165 : * return CE_Failure if they cannot support one of them.
10166 : *
10167 : * @param nXOff The pixel offset to the top left corner of the region
10168 : * of the band to be accessed. This would be zero to start from the left side.
10169 : *
10170 : * @param nYOff The line offset to the top left corner of the region
10171 : * of the band to be accessed. This would be zero to start from the top.
10172 : *
10173 : * @param nXSize The width of the region of the band to be accessed in pixels.
10174 : *
10175 : * @param nYSize The height of the region of the band to be accessed in lines.
10176 : *
10177 : * @param nBandCount the number of bands being requested.
10178 : *
10179 : * @param panBandList the list of nBandCount band numbers.
10180 : * Note band numbers are 1 based. This may be NULL to select the first
10181 : * nBandCount bands.
10182 : *
10183 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10184 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10185 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10186 : * buffer will be filled with the compressed data, provided that pnBufferSize
10187 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10188 : * of *ppBuffer, is sufficiently large to hold the data.
10189 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10190 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10191 : * free it with VSIFree().
10192 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10193 : * but *pnBufferSize will be updated with an upper bound of the size that would
10194 : * be necessary to hold it (if pnBufferSize != nullptr).
10195 : *
10196 : * @param pnBufferSize Output buffer size, or nullptr.
10197 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10198 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10199 : * method is successful, *pnBufferSize will be updated with the actual size
10200 : * used.
10201 : *
10202 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10203 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10204 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10205 : * *ppszDetailedFormat might contain strings like
10206 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10207 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10208 : * The string will contain at least as much information as what
10209 : * GetCompressionFormats() returns, and potentially more when
10210 : * ppBuffer != nullptr.
10211 : *
10212 : * @return CE_None in case of success, CE_Failure otherwise.
10213 : *
10214 : * @since GDAL 3.7
10215 : */
10216 28 : CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,
10217 : int nXOff, int nYOff, int nXSize,
10218 : int nYSize, int nBandCount,
10219 : const int *panBandList, void **ppBuffer,
10220 : size_t *pnBufferSize,
10221 : char **ppszDetailedFormat)
10222 : {
10223 28 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10224 56 : return GDALDataset::FromHandle(hDS)->ReadCompressedData(
10225 : pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,
10226 28 : ppBuffer, pnBufferSize, ppszDetailedFormat);
10227 : }
10228 :
10229 : /************************************************************************/
10230 : /* CanBeCloned() */
10231 : /************************************************************************/
10232 :
10233 : //! @cond Doxygen_Suppress
10234 :
10235 : /** This method is called by GDALThreadSafeDataset::Create() to determine if
10236 : * it is possible to create a thread-safe wrapper for a dataset, which involves
10237 : * the ability to Clone() it.
10238 : *
10239 : * Implementations of this method must be thread-safe.
10240 : *
10241 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10242 : * expressing the intended use for thread-safety.
10243 : * Currently, the only valid scope is in the base
10244 : * implementation is GDAL_OF_RASTER.
10245 : * @param bCanShareState Determines if cloned datasets are allowed to share
10246 : * state with the dataset they have been cloned from.
10247 : * If set to true, the dataset from which they have been
10248 : * cloned from must remain opened during the lifetime of
10249 : * its clones.
10250 : * @return true if the Clone() method is expected to succeed with the same values
10251 : * of nScopeFlags and bCanShareState.
10252 : */
10253 125 : bool GDALDataset::CanBeCloned(int nScopeFlags,
10254 : [[maybe_unused]] bool bCanShareState) const
10255 : {
10256 125 : return m_bCanBeReopened && nScopeFlags == GDAL_OF_RASTER;
10257 : }
10258 :
10259 : //! @endcond
10260 :
10261 : /************************************************************************/
10262 : /* Clone() */
10263 : /************************************************************************/
10264 :
10265 : //! @cond Doxygen_Suppress
10266 :
10267 : /** This method "clones" the current dataset, that is it returns a new instance
10268 : * that is opened on the same underlying "file".
10269 : *
10270 : * The base implementation uses GDALDataset::Open() to re-open the dataset.
10271 : * The MEM driver has a specialized implementation that returns a new instance,
10272 : * but which shares the same memory buffer as this.
10273 : *
10274 : * Implementations of this method must be thread-safe.
10275 : *
10276 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10277 : * expressing the intended use for thread-safety.
10278 : * Currently, the only valid scope is in the base
10279 : * implementation is GDAL_OF_RASTER.
10280 : * @param bCanShareState Determines if cloned datasets are allowed to share
10281 : * state with the dataset they have been cloned from.
10282 : * If set to true, the dataset from which they have been
10283 : * cloned from must remain opened during the lifetime of
10284 : * its clones.
10285 : * @return a new instance, or nullptr in case of error.
10286 : */
10287 : std::unique_ptr<GDALDataset>
10288 2027 : GDALDataset::Clone(int nScopeFlags, [[maybe_unused]] bool bCanShareState) const
10289 : {
10290 4018 : CPLStringList aosAllowedDrivers;
10291 2027 : if (poDriver)
10292 2027 : aosAllowedDrivers.AddString(poDriver->GetDescription());
10293 : return std::unique_ptr<GDALDataset>(GDALDataset::Open(
10294 2025 : GetDescription(),
10295 2025 : nScopeFlags | GDAL_OF_INTERNAL | GDAL_OF_VERBOSE_ERROR,
10296 4028 : aosAllowedDrivers.List(), papszOpenOptions));
10297 : }
10298 :
10299 : //! @endcond
10300 :
10301 : /************************************************************************/
10302 : /* GeolocationToPixelLine() */
10303 : /************************************************************************/
10304 :
10305 : /** Transform georeferenced coordinates to pixel/line coordinates.
10306 : *
10307 : * When poSRS is null, those georeferenced coordinates (dfGeolocX, dfGeolocY)
10308 : * must be in the "natural" SRS of the dataset, that is the one returned by
10309 : * GetSpatialRef() if there is a geotransform, GetGCPSpatialRef() if there are
10310 : * GCPs, WGS 84 if there are RPC coefficients, or the SRS of the geolocation
10311 : * array (generally WGS 84) if there is a geolocation array.
10312 : * If that natural SRS is a geographic one, dfGeolocX must be a longitude, and
10313 : * dfGeolocY a latitude. If that natural SRS is a projected one, dfGeolocX must
10314 : * be a easting, and dfGeolocY a northing.
10315 : *
10316 : * When poSRS is set to a non-null value, (dfGeolocX, dfGeolocY) must be
10317 : * expressed in that CRS, and that tuple must be conformant with the
10318 : * data-axis-to-crs-axis setting of poSRS, that is the one returned by
10319 : * the OGRSpatialReference::GetDataAxisToSRSAxisMapping(). If you want to be sure
10320 : * of the axis order, then make sure to call poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER)
10321 : * before calling this method, and in that case, dfGeolocX must be a longitude
10322 : * or an easting value, and dfGeolocX a latitude or a northing value.
10323 : *
10324 : * This method uses GDALCreateGenImgProjTransformer2() underneath.
10325 : *
10326 : * @param dfGeolocX X coordinate of the position (longitude or easting if poSRS
10327 : * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10328 : * where interpolation should be done.
10329 : * @param dfGeolocY Y coordinate of the position (latitude or northing if poSRS
10330 : * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10331 : * where interpolation should be done.
10332 : * @param poSRS If set, override the natural CRS in which dfGeolocX, dfGeolocY are expressed
10333 : * @param[out] pdfPixel Pointer to the variable where to the store the pixel/column coordinate.
10334 : * @param[out] pdfLine Pointer to the variable where to the store the line coordinate.
10335 : * @param papszTransformerOptions Options accepted by GDALCreateGenImgProjTransformer2(), or nullptr.
10336 : *
10337 : * @return CE_None on success, or an error code on failure.
10338 : * @since GDAL 3.11
10339 : */
10340 :
10341 : CPLErr
10342 10 : GDALDataset::GeolocationToPixelLine(double dfGeolocX, double dfGeolocY,
10343 : const OGRSpatialReference *poSRS,
10344 : double *pdfPixel, double *pdfLine,
10345 : CSLConstList papszTransformerOptions) const
10346 : {
10347 20 : CPLStringList aosTO(papszTransformerOptions);
10348 :
10349 10 : if (poSRS)
10350 : {
10351 4 : const char *const apszOptions[] = {"FORMAT=WKT2", nullptr};
10352 8 : const std::string osWKT = poSRS->exportToWkt(apszOptions);
10353 4 : aosTO.SetNameValue("DST_SRS", osWKT.c_str());
10354 4 : const auto eAxisMappingStrategy = poSRS->GetAxisMappingStrategy();
10355 4 : if (eAxisMappingStrategy == OAMS_TRADITIONAL_GIS_ORDER)
10356 : aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10357 1 : "TRADITIONAL_GIS_ORDER");
10358 3 : else if (eAxisMappingStrategy == OAMS_AUTHORITY_COMPLIANT)
10359 : aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10360 1 : "AUTHORITY_COMPLIANT");
10361 : else
10362 : {
10363 2 : const auto &anValues = poSRS->GetDataAxisToSRSAxisMapping();
10364 4 : std::string osVal;
10365 6 : for (int v : anValues)
10366 : {
10367 4 : if (!osVal.empty())
10368 2 : osVal += ',';
10369 4 : osVal += std::to_string(v);
10370 : }
10371 : aosTO.SetNameValue("DST_SRS_DATA_AXIS_TO_SRS_AXIS_MAPPING",
10372 2 : osVal.c_str());
10373 : }
10374 : }
10375 :
10376 10 : auto hTransformer = GDALCreateGenImgProjTransformer2(
10377 : GDALDataset::ToHandle(const_cast<GDALDataset *>(this)), nullptr,
10378 : aosTO.List());
10379 10 : if (hTransformer == nullptr)
10380 : {
10381 1 : return CE_Failure;
10382 : }
10383 :
10384 9 : double z = 0;
10385 9 : int bSuccess = 0;
10386 9 : GDALGenImgProjTransform(hTransformer, TRUE, 1, &dfGeolocX, &dfGeolocY, &z,
10387 : &bSuccess);
10388 9 : GDALDestroyTransformer(hTransformer);
10389 9 : if (bSuccess)
10390 : {
10391 9 : if (pdfPixel)
10392 9 : *pdfPixel = dfGeolocX;
10393 9 : if (pdfLine)
10394 9 : *pdfLine = dfGeolocY;
10395 9 : return CE_None;
10396 : }
10397 : else
10398 : {
10399 0 : return CE_Failure;
10400 : }
10401 : }
10402 :
10403 : /************************************************************************/
10404 : /* GDALDatasetGeolocationToPixelLine() */
10405 : /************************************************************************/
10406 :
10407 : /** Transform georeferenced coordinates to pixel/line coordinates.
10408 : *
10409 : * @see GDALDataset::GeolocationToPixelLine()
10410 : * @since GDAL 3.11
10411 : */
10412 :
10413 0 : CPLErr GDALDatasetGeolocationToPixelLine(GDALDatasetH hDS, double dfGeolocX,
10414 : double dfGeolocY,
10415 : OGRSpatialReferenceH hSRS,
10416 : double *pdfPixel, double *pdfLine,
10417 : CSLConstList papszTransformerOptions)
10418 : {
10419 0 : VALIDATE_POINTER1(hDS, "GDALDatasetGeolocationToPixelLine", CE_Failure);
10420 :
10421 0 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
10422 0 : return poDS->GeolocationToPixelLine(
10423 0 : dfGeolocX, dfGeolocY, OGRSpatialReference::FromHandle(hSRS), pdfPixel,
10424 0 : pdfLine, papszTransformerOptions);
10425 : }
|