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 143992 : 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 8369 : static unsigned long GDALSharedDatasetHashFunc(const void *elt)
150 : {
151 8369 : const SharedDatasetCtxt *psStruct =
152 : static_cast<const SharedDatasetCtxt *>(elt);
153 : return static_cast<unsigned long>(
154 8369 : CPLHashSetHashStr(psStruct->pszDescription) ^
155 8369 : CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^
156 8369 : psStruct->nOpenFlags ^ psStruct->nPID);
157 : }
158 :
159 6942 : static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)
160 : {
161 6942 : const SharedDatasetCtxt *psStruct1 =
162 : static_cast<const SharedDatasetCtxt *>(elt1);
163 6942 : const SharedDatasetCtxt *psStruct2 =
164 : static_cast<const SharedDatasetCtxt *>(elt2);
165 13831 : return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
166 6889 : strcmp(psStruct1->pszConcatenatedOpenOptions,
167 6889 : psStruct2->pszConcatenatedOpenOptions) == 0 &&
168 20720 : psStruct1->nPID == psStruct2->nPID &&
169 13831 : psStruct1->nOpenFlags == psStruct2->nOpenFlags;
170 : }
171 :
172 392 : static void GDALSharedDatasetFreeFunc(void *elt)
173 : {
174 392 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
175 392 : CPLFree(psStruct->pszDescription);
176 392 : CPLFree(psStruct->pszConcatenatedOpenOptions);
177 392 : CPLFree(psStruct);
178 392 : }
179 :
180 : static std::string
181 7042 : GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)
182 : {
183 7042 : std::string osStr;
184 7055 : for (const char *pszOption : cpl::Iterate(papszOpenOptions))
185 13 : osStr += pszOption;
186 7042 : 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 81289 : CPLMutex **GDALGetphDLMutex()
195 : {
196 81289 : return &hDLMutex;
197 : }
198 :
199 : // The current thread will act in the behalf of the thread of PID
200 : // responsiblePID.
201 71174 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
202 : {
203 : GIntBig *pResponsiblePID =
204 71174 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
205 71172 : if (pResponsiblePID == nullptr)
206 : {
207 206 : pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
208 206 : CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
209 : }
210 71171 : *pResponsiblePID = responsiblePID;
211 71171 : }
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 194402 : GIntBig GDALGetResponsiblePIDForCurrentThread()
216 : {
217 : GIntBig *pResponsiblePID =
218 194402 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
219 194312 : if (pResponsiblePID == nullptr)
220 45291 : return CPLGetPID();
221 149021 : 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 125284 : GDALDataset::GDALDataset()
248 125284 : : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
249 : {
250 125180 : }
251 :
252 144019 : GDALDataset::GDALDataset(int bForceCachedIOIn)
253 143888 : : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
254 144019 : m_poPrivate(new(std::nothrow) GDALDataset::Private)
255 : {
256 143963 : }
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 143962 : 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 143949 : if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))
285 : {
286 68541 : if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
287 209 : CPLDebug("GDAL",
288 : "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
289 209 : GetDescription(), this, static_cast<int>(CPLGetPID()),
290 209 : static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
291 : else
292 68343 : CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
293 : }
294 :
295 143986 : if (IsMarkedSuppressOnClose())
296 : {
297 2292 : 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 1141 : (!EQUAL(poDriver->GetDescription(), "MEM") &&
304 1102 : !EQUAL(poDriver->GetDescription(), "Memory")))
305 : {
306 1112 : VSIUnlink(GetDescription());
307 : }
308 : }
309 :
310 : /* -------------------------------------------------------------------- */
311 : /* Remove dataset from the "open" dataset list. */
312 : /* -------------------------------------------------------------------- */
313 143974 : if (!bIsInternal)
314 : {
315 138918 : CPLMutexHolderD(&hDLMutex);
316 69460 : if (poAllDatasetMap)
317 : {
318 : std::map<GDALDataset *, GIntBig>::iterator oIter =
319 69460 : poAllDatasetMap->find(this);
320 69460 : CPLAssert(oIter != poAllDatasetMap->end());
321 :
322 69460 : UnregisterFromSharedDataset();
323 :
324 69460 : poAllDatasetMap->erase(oIter);
325 :
326 69460 : if (poAllDatasetMap->empty())
327 : {
328 25835 : delete poAllDatasetMap;
329 25835 : poAllDatasetMap = nullptr;
330 25835 : if (phSharedDatasetSet)
331 : {
332 243 : CPLHashSetDestroy(phSharedDatasetSet);
333 : }
334 25835 : phSharedDatasetSet = nullptr;
335 25835 : CPLFree(ppDatasets);
336 25835 : ppDatasets = nullptr;
337 : }
338 : }
339 : }
340 :
341 : /* -------------------------------------------------------------------- */
342 : /* Destroy the raster bands if they exist. */
343 : /* -------------------------------------------------------------------- */
344 1371260 : for (int i = 0; i < nBands && papoBands != nullptr; ++i)
345 : {
346 1227290 : if (papoBands[i] != nullptr)
347 1227290 : delete papoBands[i];
348 1227280 : papoBands[i] = nullptr;
349 : }
350 :
351 143968 : CPLFree(papoBands);
352 :
353 143963 : if (m_poStyleTable)
354 : {
355 23 : delete m_poStyleTable;
356 23 : m_poStyleTable = nullptr;
357 : }
358 :
359 143963 : if (m_poPrivate != nullptr)
360 : {
361 143965 : if (m_poPrivate->hMutex != nullptr)
362 18367 : CPLDestroyMutex(m_poPrivate->hMutex);
363 :
364 : // coverity[missing_lock]
365 143965 : CPLFree(m_poPrivate->m_pszWKTCached);
366 143964 : if (m_poPrivate->m_poSRSCached)
367 : {
368 0 : m_poPrivate->m_poSRSCached->Release();
369 : }
370 : // coverity[missing_lock]
371 143964 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
372 143965 : if (m_poPrivate->m_poSRSGCPCached)
373 : {
374 0 : m_poPrivate->m_poSRSGCPCached->Release();
375 : }
376 : }
377 :
378 143963 : delete m_poPrivate;
379 :
380 143956 : CSLDestroy(papszOpenOptions);
381 143972 : }
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 85743 : CPLErr GDALDataset::Close()
460 : {
461 : // Call UnregisterFromSharedDataset() before altering nOpenFlags
462 85743 : UnregisterFromSharedDataset();
463 :
464 85741 : nOpenFlags = OPEN_FLAGS_CLOSED;
465 85741 : return CE_None;
466 : }
467 :
468 : /************************************************************************/
469 : /* UnregisterFromSharedDataset() */
470 : /************************************************************************/
471 :
472 155202 : void GDALDataset::UnregisterFromSharedDataset()
473 : {
474 155202 : if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))
475 154810 : return;
476 :
477 784 : CPLMutexHolderD(&hDLMutex);
478 :
479 : std::map<GDALDataset *, GIntBig>::iterator oIter =
480 392 : poAllDatasetMap->find(this);
481 392 : CPLAssert(oIter != poAllDatasetMap->end());
482 392 : const GIntBig nPIDCreatorForShared = oIter->second;
483 392 : bShared = false;
484 : SharedDatasetCtxt sStruct;
485 392 : sStruct.nPID = nPIDCreatorForShared;
486 392 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
487 392 : sStruct.pszDescription = const_cast<char *>(GetDescription());
488 : std::string osConcatenatedOpenOptions =
489 784 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
490 392 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
491 392 : sStruct.poDS = nullptr;
492 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
493 392 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
494 392 : if (psStruct && psStruct->poDS == this)
495 : {
496 391 : 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 70764 : void GDALDataset::AddToDatasetOpenList()
512 : {
513 : /* -------------------------------------------------------------------- */
514 : /* Add this dataset to the open dataset list. */
515 : /* -------------------------------------------------------------------- */
516 70764 : bIsInternal = false;
517 :
518 70764 : CPLMutexHolderD(&hDLMutex);
519 :
520 70764 : if (poAllDatasetMap == nullptr)
521 25844 : poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
522 70764 : (*poAllDatasetMap)[this] = -1;
523 70764 : }
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 109537 : CPLErr GDALDataset::FlushCache(bool bAtClosing)
552 :
553 : {
554 109537 : CPLErr eErr = CE_None;
555 : // This sometimes happens if a dataset is destroyed before completely
556 : // built.
557 :
558 109537 : if (papoBands)
559 : {
560 1690390 : for (int i = 0; i < nBands; ++i)
561 : {
562 1590200 : if (papoBands[i])
563 : {
564 1590200 : if (papoBands[i]->FlushCache(bAtClosing) != CE_None)
565 7 : eErr = CE_Failure;
566 : }
567 : }
568 : }
569 :
570 109537 : const int nLayers = GetLayerCount();
571 : // cppcheck-suppress knownConditionTrueFalse
572 109537 : if (nLayers > 0)
573 : {
574 9732 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
575 14475 : for (int i = 0; i < nLayers; ++i)
576 : {
577 9609 : OGRLayer *poLayer = GetLayer(i);
578 :
579 9609 : if (poLayer)
580 : {
581 9609 : if (poLayer->SyncToDisk() != OGRERR_NONE)
582 0 : eErr = CE_Failure;
583 : }
584 : }
585 : }
586 :
587 109537 : 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 4707 : CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)
602 :
603 : {
604 4707 : VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);
605 :
606 4707 : 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 3125 : GIntBig GDALDataset::GetEstimatedRAMUsage()
688 : {
689 3125 : 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 350 : CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)
705 :
706 : {
707 350 : GDALRasterBand *poBand1 = GetRasterBand(1);
708 350 : if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))
709 : {
710 7 : return GDALDataset::FlushCache(bAtClosing);
711 : }
712 :
713 343 : int nBlockXSize = 0;
714 343 : int nBlockYSize = 0;
715 343 : poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
716 :
717 : /* -------------------------------------------------------------------- */
718 : /* Verify that all bands match. */
719 : /* -------------------------------------------------------------------- */
720 1108 : 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 794 : 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 343 : 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 29 : CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,
813 : CSLConstList papszOptions)
814 :
815 : {
816 29 : VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
817 :
818 58 : return GDALDataset::FromHandle(hDataset)->AddBand(
819 29 : 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 1442380 : void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)
835 :
836 : {
837 : /* -------------------------------------------------------------------- */
838 : /* Do we need to grow the bands list? */
839 : /* -------------------------------------------------------------------- */
840 1442380 : if (nBands < nNewBand || papoBands == nullptr)
841 : {
842 807709 : GDALRasterBand **papoNewBands = nullptr;
843 :
844 807709 : if (papoBands == nullptr)
845 91307 : papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
846 91250 : sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
847 : else
848 : papoNewBands = static_cast<GDALRasterBand **>(
849 716403 : VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
850 716459 : std::max(nNewBand, nBands)));
851 807710 : if (papoNewBands == nullptr)
852 : {
853 0 : ReportError(CE_Failure, CPLE_OutOfMemory,
854 : "Cannot allocate band array");
855 0 : return;
856 : }
857 :
858 807710 : papoBands = papoNewBands;
859 :
860 1566100 : for (int i = nBands; i < nNewBand; ++i)
861 758386 : papoBands[i] = nullptr;
862 :
863 807710 : nBands = std::max(nBands, nNewBand);
864 :
865 807769 : if (m_poPrivate)
866 : {
867 807992 : for (int i = static_cast<int>(m_poPrivate->m_anBandMap.size());
868 2250010 : i < nBands; ++i)
869 : {
870 1442240 : 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 1442220 : 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 1442210 : 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 1442210 : poBand->nBand = nNewBand;
893 1442210 : poBand->poDS = this;
894 1442210 : poBand->nRasterXSize = nRasterXSize;
895 1442210 : poBand->nRasterYSize = nRasterYSize;
896 1442210 : 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 73487 : void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)
914 : {
915 73487 : SetBand(nNewBand, poBand.release());
916 73487 : }
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 600569 : int GDALDataset::GetRasterXSize() const
935 : {
936 600569 : 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 35820 : int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)
950 :
951 : {
952 35820 : VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
953 :
954 35820 : 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 488364 : int GDALDataset::GetRasterYSize() const
972 : {
973 488364 : 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 35507 : int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)
987 :
988 : {
989 35507 : VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
990 :
991 35507 : 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 11117600 : GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)
1014 :
1015 : {
1016 11117600 : if (papoBands)
1017 : {
1018 11110600 : if (nBandId < 1 || nBandId > nBands)
1019 : {
1020 7458 : ReportError(CE_Failure, CPLE_IllegalArg,
1021 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1022 : nBandId);
1023 12 : return nullptr;
1024 : }
1025 :
1026 11103100 : return papoBands[nBandId - 1];
1027 : }
1028 7035 : 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 112 : const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const
1051 :
1052 : {
1053 112 : if (papoBands)
1054 : {
1055 112 : 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 112 : 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 297542 : GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)
1078 :
1079 : {
1080 297542 : VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
1081 :
1082 297542 : return GDALRasterBand::ToHandle(
1083 297542 : 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 5277130 : int GDALDataset::GetRasterCount() const
1099 : {
1100 5277130 : 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 381218 : int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)
1114 :
1115 : {
1116 381218 : VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
1117 :
1118 381218 : 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 5485 : const char *GDALDataset::GetProjectionRef() const
1147 : {
1148 5485 : const auto poSRS = GetSpatialRef();
1149 5485 : if (!poSRS || !m_poPrivate)
1150 : {
1151 2441 : return "";
1152 : }
1153 3044 : char *pszWKT = nullptr;
1154 3044 : poSRS->exportToWkt(&pszWKT);
1155 3044 : 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 6088 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1164 3044 : if (m_poPrivate->m_pszWKTCached &&
1165 843 : strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)
1166 : {
1167 842 : CPLFree(pszWKT);
1168 842 : return m_poPrivate->m_pszWKTCached;
1169 : }
1170 2202 : CPLFree(m_poPrivate->m_pszWKTCached);
1171 2202 : m_poPrivate->m_pszWKTCached = pszWKT;
1172 2202 : 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 16899 : const OGRSpatialReference *GDALDataset::GetSpatialRef() const
1198 : {
1199 16899 : 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 6450 : OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)
1215 :
1216 : {
1217 6450 : VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
1218 :
1219 6450 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1220 6450 : 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 1488 : const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)
1234 :
1235 : {
1236 1488 : VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
1237 :
1238 1488 : 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 2425 : CPLErr GDALDataset::SetProjection(const char *pszProjection)
1264 : {
1265 2425 : if (pszProjection && pszProjection[0] != '\0')
1266 : {
1267 4490 : OGRSpatialReference oSRS;
1268 2245 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1269 2245 : if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)
1270 : {
1271 2 : return CE_Failure;
1272 : }
1273 2243 : return SetSpatialRef(&oSRS);
1274 : }
1275 : else
1276 : {
1277 180 : 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 1094 : CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)
1323 :
1324 : {
1325 1094 : VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1326 :
1327 2188 : return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1328 1094 : 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 1775 : CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,
1342 : const char *pszProjection)
1343 :
1344 : {
1345 1775 : VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1346 :
1347 1775 : 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 15403 : CPLErr GDALDataset::GetGeoTransform(double *padfTransform)
1382 :
1383 : {
1384 15403 : CPLAssert(padfTransform != nullptr);
1385 :
1386 15403 : padfTransform[0] = 0.0; // X Origin (top left corner)
1387 15403 : padfTransform[1] = 1.0; // X Pixel size */
1388 15403 : padfTransform[2] = 0.0;
1389 :
1390 15403 : padfTransform[3] = 0.0; // Y Origin (top left corner)
1391 15403 : padfTransform[4] = 0.0;
1392 15403 : padfTransform[5] = 1.0; // Y Pixel Size
1393 :
1394 15403 : 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 8452 : CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1408 :
1409 : {
1410 8452 : VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1411 :
1412 8452 : 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 3835 : CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1456 :
1457 : {
1458 3835 : VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1459 :
1460 3835 : 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 30081 : GDALDriver *GDALDataset::GetDriver()
1518 : {
1519 30081 : 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 2667 : GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)
1533 :
1534 : {
1535 2667 : VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1536 :
1537 : return static_cast<GDALDriverH>(
1538 2667 : 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 154597 : int GDALDataset::Reference()
1556 : {
1557 154597 : 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 1216 : int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)
1571 :
1572 : {
1573 1216 : VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1574 :
1575 1216 : 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 210192 : int GDALDataset::Dereference()
1594 : {
1595 210192 : 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 55768 : int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)
1609 :
1610 : {
1611 55768 : VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1612 :
1613 55768 : 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 149510 : int GDALDataset::ReleaseRef()
1627 :
1628 : {
1629 149510 : if (Dereference() <= 0)
1630 : {
1631 5907 : nRefCount = 1;
1632 5907 : delete this;
1633 5907 : return TRUE;
1634 : }
1635 143602 : 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 1454 : int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)
1650 :
1651 : {
1652 1454 : VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1653 :
1654 1454 : 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 106109 : int GDALDataset::GetShared() const
1668 : {
1669 106109 : return bShared;
1670 : }
1671 :
1672 : /************************************************************************/
1673 : /* MarkAsShared() */
1674 : /************************************************************************/
1675 :
1676 : /**
1677 : * \brief Mark this dataset as available for sharing.
1678 : */
1679 :
1680 407 : void GDALDataset::MarkAsShared()
1681 :
1682 : {
1683 407 : CPLAssert(!bShared);
1684 :
1685 407 : bShared = true;
1686 407 : if (bIsInternal)
1687 14 : return;
1688 :
1689 393 : GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1690 :
1691 : // Insert the dataset in the set of shared opened datasets.
1692 786 : CPLMutexHolderD(&hDLMutex);
1693 393 : if (phSharedDatasetSet == nullptr)
1694 245 : phSharedDatasetSet =
1695 245 : CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1696 : GDALSharedDatasetFreeFunc);
1697 :
1698 : SharedDatasetCtxt *psStruct =
1699 393 : static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1700 393 : psStruct->poDS = this;
1701 393 : psStruct->nPID = nPID;
1702 393 : psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
1703 393 : psStruct->pszDescription = CPLStrdup(GetDescription());
1704 : std::string osConcatenatedOpenOptions =
1705 786 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
1706 393 : psStruct->pszConcatenatedOpenOptions =
1707 393 : CPLStrdup(osConcatenatedOpenOptions.c_str());
1708 393 : 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 392 : CPLHashSetInsert(phSharedDatasetSet, psStruct);
1718 :
1719 392 : (*poAllDatasetMap)[this] = nPID;
1720 : }
1721 : }
1722 :
1723 : /************************************************************************/
1724 : /* MarkSuppressOnClose() */
1725 : /************************************************************************/
1726 :
1727 : /** Set that the dataset must be deleted on close. */
1728 1152 : void GDALDataset::MarkSuppressOnClose()
1729 : {
1730 1152 : bSuppressOnClose = true;
1731 1152 : }
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 253 : void GDALDataset::CleanupPostFileClosing()
1753 : {
1754 253 : 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 253 : }
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 15648 : int GDALDataset::GetGCPCount()
1776 : {
1777 15648 : return 0;
1778 : }
1779 :
1780 : /************************************************************************/
1781 : /* GDALGetGCPCount() */
1782 : /************************************************************************/
1783 :
1784 : /**
1785 : * \brief Get number of GCPs.
1786 : *
1787 : * @see GDALDataset::GetGCPCount()
1788 : */
1789 :
1790 1179 : int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)
1791 :
1792 : {
1793 1179 : VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
1794 :
1795 1179 : 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 874 : const char *GDALDataset::GetGCPProjection()
1817 : {
1818 874 : const auto poSRS = GetGCPSpatialRef();
1819 874 : if (!poSRS || !m_poPrivate)
1820 : {
1821 537 : 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 468 : OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)
1883 :
1884 : {
1885 468 : VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
1886 :
1887 468 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1888 468 : 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 803 : const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)
1902 :
1903 : {
1904 803 : VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
1905 :
1906 803 : 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 580 : const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)
1938 :
1939 : {
1940 580 : VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
1941 :
1942 580 : 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 53 : CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,
1978 : const char *pszGCPProjection)
1979 :
1980 : {
1981 53 : if (pszGCPProjection && pszGCPProjection[0] != '\0')
1982 : {
1983 68 : OGRSpatialReference oSRS;
1984 34 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1985 34 : if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)
1986 : {
1987 0 : return CE_Failure;
1988 : }
1989 34 : 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 1 : CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,
2030 : CPL_UNUSED const GDAL_GCP *pasGCPList,
2031 : CPL_UNUSED const OGRSpatialReference *poGCP_SRS)
2032 :
2033 : {
2034 1 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
2035 1 : ReportError(CE_Failure, CPLE_NotSupported,
2036 : "Dataset does not support the SetGCPs() method.");
2037 :
2038 1 : 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 30 : CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,
2052 : const GDAL_GCP *pasGCPList,
2053 : const char *pszGCPProjection)
2054 :
2055 : {
2056 30 : VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
2057 :
2058 30 : return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,
2059 30 : 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 727 : 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 727 : int *panAllBandList = nullptr;
2141 :
2142 727 : if (nListBands == 0)
2143 : {
2144 716 : nListBands = GetRasterCount();
2145 : panAllBandList =
2146 716 : static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
2147 67427 : for (int i = 0; i < nListBands; ++i)
2148 66711 : panAllBandList[i] = i + 1;
2149 :
2150 716 : panBandList = panAllBandList;
2151 : }
2152 :
2153 727 : if (pfnProgress == nullptr)
2154 693 : pfnProgress = GDALDummyProgress;
2155 :
2156 1785 : for (int i = 0; i < nOverviews; ++i)
2157 : {
2158 1059 : 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 726 : std::vector<std::unique_ptr<CPLConfigOptionSetter>> apoConfigOptionSetter;
2172 760 : 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 1452 : IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
2180 726 : panBandList, pfnProgress, pProgressData, papszOptions);
2181 :
2182 726 : if (panAllBandList != nullptr)
2183 714 : CPLFree(panAllBandList);
2184 :
2185 726 : 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 35 : 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 35 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2207 :
2208 35 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2209 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2210 35 : 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 672 : 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 672 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2232 :
2233 672 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2234 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2235 672 : pfnProgress, pProgressData, papszOptions);
2236 : }
2237 :
2238 : /************************************************************************/
2239 : /* IBuildOverviews() */
2240 : /* */
2241 : /* Default implementation. */
2242 : /************************************************************************/
2243 :
2244 : //! @cond Doxygen_Suppress
2245 195 : 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 195 : if (oOvManager.IsInitialized())
2254 194 : return oOvManager.BuildOverviews(
2255 : nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2256 194 : 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 443989 : 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 443989 : const char *pszInterleave = nullptr;
2288 :
2289 443989 : CPLAssert(nullptr != pData);
2290 :
2291 443989 : const bool bHasSubpixelShift =
2292 446029 : psExtraArg->bFloatingPointWindowValidity &&
2293 444648 : psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2294 659 : (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2295 :
2296 443874 : if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&
2297 69939 : nBandCount > 1 &&
2298 69942 : (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2299 887860 : nullptr &&
2300 66879 : EQUAL(pszInterleave, "PIXEL"))
2301 : {
2302 63886 : return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2303 : nBufXSize, nBufYSize, eBufType, nBandCount,
2304 : panBandMap, nPixelSpace, nLineSpace,
2305 63885 : nBandSpace, psExtraArg);
2306 : }
2307 :
2308 380101 : if (eRWFlag == GF_Read &&
2309 200693 : (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2310 200042 : psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2311 200040 : psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2312 200693 : psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2313 815 : !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)
2314 : {
2315 790 : if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())
2316 : {
2317 591 : int bTried = FALSE;
2318 591 : const CPLErr eErr = TryOverviewRasterIO(
2319 : eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
2320 : nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
2321 : nLineSpace, nBandSpace, psExtraArg, &bTried);
2322 591 : if (bTried)
2323 1 : return eErr;
2324 : }
2325 :
2326 789 : GDALDataType eFirstBandDT = GDT_Unknown;
2327 789 : int nFirstMaskFlags = 0;
2328 789 : GDALRasterBand *poFirstMaskBand = nullptr;
2329 789 : int nOKBands = 0;
2330 :
2331 : // Check if bands share the same mask band
2332 2390 : for (int i = 0; i < nBandCount; ++i)
2333 : {
2334 2118 : GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2335 3589 : if ((nBufXSize < nXSize || nBufYSize < nYSize) &&
2336 1464 : poBand->GetOverviewCount())
2337 : {
2338 : // Could be improved to select the appropriate overview.
2339 3 : break;
2340 : }
2341 2122 : if (poBand->GetColorTable() != nullptr)
2342 : {
2343 0 : break;
2344 : }
2345 2133 : const GDALDataType eDT = poBand->GetRasterDataType();
2346 2127 : if (GDALDataTypeIsComplex(eDT))
2347 : {
2348 30 : break;
2349 : }
2350 2085 : if (i == 0)
2351 : {
2352 754 : eFirstBandDT = eDT;
2353 754 : nFirstMaskFlags = poBand->GetMaskFlags();
2354 764 : if (nFirstMaskFlags == GMF_NODATA)
2355 : {
2356 : // The dataset-level resampling code is not ready for nodata
2357 : // Fallback to band-level resampling
2358 10 : break;
2359 : }
2360 754 : poFirstMaskBand = poBand->GetMaskBand();
2361 : }
2362 : else
2363 : {
2364 1331 : if (eDT != eFirstBandDT)
2365 : {
2366 0 : break;
2367 : }
2368 1331 : int nMaskFlags = poBand->GetMaskFlags();
2369 1333 : 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 1333 : GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2376 1338 : if (nFirstMaskFlags == GMF_ALL_VALID &&
2377 : nMaskFlags == GMF_ALL_VALID)
2378 : {
2379 : // Ok.
2380 : }
2381 694 : else if (poFirstMaskBand == poMaskBand)
2382 : {
2383 : // Ok.
2384 : }
2385 : else
2386 : {
2387 489 : break;
2388 : }
2389 : }
2390 :
2391 1601 : ++nOKBands;
2392 : }
2393 :
2394 804 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2395 804 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2396 :
2397 804 : CPLErr eErr = CE_None;
2398 804 : if (nOKBands > 0)
2399 : {
2400 758 : if (nOKBands < nBandCount)
2401 : {
2402 489 : psExtraArg->pfnProgress = GDALScaledProgress;
2403 978 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2404 489 : 0.0, static_cast<double>(nOKBands) / nBandCount,
2405 : pfnProgressGlobal, pProgressDataGlobal);
2406 489 : if (psExtraArg->pProgressData == nullptr)
2407 100 : psExtraArg->pfnProgress = nullptr;
2408 : }
2409 :
2410 758 : eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2411 : pData, nBufXSize, nBufYSize, eBufType,
2412 : nOKBands, panBandMap, nPixelSpace,
2413 : nLineSpace, nBandSpace, psExtraArg);
2414 :
2415 758 : if (nOKBands < nBandCount)
2416 : {
2417 489 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2418 : }
2419 : }
2420 804 : if (eErr == CE_None && nOKBands < nBandCount)
2421 : {
2422 529 : if (nOKBands > 0)
2423 : {
2424 486 : psExtraArg->pfnProgress = GDALScaledProgress;
2425 972 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2426 486 : static_cast<double>(nOKBands) / nBandCount, 1.0,
2427 : pfnProgressGlobal, pProgressDataGlobal);
2428 486 : if (psExtraArg->pProgressData == nullptr)
2429 97 : psExtraArg->pfnProgress = nullptr;
2430 : }
2431 1058 : eErr = BandBasedRasterIO(
2432 : eRWFlag, nXOff, nYOff, nXSize, nYSize,
2433 529 : static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,
2434 : nBufYSize, eBufType, nBandCount - nOKBands,
2435 529 : panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,
2436 : psExtraArg);
2437 529 : if (nOKBands > 0)
2438 : {
2439 486 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2440 : }
2441 : }
2442 :
2443 800 : psExtraArg->pfnProgress = pfnProgressGlobal;
2444 800 : psExtraArg->pProgressData = pProgressDataGlobal;
2445 :
2446 800 : return eErr;
2447 : }
2448 :
2449 379311 : return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2450 : nBufXSize, nBufYSize, eBufType, nBandCount,
2451 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2452 379306 : 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 719121 : 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 719121 : CPLErr eErr = CE_None;
2474 :
2475 719121 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2476 719121 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2477 :
2478 1884680 : for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
2479 : ++iBandIndex)
2480 : {
2481 1165550 : GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2482 :
2483 1165550 : if (poBand == nullptr)
2484 : {
2485 0 : eErr = CE_Failure;
2486 0 : break;
2487 : }
2488 :
2489 1165550 : GByte *pabyBandData =
2490 1165550 : static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2491 :
2492 1165550 : if (nBandCount > 1)
2493 : {
2494 655440 : psExtraArg->pfnProgress = GDALScaledProgress;
2495 1310880 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2496 : 1.0 * iBandIndex / nBandCount,
2497 655440 : 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2498 : pProgressDataGlobal);
2499 655441 : if (psExtraArg->pProgressData == nullptr)
2500 652679 : psExtraArg->pfnProgress = nullptr;
2501 : }
2502 :
2503 2331140 : eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2504 : pabyBandData, nBufXSize, nBufYSize, eBufType,
2505 1165550 : nPixelSpace, nLineSpace, psExtraArg);
2506 :
2507 1165580 : if (nBandCount > 1)
2508 655492 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2509 : }
2510 :
2511 719137 : psExtraArg->pfnProgress = pfnProgressGlobal;
2512 719137 : psExtraArg->pProgressData = pProgressDataGlobal;
2513 :
2514 719137 : return eErr;
2515 : }
2516 :
2517 : //! @endcond
2518 :
2519 : /************************************************************************/
2520 : /* ValidateRasterIOOrAdviseReadParameters() */
2521 : /************************************************************************/
2522 :
2523 : //! @cond Doxygen_Suppress
2524 816268 : 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 816268 : if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)
2535 : {
2536 32 : 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 24 : *pbStopProcessingOnCENone = TRUE;
2544 24 : return CE_None;
2545 : }
2546 :
2547 816236 : CPLErr eErr = CE_None;
2548 816236 : *pbStopProcessingOnCENone = FALSE;
2549 :
2550 816236 : if (nXOff < 0 || nXOff > INT_MAX - nXSize ||
2551 816225 : nXOff + nXSize > nRasterXSize || nYOff < 0 ||
2552 816229 : nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)
2553 : {
2554 17 : 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 816221 : 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 0 : eErr = CE_Failure;
2568 : }
2569 :
2570 2440190 : for (int i = 0; i < nBandCount && eErr == CE_None; ++i)
2571 : {
2572 1623930 : int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2573 1623930 : 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 1623930 : 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 816253 : 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 801513 : 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 801513 : if (psExtraArg == nullptr)
2730 : {
2731 609575 : INIT_RASTERIO_EXTRA_ARG(sExtraArg);
2732 :
2733 : // 4 below inits are not strictly needed but make Coverity Scan
2734 : // happy
2735 609575 : sExtraArg.dfXOff = nXOff;
2736 609575 : sExtraArg.dfYOff = nYOff;
2737 609575 : sExtraArg.dfXSize = nXSize;
2738 609575 : sExtraArg.dfYSize = nYSize;
2739 :
2740 609575 : psExtraArg = &sExtraArg;
2741 : }
2742 191938 : 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 801513 : GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
2751 : nBufYSize);
2752 :
2753 801502 : 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 801502 : 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 801502 : if (eRWFlag == GF_Write)
2774 : {
2775 215916 : 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 801500 : int bStopProcessing = FALSE;
2785 801500 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2786 : "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2787 : nBufYSize, nBandCount, panBandMap);
2788 801507 : if (eErr != CE_None || bStopProcessing)
2789 19 : return eErr;
2790 801488 : 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 801486 : if (nPixelSpace == 0)
2802 422406 : nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
2803 :
2804 801491 : if (nLineSpace == 0)
2805 : {
2806 525476 : nLineSpace = nPixelSpace * nBufXSize;
2807 : }
2808 :
2809 801491 : if (nBandSpace == 0 && nBandCount > 1)
2810 : {
2811 66442 : nBandSpace = nLineSpace * nBufYSize;
2812 : }
2813 :
2814 801491 : if (panBandMap == nullptr)
2815 : {
2816 427358 : if (!m_poPrivate)
2817 0 : return CE_Failure;
2818 427358 : CPLAssert(static_cast<int>(m_poPrivate->m_anBandMap.size()) == nBands);
2819 427359 : panBandMap = m_poPrivate->m_anBandMap.data();
2820 : }
2821 :
2822 801490 : int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
2823 :
2824 : /* -------------------------------------------------------------------- */
2825 : /* We are being forced to use cached IO instead of a driver */
2826 : /* specific implementation. */
2827 : /* -------------------------------------------------------------------- */
2828 801498 : 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 801487 : 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 801480 : nBandSpace, psExtraArg);
2847 : }
2848 :
2849 801505 : if (bCallLeaveReadWrite)
2850 407418 : LeaveReadWrite();
2851 :
2852 801504 : 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 4762 : 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 4762 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
2880 :
2881 4762 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2882 :
2883 4762 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2884 : nBufXSize, nBufYSize, eBufType, nBandCount,
2885 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2886 4762 : 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 352698 : 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 352698 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
2911 :
2912 352698 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2913 :
2914 352698 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2915 : nBufXSize, nBufYSize, eBufType, nBandCount,
2916 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2917 352698 : 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 2242 : GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)
2939 :
2940 : {
2941 4484 : CPLMutexHolderD(&hDLMutex);
2942 :
2943 2242 : if (poAllDatasetMap == nullptr)
2944 : {
2945 2220 : *pnCount = 0;
2946 2220 : return nullptr;
2947 : }
2948 :
2949 22 : *pnCount = static_cast<int>(poAllDatasetMap->size());
2950 22 : ppDatasets = static_cast<GDALDataset **>(
2951 22 : CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
2952 22 : std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();
2953 598 : for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)
2954 576 : ppDatasets[i] = oIter->first;
2955 22 : 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 14512 : 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 14512 : int bStopProcessing = FALSE;
3070 14512 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3071 : "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
3072 : nBufXSize, nBufYSize, nBandCount, panBandMap);
3073 14512 : if (eErr != CE_None || bStopProcessing)
3074 20 : return eErr;
3075 :
3076 128225 : for (int iBand = 0; iBand < nBandCount; ++iBand)
3077 : {
3078 113733 : GDALRasterBand *poBand = nullptr;
3079 :
3080 113733 : if (panBandMap == nullptr)
3081 112418 : poBand = GetRasterBand(iBand + 1);
3082 : else
3083 1315 : poBand = GetRasterBand(panBandMap[iBand]);
3084 :
3085 113733 : if (poBand == nullptr)
3086 0 : return CE_Failure;
3087 :
3088 227466 : eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
3089 113733 : nBufYSize, eBufType, papszOptions);
3090 :
3091 113733 : if (eErr != CE_None)
3092 0 : return eErr;
3093 : }
3094 :
3095 14492 : 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 78746 : DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,
3135 : const std::string &osAllowedDriversIn)
3136 78746 : : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),
3137 78746 : osAllowedDrivers(osAllowedDriversIn)
3138 : {
3139 78739 : }
3140 : };
3141 :
3142 : struct DatasetContextCompare
3143 : {
3144 911770 : bool operator()(const DatasetContext &lhs,
3145 : const DatasetContext &rhs) const
3146 : {
3147 2662560 : return lhs.osFilename < rhs.osFilename ||
3148 881231 : (lhs.osFilename == rhs.osFilename &&
3149 868902 : (lhs.nOpenFlags < rhs.nOpenFlags ||
3150 1737110 : (lhs.nOpenFlags == rhs.nOpenFlags &&
3151 1780970 : 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 338490 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3195 : {
3196 338490 : return g_tls_antiRecursion;
3197 : }
3198 : #endif
3199 :
3200 : //! @cond Doxygen_Suppress
3201 259744 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)
3202 259744 : : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),
3203 : m_osIdentifier(osIdentifier),
3204 259744 : m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3205 : {
3206 259744 : CPLAssert(!osIdentifier.empty());
3207 259744 : }
3208 :
3209 259744 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(
3210 259744 : const GDALAntiRecursionGuard &other, const std::string &osIdentifier)
3211 259744 : : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),
3212 259744 : m_osIdentifier(osIdentifier.empty()
3213 : ? osIdentifier
3214 26851 : : other.m_osIdentifier + osIdentifier),
3215 259744 : m_nDepth(m_osIdentifier.empty()
3216 259744 : ? 0
3217 286595 : : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3218 : {
3219 259744 : }
3220 :
3221 519488 : GDALAntiRecursionGuard::~GDALAntiRecursionGuard()
3222 : {
3223 519488 : if (!m_osIdentifier.empty())
3224 : {
3225 286595 : --m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier];
3226 : }
3227 519488 : }
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 4768 : char **GDALDataset::GetFileList()
3254 :
3255 : {
3256 9536 : CPLString osMainFilename = GetDescription();
3257 : VSIStatBufL sStat;
3258 :
3259 4768 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3260 : GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,
3261 9536 : std::string());
3262 4768 : auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
3263 4768 : 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 4768 : VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
3271 :
3272 : /* -------------------------------------------------------------------- */
3273 : /* Form new list. */
3274 : /* -------------------------------------------------------------------- */
3275 4768 : char **papszList = nullptr;
3276 :
3277 4768 : if (bMainFileReal)
3278 4707 : papszList = CSLAddString(papszList, osMainFilename);
3279 :
3280 4768 : 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 4768 : ++sAntiRecursion.nRecLevel;
3287 :
3288 : /* -------------------------------------------------------------------- */
3289 : /* Do we have a known overview file? */
3290 : /* -------------------------------------------------------------------- */
3291 4768 : if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
3292 : {
3293 61 : auto iter = aosDatasetList.insert(datasetCtxt).first;
3294 61 : char **papszOvrList = oOvManager.poODS->GetFileList();
3295 61 : papszList = CSLInsertStrings(papszList, -1, papszOvrList);
3296 61 : CSLDestroy(papszOvrList);
3297 61 : aosDatasetList.erase(iter);
3298 : }
3299 :
3300 : /* -------------------------------------------------------------------- */
3301 : /* Do we have a known mask file? */
3302 : /* -------------------------------------------------------------------- */
3303 4768 : if (oOvManager.HaveMaskFile())
3304 : {
3305 11 : auto iter = aosDatasetList.insert(std::move(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 4768 : --sAntiRecursion.nRecLevel;
3316 :
3317 4768 : return papszList;
3318 : }
3319 :
3320 : /************************************************************************/
3321 : /* GDALGetFileList() */
3322 : /************************************************************************/
3323 :
3324 : /**
3325 : * \brief Fetch files forming dataset.
3326 : *
3327 : * @see GDALDataset::GetFileList()
3328 : */
3329 :
3330 3977 : char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)
3331 :
3332 : {
3333 3977 : VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3334 :
3335 3977 : 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 89 : CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)
3405 :
3406 : {
3407 89 : VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3408 :
3409 89 : 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 25063 : GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)
3456 :
3457 : {
3458 25063 : const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3459 25063 : const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3460 : GDALDatasetH hDataset =
3461 25063 : GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3462 25059 : return hDataset;
3463 : }
3464 :
3465 : /************************************************************************/
3466 : /* GetSharedDS() */
3467 : /************************************************************************/
3468 :
3469 6484 : static GDALDataset *GetSharedDS(const char *pszFilename,
3470 : unsigned int nOpenFlags,
3471 : const char *const *papszOpenOptions)
3472 : {
3473 12968 : CPLMutexHolderD(&hDLMutex);
3474 :
3475 6484 : if (phSharedDatasetSet != nullptr)
3476 : {
3477 6257 : const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3478 : SharedDatasetCtxt sStruct;
3479 :
3480 6257 : sStruct.nPID = nThisPID;
3481 6257 : sStruct.pszDescription = const_cast<char *>(pszFilename);
3482 6257 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
3483 : std::string osConcatenatedOpenOptions =
3484 6257 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
3485 6257 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
3486 6257 : sStruct.poDS = nullptr;
3487 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3488 6257 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3489 6257 : if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3490 : {
3491 152 : sStruct.nOpenFlags |= GDAL_OF_UPDATE;
3492 : psStruct = static_cast<SharedDatasetCtxt *>(
3493 152 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3494 : }
3495 6257 : if (psStruct)
3496 : {
3497 6106 : return psStruct->poDS;
3498 : }
3499 : }
3500 378 : 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 80088 : 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 80088 : VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
3615 :
3616 : // Hack for the ZARR driver. We translate the CACHE_KERCHUNK_JSON
3617 : // into VSIKERCHUNK_USE_CACHE config option
3618 80074 : std::unique_ptr<CPLConfigOptionSetter> poVSIKERCHUNK_USE_CACHESetter;
3619 80088 : if (CPLFetchBool(papszOpenOptions, "CACHE_KERCHUNK_JSON", false))
3620 : {
3621 13 : poVSIKERCHUNK_USE_CACHESetter = std::make_unique<CPLConfigOptionSetter>(
3622 26 : "VSIKERCHUNK_USE_CACHE", "YES", false);
3623 : }
3624 :
3625 : // Do some sanity checks on incompatible flags with thread-safe mode.
3626 80088 : if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3627 : {
3628 : const struct
3629 : {
3630 : int nFlag;
3631 : const char *pszFlagName;
3632 128 : } asFlags[] = {
3633 : {GDAL_OF_UPDATE, "GDAL_OF_UPDATE"},
3634 : {GDAL_OF_VECTOR, "GDAL_OF_VECTOR"},
3635 : {GDAL_OF_MULTIDIM_RASTER, "GDAL_OF_MULTIDIM_RASTER"},
3636 : {GDAL_OF_GNM, "GDAL_OF_GNM"},
3637 : };
3638 :
3639 630 : for (const auto &asFlag : asFlags)
3640 : {
3641 506 : if ((nOpenFlags & asFlag.nFlag) != 0)
3642 : {
3643 4 : CPLError(CE_Failure, CPLE_IllegalArg,
3644 : "GDAL_OF_THREAD_SAFE and %s are mutually "
3645 : "exclusive",
3646 4 : asFlag.pszFlagName);
3647 4 : return nullptr;
3648 : }
3649 : }
3650 : }
3651 :
3652 : // If no driver kind is specified, assume all are to be probed.
3653 80084 : if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)
3654 7506 : nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
3655 :
3656 : /* -------------------------------------------------------------------- */
3657 : /* In case of shared dataset, first scan the existing list to see */
3658 : /* if it could already contain the requested dataset. */
3659 : /* -------------------------------------------------------------------- */
3660 80084 : if (nOpenFlags & GDAL_OF_SHARED)
3661 : {
3662 6484 : if (nOpenFlags & GDAL_OF_INTERNAL)
3663 : {
3664 0 : CPLError(CE_Failure, CPLE_IllegalArg,
3665 : "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
3666 0 : return nullptr;
3667 : }
3668 :
3669 : auto poSharedDS =
3670 6484 : GetSharedDS(pszFilename, nOpenFlags, papszOpenOptions);
3671 6484 : if (poSharedDS)
3672 : {
3673 6106 : poSharedDS->Reference();
3674 6106 : return poSharedDS;
3675 : }
3676 : }
3677 :
3678 73978 : GDALDriverManager *poDM = GetGDALDriverManager();
3679 : // CPLLocaleC oLocaleForcer;
3680 :
3681 73978 : CPLErrorReset();
3682 73977 : VSIErrorReset();
3683 73978 : CPLAssert(nullptr != poDM);
3684 :
3685 : // Build GDALOpenInfo just now to avoid useless file stat'ing if a
3686 : // shared dataset was asked before.
3687 : GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
3688 147945 : const_cast<char **>(papszSiblingFiles));
3689 73976 : oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3690 :
3691 73976 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3692 73976 : if (sAntiRecursion.nRecLevel == 100)
3693 : {
3694 0 : CPLError(CE_Failure, CPLE_AppDefined,
3695 : "GDALOpen() called with too many recursion levels");
3696 0 : return nullptr;
3697 : }
3698 :
3699 147946 : std::string osAllowedDrivers;
3700 162721 : for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
3701 88743 : osAllowedDrivers += pszDriverName;
3702 : auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(
3703 221916 : std::string(pszFilename), nOpenFlags, osAllowedDrivers);
3704 73974 : if (cpl::contains(sAntiRecursion.aosDatasetNamesWithFlags, dsCtxt))
3705 : {
3706 0 : CPLError(CE_Failure, CPLE_AppDefined,
3707 : "GDALOpen() called on %s recursively", pszFilename);
3708 0 : return nullptr;
3709 : }
3710 :
3711 : // Remove leading @ if present.
3712 : char **papszOpenOptionsCleaned =
3713 73963 : CSLDuplicate(const_cast<char **>(papszOpenOptions));
3714 79466 : for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
3715 : ++papszIter)
3716 : {
3717 5504 : char *pszOption = *papszIter;
3718 5504 : if (pszOption[0] == '@')
3719 183 : memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
3720 : }
3721 :
3722 73962 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3723 73962 : oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;
3724 :
3725 : #ifdef OGRAPISPY_ENABLED
3726 73962 : const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
3727 : const int iSnapshot =
3728 18636 : (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0
3729 92598 : ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)
3730 73962 : : INT_MIN;
3731 : #endif
3732 :
3733 73962 : const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);
3734 73967 : GDALDriver *poMissingPluginDriver = nullptr;
3735 147943 : std::vector<GDALDriver *> apoSecondPassDrivers;
3736 :
3737 : // Lookup of matching driver for dataset can involve up to 2 passes:
3738 : // - in the first pass, all drivers that are compabile of the request mode
3739 : // (raster/vector/etc.) are probed using their Identify() method if it
3740 : // exists. If the Identify() method returns FALSE, the driver is skipped.
3741 : // If the Identify() methods returns GDAL_IDENTIFY_UNKNOWN and that the
3742 : // driver is a deferred-loading plugin, it is added to the
3743 : // apoSecondPassDrivers list for potential later probing, and execution
3744 : // continues to the next driver in the list.
3745 : // Otherwise if Identify() returns non-FALSE, the Open() method is used.
3746 : // If Open() returns a non-NULL dataset, the loop stops and it is
3747 : // returned. Otherwise looping over remaining drivers continues.
3748 : // - the second pass is optional, only if at least one driver was added
3749 : // into apoSecondPassDrivers during the first pass. It is similar
3750 : // to the first pass except it runs only on apoSecondPassDrivers drivers.
3751 : // And the Open() method of such drivers is used, causing them to be
3752 : // loaded for real.
3753 73957 : int iPass = 1;
3754 73967 : retry:
3755 7540360 : for (int iDriver = 0;
3756 7540400 : iDriver < (iPass == 1 ? nDriverCount
3757 34 : : static_cast<int>(apoSecondPassDrivers.size()));
3758 : ++iDriver)
3759 : {
3760 : GDALDriver *poDriver =
3761 7523330 : iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
3762 3258 : : apoSecondPassDrivers[iDriver];
3763 10934300 : if (papszAllowedDrivers != nullptr &&
3764 3422450 : CSLFindString(papszAllowedDrivers,
3765 : GDALGetDriverShortName(poDriver)) == -1)
3766 : {
3767 7089650 : continue;
3768 : }
3769 :
3770 4173250 : if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)
3771 38963 : continue;
3772 :
3773 11024600 : if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&
3774 6015900 : (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
3775 1869680 : poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
3776 451548 : continue;
3777 10811900 : if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3778 5412170 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3779 1717500 : poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
3780 1292220 : continue;
3781 5085460 : if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
3782 2546240 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3783 143792 : poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)
3784 135201 : continue;
3785 :
3786 : // Remove general OVERVIEW_LEVEL open options from list before passing
3787 : // it to the driver, if it isn't a driver specific option already.
3788 2267250 : char **papszTmpOpenOptions = nullptr;
3789 2267250 : char **papszTmpOpenOptionsToValidate = nullptr;
3790 2267250 : char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
3791 2267250 : if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
3792 2263620 : nullptr &&
3793 183 : !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
3794 : {
3795 183 : papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
3796 : papszTmpOpenOptions =
3797 183 : CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
3798 183 : oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
3799 :
3800 183 : papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
3801 183 : papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate,
3802 : "OVERVIEW_LEVEL", nullptr);
3803 183 : papszTmpOpenOptionsToValidate = papszOptionsToValidate;
3804 : }
3805 :
3806 : const int nIdentifyRes =
3807 2263440 : poDriver->pfnIdentifyEx
3808 4527400 : ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)
3809 2263430 : : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)
3810 2263980 : : GDAL_IDENTIFY_UNKNOWN;
3811 2263980 : if (nIdentifyRes == FALSE)
3812 : {
3813 1833510 : CSLDestroy(papszTmpOpenOptions);
3814 1832800 : CSLDestroy(papszTmpOpenOptionsToValidate);
3815 1832990 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3816 1832990 : continue;
3817 : }
3818 434535 : else if (iPass == 1 && nIdentifyRes < 0 &&
3819 865103 : poDriver->pfnOpen == nullptr &&
3820 107 : poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN"))
3821 : {
3822 : // Not loaded plugin
3823 104 : apoSecondPassDrivers.push_back(poDriver);
3824 104 : CSLDestroy(papszTmpOpenOptions);
3825 104 : CSLDestroy(papszTmpOpenOptionsToValidate);
3826 104 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3827 104 : continue;
3828 : }
3829 :
3830 430357 : const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;
3831 430357 : if (bIdentifyRes)
3832 : {
3833 54720 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3834 : }
3835 :
3836 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3837 : const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
3838 : CPLErrorReset();
3839 : #endif
3840 :
3841 430360 : sAntiRecursion.nRecLevel++;
3842 430360 : sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
3843 :
3844 434230 : GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
3845 :
3846 434432 : sAntiRecursion.nRecLevel--;
3847 434432 : sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
3848 :
3849 433791 : if (poDriver->pfnOpen != nullptr)
3850 : {
3851 : // If we couldn't determine for sure with Identify() (it returned
3852 : // -1), but Open() managed to open the file, post validate options.
3853 434165 : if (poDS != nullptr &&
3854 54629 : (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&
3855 54095 : !bIdentifyRes)
3856 : {
3857 779 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3858 : }
3859 : }
3860 0 : else if (poDriver->pfnOpenWithDriverArg != nullptr)
3861 : {
3862 : // do nothing
3863 : }
3864 0 : else if (bIdentifyRes &&
3865 0 : poDriver->GetMetadataItem("MISSING_PLUGIN_FILENAME"))
3866 : {
3867 0 : if (!poMissingPluginDriver)
3868 : {
3869 0 : poMissingPluginDriver = poDriver;
3870 : }
3871 : }
3872 : else
3873 : {
3874 : // should not happen given the GDAL_DCAP_OPEN check
3875 0 : CSLDestroy(papszTmpOpenOptions);
3876 0 : CSLDestroy(papszTmpOpenOptionsToValidate);
3877 0 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3878 0 : continue;
3879 : }
3880 :
3881 433791 : CSLDestroy(papszTmpOpenOptions);
3882 433584 : CSLDestroy(papszTmpOpenOptionsToValidate);
3883 434072 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3884 :
3885 434072 : if (poDS != nullptr)
3886 : {
3887 54631 : if (poDS->papszOpenOptions == nullptr)
3888 : {
3889 54365 : poDS->papszOpenOptions = papszOpenOptionsCleaned;
3890 54365 : papszOpenOptionsCleaned = nullptr;
3891 : }
3892 :
3893 : // Deal with generic OVERVIEW_LEVEL open option, unless it is
3894 : // driver specific.
3895 54631 : if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
3896 54672 : nullptr &&
3897 39 : !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
3898 : {
3899 : CPLString osVal(
3900 78 : CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
3901 39 : const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
3902 : const bool bThisLevelOnly =
3903 39 : nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
3904 : GDALDataset *poOvrDS =
3905 39 : GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly);
3906 38 : if (poOvrDS && (nOpenFlags & GDAL_OF_SHARED) != 0)
3907 : {
3908 4 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3909 : {
3910 0 : CPLError(
3911 : CE_Warning, CPLE_NotSupported,
3912 : "A dataset opened by GDALOpenShared should have "
3913 : "the same filename (%s) "
3914 : "and description (%s)",
3915 0 : pszFilename, poDS->GetDescription());
3916 : }
3917 : else
3918 : {
3919 4 : CSLDestroy(poDS->papszOpenOptions);
3920 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
3921 4 : poDS->papszOpenOptions = CSLSetNameValue(
3922 : poDS->papszOpenOptions, "OVERVIEW_LEVEL", nullptr);
3923 : }
3924 : }
3925 38 : poDS->ReleaseRef();
3926 39 : poDS = poOvrDS;
3927 39 : if (poDS == nullptr)
3928 : {
3929 1 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
3930 : {
3931 1 : CPLError(CE_Failure, CPLE_OpenFailed,
3932 : "Cannot open overview level %d of %s",
3933 : nOvrLevel, pszFilename);
3934 : }
3935 : }
3936 : else
3937 : {
3938 : // For thread-safe opening, currently poDS is what will be
3939 : // the "master" dataset owned by the thread-safe dataset
3940 : // returned to the user, hence we do not register it as a
3941 : // visible one in the open dataset list, or mark it as shared.
3942 38 : if (!(nOpenFlags & GDAL_OF_INTERNAL) &&
3943 36 : !(nOpenFlags & GDAL_OF_THREAD_SAFE))
3944 : {
3945 35 : poDS->AddToDatasetOpenList();
3946 : }
3947 38 : if (nOpenFlags & GDAL_OF_SHARED)
3948 : {
3949 4 : CSLDestroy(poDS->papszOpenOptions);
3950 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
3951 4 : poDS->nOpenFlags = nOpenFlags;
3952 4 : if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
3953 4 : poDS->MarkAsShared();
3954 : }
3955 : }
3956 : }
3957 54594 : else if (nOpenFlags & GDAL_OF_SHARED)
3958 : {
3959 368 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3960 : {
3961 2 : CPLError(CE_Warning, CPLE_NotSupported,
3962 : "A dataset opened by GDALOpenShared should have "
3963 : "the same filename (%s) "
3964 : "and description (%s)",
3965 2 : pszFilename, poDS->GetDescription());
3966 : }
3967 366 : else if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
3968 : {
3969 : // For thread-safe opening, currently poDS is what will be
3970 : // the "master" dataset owned by the thread-safe dataset
3971 : // returned to the user, hence we do not or mark it as shared.
3972 366 : poDS->MarkAsShared();
3973 : }
3974 : }
3975 :
3976 54632 : VSIErrorReset();
3977 :
3978 54629 : CSLDestroy(papszOpenOptionsCleaned);
3979 :
3980 : #ifdef OGRAPISPY_ENABLED
3981 54628 : if (iSnapshot != INT_MIN)
3982 : {
3983 11021 : GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
3984 11021 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3985 11021 : poDS = GDALDataset::FromHandle(hDS);
3986 : }
3987 : #endif
3988 :
3989 54628 : if (poDS)
3990 : {
3991 54629 : poDS->m_bCanBeReopened = true;
3992 :
3993 54629 : if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3994 : {
3995 : poDS =
3996 248 : GDALGetThreadSafeDataset(
3997 248 : std::unique_ptr<GDALDataset>(poDS), GDAL_OF_RASTER)
3998 124 : .release();
3999 124 : if (poDS)
4000 : {
4001 124 : poDS->m_bCanBeReopened = true;
4002 124 : poDS->poDriver = poDriver;
4003 124 : poDS->nOpenFlags = nOpenFlags;
4004 124 : if (!(nOpenFlags & GDAL_OF_INTERNAL))
4005 124 : poDS->AddToDatasetOpenList();
4006 124 : if (nOpenFlags & GDAL_OF_SHARED)
4007 0 : poDS->MarkAsShared();
4008 : }
4009 : }
4010 : }
4011 :
4012 55617 : return poDS;
4013 : }
4014 :
4015 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
4016 : if (bFpAvailableBefore && oOpenInfo.fpL == nullptr)
4017 : {
4018 : // In case the file descriptor was "consumed" by a driver
4019 : // that ultimately failed, re-open it for next drivers.
4020 : oOpenInfo.fpL = VSIFOpenL(
4021 : pszFilename, (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
4022 : }
4023 : #else
4024 379441 : if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
4025 : {
4026 2691 : CSLDestroy(papszOpenOptionsCleaned);
4027 :
4028 : #ifdef OGRAPISPY_ENABLED
4029 984 : if (iSnapshot != INT_MIN)
4030 : {
4031 186 : GDALDatasetH hDS = nullptr;
4032 186 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4033 : }
4034 : #endif
4035 984 : return nullptr;
4036 : }
4037 : #endif
4038 : }
4039 :
4040 : // cppcheck-suppress knownConditionTrueFalse
4041 17053 : if (iPass == 1 && !apoSecondPassDrivers.empty())
4042 : {
4043 14 : CPLDebugOnly("GDAL", "GDALOpen(): Second pass");
4044 10 : iPass = 2;
4045 10 : goto retry;
4046 : }
4047 :
4048 17039 : CSLDestroy(papszOpenOptionsCleaned);
4049 :
4050 : #ifdef OGRAPISPY_ENABLED
4051 18359 : if (iSnapshot != INT_MIN)
4052 : {
4053 644 : GDALDatasetH hDS = nullptr;
4054 644 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4055 : }
4056 : #endif
4057 :
4058 18359 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4059 : {
4060 : // Check to see if there was a filesystem error, and report it if so.
4061 : // If not, return a more generic error.
4062 5585 : if (!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
4063 : {
4064 353 : if (nDriverCount == 0)
4065 : {
4066 0 : CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");
4067 : }
4068 353 : else if (oOpenInfo.bStatOK)
4069 : {
4070 350 : if (!poMissingPluginDriver)
4071 : {
4072 350 : CPLError(CE_Failure, CPLE_OpenFailed,
4073 : "`%s' not recognized as being in a supported file "
4074 : "format.",
4075 : pszFilename);
4076 : }
4077 : else
4078 : {
4079 0 : std::string osMsg("`");
4080 0 : osMsg += pszFilename;
4081 : osMsg +=
4082 : "' not recognized as being in a supported file format. "
4083 0 : "It could have been recognized by driver ";
4084 0 : osMsg += poMissingPluginDriver->GetDescription();
4085 0 : osMsg += ", but plugin ";
4086 0 : osMsg += GDALGetMessageAboutMissingPluginDriver(
4087 0 : poMissingPluginDriver);
4088 :
4089 0 : CPLError(CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str());
4090 : }
4091 : }
4092 : else
4093 : {
4094 : // If Stat failed and no VSI error was set, assume it is because
4095 : // the file did not exist on the filesystem.
4096 3 : CPLError(CE_Failure, CPLE_OpenFailed,
4097 : "`%s' does not exist in the file system, "
4098 : "and is not recognized as a supported dataset name.",
4099 : pszFilename);
4100 : }
4101 : }
4102 : }
4103 :
4104 18359 : return nullptr;
4105 : }
4106 :
4107 : /************************************************************************/
4108 : /* GDALOpenShared() */
4109 : /************************************************************************/
4110 :
4111 : /**
4112 : * \brief Open a raster file as a GDALDataset.
4113 : *
4114 : * This function works the same as GDALOpen(), but allows the sharing of
4115 : * GDALDataset handles for a dataset with other callers to GDALOpenShared().
4116 : *
4117 : * In particular, GDALOpenShared() will first consult its list of currently
4118 : * open and shared GDALDataset's, and if the GetDescription() name for one
4119 : * exactly matches the pszFilename passed to GDALOpenShared() it will be
4120 : * referenced and returned.
4121 : *
4122 : * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
4123 : * pszFilename from two different threads, a different GDALDataset object will
4124 : * be returned as it is not safe to use the same dataset from different threads,
4125 : * unless the user does explicitly use mutexes in its code.
4126 : *
4127 : * For drivers supporting the VSI virtual file API, it is possible to open a
4128 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
4129 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
4130 : * server (see VSIInstallCurlFileHandler())
4131 : *
4132 : * \sa GDALOpen()
4133 : * \sa GDALOpenEx()
4134 : *
4135 : * @param pszFilename the name of the file to access. In the case of
4136 : * exotic drivers this may not refer to a physical file, but instead contain
4137 : * information for the driver on how to access a dataset. It should be in
4138 : * UTF-8 encoding.
4139 : *
4140 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
4141 : * drivers support only read only access.
4142 : *
4143 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
4144 : * this handle can be cast to a GDALDataset *.
4145 : */
4146 :
4147 5222 : GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,
4148 : GDALAccess eAccess)
4149 : {
4150 5222 : VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
4151 5222 : return GDALOpenEx(pszFilename,
4152 : GDAL_OF_RASTER |
4153 : (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
4154 : GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
4155 5222 : nullptr, nullptr, nullptr);
4156 : }
4157 :
4158 : /************************************************************************/
4159 : /* GDALClose() */
4160 : /************************************************************************/
4161 :
4162 : /**
4163 : * \brief Close GDAL dataset.
4164 : *
4165 : * For non-shared datasets (opened with GDALOpen()) the dataset is closed
4166 : * using the C++ "delete" operator, recovering all dataset related resources.
4167 : * For shared datasets (opened with GDALOpenShared()) the dataset is
4168 : * dereferenced, and closed only if the referenced count has dropped below 1.
4169 : *
4170 : * @param hDS The dataset to close. May be cast from a "GDALDataset *".
4171 : * @return CE_None in case of success (return value since GDAL 3.7). On a
4172 : * shared dataset whose reference count is not dropped below 1, CE_None will
4173 : * be returned.
4174 : */
4175 :
4176 74286 : CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)
4177 :
4178 : {
4179 74286 : if (!hDS)
4180 395 : return CE_None;
4181 :
4182 : #ifdef OGRAPISPY_ENABLED
4183 73891 : if (bOGRAPISpyEnabled)
4184 11 : OGRAPISpyPreClose(hDS);
4185 : #endif
4186 :
4187 73891 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
4188 :
4189 73891 : if (poDS->GetShared())
4190 : {
4191 : /* --------------------------------------------------------------------
4192 : */
4193 : /* If this file is in the shared dataset list then dereference */
4194 : /* it, and only delete/remote it if the reference count has */
4195 : /* dropped to zero. */
4196 : /* --------------------------------------------------------------------
4197 : */
4198 304 : if (poDS->Dereference() > 0)
4199 28 : return CE_None;
4200 :
4201 276 : CPLErr eErr = poDS->Close();
4202 276 : delete poDS;
4203 :
4204 : #ifdef OGRAPISPY_ENABLED
4205 276 : if (bOGRAPISpyEnabled)
4206 0 : OGRAPISpyPostClose();
4207 : #endif
4208 :
4209 276 : return eErr;
4210 : }
4211 :
4212 : /* -------------------------------------------------------------------- */
4213 : /* This is not shared dataset, so directly delete it. */
4214 : /* -------------------------------------------------------------------- */
4215 73587 : CPLErr eErr = poDS->Close();
4216 73586 : delete poDS;
4217 :
4218 : #ifdef OGRAPISPY_ENABLED
4219 73584 : if (bOGRAPISpyEnabled)
4220 11 : OGRAPISpyPostClose();
4221 : #endif
4222 73582 : return eErr;
4223 : }
4224 :
4225 : /************************************************************************/
4226 : /* GDALDumpOpenDataset() */
4227 : /************************************************************************/
4228 :
4229 0 : static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
4230 : {
4231 0 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
4232 0 : FILE *fp = static_cast<FILE *>(user_data);
4233 0 : GDALDataset *poDS = psStruct->poDS;
4234 :
4235 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4236 0 : ? "DriverIsNULL"
4237 0 : : poDS->GetDriver()->GetDescription();
4238 :
4239 0 : poDS->Reference();
4240 0 : CPL_IGNORE_RET_VAL(
4241 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4242 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName,
4243 0 : static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
4244 : poDS->GetRasterYSize(), poDS->GetRasterCount(),
4245 0 : poDS->GetDescription()));
4246 :
4247 0 : return TRUE;
4248 : }
4249 :
4250 0 : static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
4251 : {
4252 :
4253 : // Don't list shared datasets. They have already been listed by
4254 : // GDALDumpOpenSharedDatasetsForeach.
4255 0 : if (poDS->GetShared())
4256 0 : return TRUE;
4257 :
4258 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4259 0 : ? "DriverIsNULL"
4260 0 : : poDS->GetDriver()->GetDescription();
4261 :
4262 0 : poDS->Reference();
4263 0 : CPL_IGNORE_RET_VAL(
4264 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4265 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
4266 : poDS->GetRasterXSize(), poDS->GetRasterYSize(),
4267 0 : poDS->GetRasterCount(), poDS->GetDescription()));
4268 :
4269 0 : return TRUE;
4270 : }
4271 :
4272 : /**
4273 : * \brief List open datasets.
4274 : *
4275 : * Dumps a list of all open datasets (shared or not) to the indicated
4276 : * text file (may be stdout or stderr). This function is primarily intended
4277 : * to assist in debugging "dataset leaks" and reference counting issues.
4278 : * The information reported includes the dataset name, referenced count,
4279 : * shared status, driver name, size, and band count.
4280 : */
4281 :
4282 265 : int CPL_STDCALL GDALDumpOpenDatasets(FILE *fp)
4283 :
4284 : {
4285 265 : VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
4286 :
4287 530 : CPLMutexHolderD(&hDLMutex);
4288 :
4289 265 : if (poAllDatasetMap == nullptr)
4290 265 : return 0;
4291 :
4292 0 : CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
4293 :
4294 0 : for (const auto &oIter : *poAllDatasetMap)
4295 : {
4296 0 : GDALDumpOpenDatasetsForeach(oIter.first, fp);
4297 : }
4298 :
4299 0 : if (phSharedDatasetSet != nullptr)
4300 : {
4301 0 : CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach,
4302 : fp);
4303 : }
4304 0 : return static_cast<int>(poAllDatasetMap->size());
4305 : }
4306 :
4307 : /************************************************************************/
4308 : /* BeginAsyncReader() */
4309 : /************************************************************************/
4310 :
4311 : /**
4312 : * \brief Sets up an asynchronous data request
4313 : *
4314 : * This method establish an asynchronous raster read request for the
4315 : * indicated window on the dataset into the indicated buffer. The parameters
4316 : * for windowing, buffer size, buffer type and buffer organization are similar
4317 : * to those for GDALDataset::RasterIO(); however, this call only launches
4318 : * the request and filling the buffer is accomplished via calls to
4319 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4320 : *
4321 : * Once all processing for the created session is complete, or if no further
4322 : * refinement of the request is required, the GDALAsyncReader object should
4323 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4324 : *
4325 : * Note that the data buffer (pData) will potentially continue to be
4326 : * updated as long as the session lives, but it is not deallocated when
4327 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4328 : * should be deallocated by the application at that point.
4329 : *
4330 : * Additional information on asynchronous IO in GDAL may be found at:
4331 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4332 : *
4333 : * This method is the same as the C GDALBeginAsyncReader() function.
4334 : *
4335 : * @param nXOff The pixel offset to the top left corner of the region
4336 : * of the band to be accessed. This would be zero to start from the left side.
4337 : *
4338 : * @param nYOff The line offset to the top left corner of the region
4339 : * of the band to be accessed. This would be zero to start from the top.
4340 : *
4341 : * @param nXSize The width of the region of the band to be accessed in pixels.
4342 : *
4343 : * @param nYSize The height of the region of the band to be accessed in lines.
4344 : *
4345 : * @param pBuf The buffer into which the data should be read. This buffer must
4346 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4347 : * It is organized in left to right,top to bottom pixel order. Spacing is
4348 : * controlled by the nPixelSpace, and nLineSpace parameters.
4349 : *
4350 : * @param nBufXSize the width of the buffer image into which the desired region
4351 : * is to be read, or from which it is to be written.
4352 : *
4353 : * @param nBufYSize the height of the buffer image into which the desired
4354 : * region is to be read, or from which it is to be written.
4355 : *
4356 : * @param eBufType the type of the pixel values in the pData data buffer. The
4357 : * pixel values will automatically be translated to/from the GDALRasterBand
4358 : * data type as needed.
4359 : *
4360 : * @param nBandCount the number of bands being read or written.
4361 : *
4362 : * @param panBandMap the list of nBandCount band numbers being read/written.
4363 : * Note band numbers are 1 based. This may be NULL to select the first
4364 : * nBandCount bands.
4365 : *
4366 : * @param nPixelSpace The byte offset from the start of one pixel value in
4367 : * pData to the start of the next pixel value within a scanline. If defaulted
4368 : * (0) the size of the datatype eBufType is used.
4369 : *
4370 : * @param nLineSpace The byte offset from the start of one scanline in
4371 : * pData to the start of the next. If defaulted the size of the datatype
4372 : * eBufType * nBufXSize is used.
4373 : *
4374 : * @param nBandSpace the byte offset from the start of one bands data to the
4375 : * start of the next. If defaulted (zero) the value will be
4376 : * nLineSpace * nBufYSize implying band sequential organization
4377 : * of the data buffer.
4378 : *
4379 : * @param papszOptions Driver specific control options in a string list or NULL.
4380 : * Consult driver documentation for options supported.
4381 : *
4382 : * @return The GDALAsyncReader object representing the request.
4383 : */
4384 :
4385 1 : GDALAsyncReader *GDALDataset::BeginAsyncReader(
4386 : int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
4387 : int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
4388 : int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions)
4389 : {
4390 : // See gdaldefaultasync.cpp
4391 :
4392 1 : return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
4393 : nBufXSize, nBufYSize, eBufType, nBandCount,
4394 : panBandMap, nPixelSpace, nLineSpace,
4395 1 : nBandSpace, papszOptions);
4396 : }
4397 :
4398 : /************************************************************************/
4399 : /* GDALBeginAsyncReader() */
4400 : /************************************************************************/
4401 :
4402 : /**
4403 : * \brief Sets up an asynchronous data request
4404 : *
4405 : * This method establish an asynchronous raster read request for the
4406 : * indicated window on the dataset into the indicated buffer. The parameters
4407 : * for windowing, buffer size, buffer type and buffer organization are similar
4408 : * to those for GDALDataset::RasterIO(); however, this call only launches
4409 : * the request and filling the buffer is accomplished via calls to
4410 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4411 : *
4412 : * Once all processing for the created session is complete, or if no further
4413 : * refinement of the request is required, the GDALAsyncReader object should
4414 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4415 : *
4416 : * Note that the data buffer (pData) will potentially continue to be
4417 : * updated as long as the session lives, but it is not deallocated when
4418 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4419 : * should be deallocated by the application at that point.
4420 : *
4421 : * Additional information on asynchronous IO in GDAL may be found at:
4422 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4423 : *
4424 : * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
4425 : *
4426 : * @param hDS handle to the dataset object.
4427 : *
4428 : * @param nXOff The pixel offset to the top left corner of the region
4429 : * of the band to be accessed. This would be zero to start from the left side.
4430 : *
4431 : * @param nYOff The line offset to the top left corner of the region
4432 : * of the band to be accessed. This would be zero to start from the top.
4433 : *
4434 : * @param nXSize The width of the region of the band to be accessed in pixels.
4435 : *
4436 : * @param nYSize The height of the region of the band to be accessed in lines.
4437 : *
4438 : * @param pBuf The buffer into which the data should be read. This buffer must
4439 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4440 : * It is organized in left to right,top to bottom pixel order. Spacing is
4441 : * controlled by the nPixelSpace, and nLineSpace parameters.
4442 : *
4443 : * @param nBufXSize the width of the buffer image into which the desired region
4444 : * is to be read, or from which it is to be written.
4445 : *
4446 : * @param nBufYSize the height of the buffer image into which the desired
4447 : * region is to be read, or from which it is to be written.
4448 : *
4449 : * @param eBufType the type of the pixel values in the pData data buffer. The
4450 : * pixel values will automatically be translated to/from the GDALRasterBand
4451 : * data type as needed.
4452 : *
4453 : * @param nBandCount the number of bands being read or written.
4454 : *
4455 : * @param panBandMap the list of nBandCount band numbers being read/written.
4456 : * Note band numbers are 1 based. This may be NULL to select the first
4457 : * nBandCount bands.
4458 : *
4459 : * @param nPixelSpace The byte offset from the start of one pixel value in
4460 : * pData to the start of the next pixel value within a scanline. If defaulted
4461 : * (0) the size of the datatype eBufType is used.
4462 : *
4463 : * @param nLineSpace The byte offset from the start of one scanline in
4464 : * pData to the start of the next. If defaulted the size of the datatype
4465 : * eBufType * nBufXSize is used.
4466 : *
4467 : * @param nBandSpace the byte offset from the start of one bands data to the
4468 : * start of the next. If defaulted (zero) the value will be
4469 : * nLineSpace * nBufYSize implying band sequential organization
4470 : * of the data buffer.
4471 : *
4472 : * @param papszOptions Driver specific control options in a string list or NULL.
4473 : * Consult driver documentation for options supported.
4474 : *
4475 : * @return handle representing the request.
4476 : */
4477 :
4478 2 : GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(
4479 : GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf,
4480 : int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount,
4481 : int *panBandMap, int nPixelSpace, int nLineSpace, int nBandSpace,
4482 : CSLConstList papszOptions)
4483 :
4484 : {
4485 2 : VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
4486 : return static_cast<GDALAsyncReaderH>(
4487 2 : GDALDataset::FromHandle(hDS)->BeginAsyncReader(
4488 : nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
4489 : nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
4490 2 : const_cast<char **>(papszOptions)));
4491 : }
4492 :
4493 : /************************************************************************/
4494 : /* EndAsyncReader() */
4495 : /************************************************************************/
4496 :
4497 : /**
4498 : * End asynchronous request.
4499 : *
4500 : * This method destroys an asynchronous io request and recovers all
4501 : * resources associated with it.
4502 : *
4503 : * This method is the same as the C function GDALEndAsyncReader().
4504 : *
4505 : * @param poARIO pointer to a GDALAsyncReader
4506 : */
4507 :
4508 1 : void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO)
4509 : {
4510 1 : delete poARIO;
4511 1 : }
4512 :
4513 : /************************************************************************/
4514 : /* GDALEndAsyncReader() */
4515 : /************************************************************************/
4516 :
4517 : /**
4518 : * End asynchronous request.
4519 : *
4520 : * This method destroys an asynchronous io request and recovers all
4521 : * resources associated with it.
4522 : *
4523 : * This method is the same as the C++ method GDALDataset::EndAsyncReader().
4524 : *
4525 : * @param hDS handle to the dataset object.
4526 : * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
4527 : */
4528 :
4529 1 : void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS,
4530 : GDALAsyncReaderH hAsyncReaderH)
4531 : {
4532 1 : VALIDATE_POINTER0(hDS, "GDALDataset");
4533 1 : VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
4534 1 : GDALDataset::FromHandle(hDS)->EndAsyncReader(
4535 1 : static_cast<GDALAsyncReader *>(hAsyncReaderH));
4536 : }
4537 :
4538 : /************************************************************************/
4539 : /* CloseDependentDatasets() */
4540 : /************************************************************************/
4541 :
4542 : /**
4543 : * Drop references to any other datasets referenced by this dataset.
4544 : *
4545 : * This method should release any reference to other datasets (e.g. a VRT
4546 : * dataset to its sources), but not close the current dataset itself.
4547 : *
4548 : * If at least, one reference to a dependent dataset has been dropped,
4549 : * this method should return TRUE. Otherwise it *should* return FALSE.
4550 : * (Failure to return the proper value might result in infinite loop)
4551 : *
4552 : * This method can be called several times on a given dataset. After
4553 : * the first time, it should not do anything and return FALSE.
4554 : *
4555 : * The driver implementation may choose to destroy its raster bands,
4556 : * so be careful not to call any method on the raster bands afterwards.
4557 : *
4558 : * Basically the only safe action you can do after calling
4559 : * CloseDependentDatasets() is to call the destructor.
4560 : *
4561 : * Note: the only legitimate caller of CloseDependentDatasets() is
4562 : * GDALDriverManager::~GDALDriverManager()
4563 : *
4564 : * @return TRUE if at least one reference to another dataset has been dropped.
4565 : */
4566 18871 : int GDALDataset::CloseDependentDatasets()
4567 : {
4568 18871 : return oOvManager.CloseDependentDatasets();
4569 : }
4570 :
4571 : /************************************************************************/
4572 : /* ReportError() */
4573 : /************************************************************************/
4574 :
4575 : #ifndef DOXYGEN_XML
4576 : /**
4577 : * \brief Emits an error related to a dataset.
4578 : *
4579 : * This function is a wrapper for regular CPLError(). The only difference
4580 : * with CPLError() is that it prepends the error message with the dataset
4581 : * name.
4582 : *
4583 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4584 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4585 : * @param fmt a printf() style format string. Any additional arguments
4586 : * will be treated as arguments to fill in this format in a manner
4587 : * similar to printf().
4588 : *
4589 : * @since GDAL 1.9.0
4590 : */
4591 :
4592 98 : void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4593 : const char *fmt, ...) const
4594 : {
4595 : va_list args;
4596 98 : va_start(args, fmt);
4597 98 : ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4598 98 : va_end(args);
4599 98 : }
4600 :
4601 : /**
4602 : * \brief Emits an error related to a dataset (static method)
4603 : *
4604 : * This function is a wrapper for regular CPLError(). The only difference
4605 : * with CPLError() is that it prepends the error message with the dataset
4606 : * name.
4607 : *
4608 : * @param pszDSName dataset name.
4609 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4610 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4611 : * @param fmt a printf() style format string. Any additional arguments
4612 : * will be treated as arguments to fill in this format in a manner
4613 : * similar to printf().
4614 : *
4615 : * @since GDAL 3.2.0
4616 : */
4617 :
4618 108 : void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,
4619 : CPLErrorNum err_no, const char *fmt, ...)
4620 : {
4621 : va_list args;
4622 108 : va_start(args, fmt);
4623 108 : ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4624 108 : va_end(args);
4625 108 : }
4626 :
4627 206 : void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,
4628 : CPLErrorNum err_no, const char *fmt,
4629 : va_list args)
4630 : {
4631 206 : pszDSName = CPLGetFilename(pszDSName);
4632 206 : if (pszDSName[0] != '\0')
4633 : {
4634 192 : CPLError(eErrClass, err_no, "%s",
4635 384 : std::string(pszDSName)
4636 192 : .append(": ")
4637 384 : .append(CPLString().vPrintf(fmt, args))
4638 : .c_str());
4639 : }
4640 : else
4641 : {
4642 14 : CPLErrorV(eErrClass, err_no, fmt, args);
4643 : }
4644 206 : }
4645 : #endif
4646 :
4647 : /************************************************************************/
4648 : /* GetMetadata() */
4649 : /************************************************************************/
4650 69555 : char **GDALDataset::GetMetadata(const char *pszDomain)
4651 : {
4652 : #ifndef WITHOUT_DERIVED
4653 69555 : if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
4654 : {
4655 10 : oDerivedMetadataList.Clear();
4656 :
4657 : // First condition: at least one raster band.
4658 10 : if (GetRasterCount() > 0)
4659 : {
4660 : // Check if there is at least one complex band.
4661 10 : bool hasAComplexBand = false;
4662 :
4663 19 : for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4664 : {
4665 11 : if (GDALDataTypeIsComplex(
4666 11 : GetRasterBand(rasterId)->GetRasterDataType()))
4667 : {
4668 2 : hasAComplexBand = true;
4669 2 : break;
4670 : }
4671 : }
4672 :
4673 10 : unsigned int nbSupportedDerivedDS = 0;
4674 : const DerivedDatasetDescription *poDDSDesc =
4675 10 : GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4676 :
4677 10 : int nNumDataset = 1;
4678 80 : for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4679 : ++derivedId)
4680 : {
4681 126 : if (hasAComplexBand ||
4682 126 : CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4683 : "complex")
4684 : {
4685 : oDerivedMetadataList.SetNameValue(
4686 : CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4687 : CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4688 22 : poDDSDesc[derivedId].pszDatasetName,
4689 22 : GetDescription()));
4690 :
4691 : CPLString osDesc(
4692 : CPLSPrintf("%s from %s",
4693 22 : poDDSDesc[derivedId].pszDatasetDescription,
4694 22 : GetDescription()));
4695 : oDerivedMetadataList.SetNameValue(
4696 : CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4697 22 : osDesc.c_str());
4698 :
4699 22 : nNumDataset++;
4700 : }
4701 : }
4702 : }
4703 10 : return oDerivedMetadataList.List();
4704 : }
4705 : #endif
4706 :
4707 69545 : return GDALMajorObject::GetMetadata(pszDomain);
4708 : }
4709 :
4710 : // clang-format off
4711 :
4712 : /**
4713 : * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
4714 : * \brief Set metadata.
4715 : *
4716 : * CAUTION: depending on the format, older values of the updated information
4717 : * might still be found in the file in a "ghost" state, even if no longer
4718 : * accessible through the GDAL API. This is for example the case of the GTiff
4719 : * format (this is not a exhaustive list)
4720 : *
4721 : * The C function GDALSetMetadata() does the same thing as this method.
4722 : *
4723 : * @param papszMetadata the metadata in name=value string list format to
4724 : * apply.
4725 : * @param pszDomain the domain of interest. Use "" or NULL for the default
4726 : * domain.
4727 : * @return CE_None on success, CE_Failure on failure and CE_Warning if the
4728 : * metadata has been accepted, but is likely not maintained persistently
4729 : * by the underlying object between sessions.
4730 : */
4731 :
4732 : /**
4733 : * \fn GDALDataset::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
4734 : * \brief Set single metadata item.
4735 : *
4736 : * CAUTION: depending on the format, older values of the updated information
4737 : * might still be found in the file in a "ghost" state, even if no longer
4738 : * accessible through the GDAL API. This is for example the case of the GTiff
4739 : * format (this is not a exhaustive list)
4740 : *
4741 : * The C function GDALSetMetadataItem() does the same thing as this method.
4742 : *
4743 : * @param pszName the key for the metadata item to fetch.
4744 : * @param pszValue the value to assign to the key.
4745 : * @param pszDomain the domain to set within, use NULL for the default domain.
4746 : *
4747 : * @return CE_None on success, or an error code on failure.
4748 : */
4749 :
4750 : // clang-format on
4751 :
4752 : /************************************************************************/
4753 : /* GetMetadataDomainList() */
4754 : /************************************************************************/
4755 :
4756 926 : char **GDALDataset::GetMetadataDomainList()
4757 : {
4758 926 : char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
4759 :
4760 : // Ensure that we do not duplicate DERIVED domain.
4761 1066 : if (GetRasterCount() > 0 &&
4762 140 : CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
4763 : {
4764 : currentDomainList =
4765 140 : CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
4766 : }
4767 926 : return currentDomainList;
4768 : }
4769 :
4770 : /************************************************************************/
4771 : /* GetDriverName() */
4772 : /************************************************************************/
4773 :
4774 : /** Return driver name.
4775 : * @return driver name.
4776 : */
4777 2056 : const char *GDALDataset::GetDriverName()
4778 : {
4779 2056 : if (poDriver)
4780 2044 : return poDriver->GetDescription();
4781 12 : return "";
4782 : }
4783 :
4784 : /************************************************************************/
4785 : /* GDALDatasetReleaseResultSet() */
4786 : /************************************************************************/
4787 :
4788 : /**
4789 : \brief Release results of ExecuteSQL().
4790 :
4791 : This function should only be used to deallocate OGRLayers resulting from
4792 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
4793 : results set before destroying the GDALDataset may cause errors.
4794 :
4795 : This function is the same as the C++ method GDALDataset::ReleaseResultSet()
4796 :
4797 : @since GDAL 2.0
4798 :
4799 : @param hDS the dataset handle.
4800 : @param hLayer the result of a previous ExecuteSQL() call.
4801 :
4802 : */
4803 3406 : void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)
4804 :
4805 : {
4806 3406 : VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
4807 :
4808 : #ifdef OGRAPISPY_ENABLED
4809 3406 : if (bOGRAPISpyEnabled)
4810 6 : OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
4811 : #endif
4812 :
4813 6812 : GDALDataset::FromHandle(hDS)->ReleaseResultSet(
4814 3406 : OGRLayer::FromHandle(hLayer));
4815 : }
4816 :
4817 : /************************************************************************/
4818 : /* GDALDatasetGetLayerCount() */
4819 : /************************************************************************/
4820 :
4821 : /**
4822 : \brief Get the number of layers in this dataset.
4823 :
4824 : This function is the same as the C++ method GDALDataset::GetLayerCount()
4825 :
4826 : @since GDAL 2.0
4827 :
4828 : @param hDS the dataset handle.
4829 : @return layer count.
4830 : */
4831 :
4832 1448 : int GDALDatasetGetLayerCount(GDALDatasetH hDS)
4833 :
4834 : {
4835 1448 : VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
4836 :
4837 : #ifdef OGRAPISPY_ENABLED
4838 1448 : if (bOGRAPISpyEnabled)
4839 2 : OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
4840 : #endif
4841 :
4842 1448 : return GDALDataset::FromHandle(hDS)->GetLayerCount();
4843 : }
4844 :
4845 : /************************************************************************/
4846 : /* GDALDatasetGetLayer() */
4847 : /************************************************************************/
4848 :
4849 : /**
4850 : \brief Fetch a layer by index.
4851 :
4852 : The returned layer remains owned by the
4853 : GDALDataset and should not be deleted by the application.
4854 :
4855 : This function is the same as the C++ method GDALDataset::GetLayer()
4856 :
4857 : @since GDAL 2.0
4858 :
4859 : @param hDS the dataset handle.
4860 : @param iLayer a layer number between 0 and GetLayerCount()-1.
4861 :
4862 : @return the layer, or NULL if iLayer is out of range or an error occurs.
4863 : */
4864 :
4865 9171 : OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)
4866 :
4867 : {
4868 9171 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
4869 :
4870 : OGRLayerH hLayer =
4871 9171 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
4872 :
4873 : #ifdef OGRAPISPY_ENABLED
4874 9171 : if (bOGRAPISpyEnabled)
4875 3 : OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
4876 : #endif
4877 :
4878 9171 : return hLayer;
4879 : }
4880 :
4881 : /************************************************************************/
4882 : /* GDALDatasetGetLayerByName() */
4883 : /************************************************************************/
4884 :
4885 : /**
4886 : \brief Fetch a layer by name.
4887 :
4888 : The returned layer remains owned by the
4889 : GDALDataset and should not be deleted by the application.
4890 :
4891 : This function is the same as the C++ method GDALDataset::GetLayerByName()
4892 :
4893 : @since GDAL 2.0
4894 :
4895 : @param hDS the dataset handle.
4896 : @param pszName the layer name of the layer to fetch.
4897 :
4898 : @return the layer, or NULL if Layer is not found or an error occurs.
4899 : */
4900 :
4901 3378 : OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)
4902 :
4903 : {
4904 3378 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
4905 :
4906 3378 : OGRLayerH hLayer = OGRLayer::ToHandle(
4907 3378 : GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
4908 :
4909 : #ifdef OGRAPISPY_ENABLED
4910 3378 : if (bOGRAPISpyEnabled)
4911 4 : OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
4912 : #endif
4913 :
4914 3378 : return hLayer;
4915 : }
4916 :
4917 : /************************************************************************/
4918 : /* GDALDatasetIsLayerPrivate() */
4919 : /************************************************************************/
4920 :
4921 : /**
4922 : \brief Returns true if the layer at the specified index is deemed a private or
4923 : system table, or an internal detail only.
4924 :
4925 : This function is the same as the C++ method GDALDataset::IsLayerPrivate()
4926 :
4927 : @since GDAL 3.4
4928 :
4929 : @param hDS the dataset handle.
4930 : @param iLayer a layer number between 0 and GetLayerCount()-1.
4931 :
4932 : @return true if the layer is a private or system table.
4933 : */
4934 :
4935 91 : int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)
4936 :
4937 : {
4938 91 : VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);
4939 :
4940 91 : const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);
4941 :
4942 91 : return res ? 1 : 0;
4943 : }
4944 :
4945 : /************************************************************************/
4946 : /* GetLayerIndex() */
4947 : /************************************************************************/
4948 :
4949 : /**
4950 : \brief Returns the index of the layer specified by name.
4951 :
4952 : @since GDAL 3.12
4953 :
4954 : @param pszName layer name (not NULL)
4955 :
4956 : @return an index >= 0, or -1 if not found.
4957 : */
4958 :
4959 3 : int GDALDataset::GetLayerIndex(const char *pszName)
4960 : {
4961 3 : const int nLayerCount = GetLayerCount();
4962 3 : int iMatch = -1;
4963 6 : for (int i = 0; i < nLayerCount; ++i)
4964 : {
4965 5 : if (const auto poLayer = GetLayer(i))
4966 : {
4967 5 : const char *pszLayerName = poLayer->GetDescription();
4968 5 : if (strcmp(pszName, pszLayerName) == 0)
4969 : {
4970 2 : iMatch = i;
4971 2 : break;
4972 : }
4973 3 : else if (EQUAL(pszName, pszLayerName))
4974 : {
4975 0 : iMatch = i;
4976 : }
4977 : }
4978 : }
4979 3 : return iMatch;
4980 : }
4981 :
4982 : /************************************************************************/
4983 : /* GDALDatasetDeleteLayer() */
4984 : /************************************************************************/
4985 :
4986 : /**
4987 : \brief Delete the indicated layer from the datasource.
4988 :
4989 : If this function is supported
4990 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
4991 :
4992 : This method is the same as the C++ method GDALDataset::DeleteLayer().
4993 :
4994 : @since GDAL 2.0
4995 :
4996 : @param hDS the dataset handle.
4997 : @param iLayer the index of the layer to delete.
4998 :
4999 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
5000 : layers is not supported for this datasource.
5001 :
5002 : */
5003 40 : OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)
5004 :
5005 : {
5006 40 : VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
5007 :
5008 : #ifdef OGRAPISPY_ENABLED
5009 40 : if (bOGRAPISpyEnabled)
5010 2 : OGRAPISpy_DS_DeleteLayer(hDS, iLayer);
5011 : #endif
5012 :
5013 40 : return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
5014 : }
5015 :
5016 : /************************************************************************/
5017 : /* CreateLayer() */
5018 : /************************************************************************/
5019 :
5020 : /**
5021 : \brief This method attempts to create a new layer on the dataset with the
5022 : indicated name, coordinate system, geometry type.
5023 :
5024 : The papszOptions argument
5025 : can be used to control driver specific creation options. These options are
5026 : normally documented in the format specific documentation.
5027 : That function will try to validate the creation option list passed to the
5028 : driver with the GDALValidateCreationOptions() method. This check can be
5029 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5030 : to NO.
5031 :
5032 : Drivers should extend the ICreateLayer() method and not
5033 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5034 : delegating the actual work to ICreateLayer().
5035 :
5036 : This method is the same as the C function GDALDatasetCreateLayer() and the
5037 : deprecated OGR_DS_CreateLayer().
5038 :
5039 : Example:
5040 :
5041 : \code{.cpp}
5042 : #include "gdal.h"
5043 : #include "cpl_string.h"
5044 :
5045 : ...
5046 :
5047 : OGRLayer *poLayer;
5048 : char **papszOptions;
5049 :
5050 : if( !poDS->TestCapability( ODsCCreateLayer ) )
5051 : {
5052 : ...
5053 : }
5054 :
5055 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5056 : poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
5057 : papszOptions );
5058 : CSLDestroy( papszOptions );
5059 :
5060 : if( poLayer == NULL )
5061 : {
5062 : ...
5063 : }
5064 : \endcode
5065 :
5066 : @param pszName the name for the new layer. This should ideally not
5067 : match any existing layer on the datasource.
5068 : @param poSpatialRef the coordinate system to use for the new layer, or NULL if
5069 : no coordinate system is available.
5070 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5071 : are no constraints on the types geometry to be written.
5072 : @param papszOptions a StringList of name=value options. Options are driver
5073 : specific.
5074 :
5075 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5076 :
5077 : */
5078 :
5079 7734 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5080 : const OGRSpatialReference *poSpatialRef,
5081 : OGRwkbGeometryType eGType,
5082 : CSLConstList papszOptions)
5083 :
5084 : {
5085 7734 : if (eGType == wkbNone)
5086 : {
5087 452 : return CreateLayer(pszName, nullptr, papszOptions);
5088 : }
5089 : else
5090 : {
5091 14564 : OGRGeomFieldDefn oGeomFieldDefn("", eGType);
5092 7282 : oGeomFieldDefn.SetSpatialRef(poSpatialRef);
5093 7282 : return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5094 : }
5095 : }
5096 :
5097 : /**
5098 : \brief This method attempts to create a new layer on the dataset with the
5099 : indicated name and geometry field definition.
5100 :
5101 : When poGeomFieldDefn is not null, most drivers should honor
5102 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5103 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5104 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5105 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5106 : very few currently.
5107 :
5108 : Note that even if a geometry coordinate precision is set and a driver honors the
5109 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5110 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5111 : with the coordinate precision. That is they are assumed to be valid once their
5112 : coordinates are rounded to it. If it might not be the case, the user may set
5113 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5114 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5115 : the passed geometries.
5116 :
5117 : The papszOptions argument
5118 : can be used to control driver specific creation options. These options are
5119 : normally documented in the format specific documentation.
5120 : This function will try to validate the creation option list passed to the
5121 : driver with the GDALValidateCreationOptions() method. This check can be
5122 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5123 : to NO.
5124 :
5125 : Drivers should extend the ICreateLayer() method and not
5126 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5127 : delegating the actual work to ICreateLayer().
5128 :
5129 : This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().
5130 :
5131 : @param pszName the name for the new layer. This should ideally not
5132 : match any existing layer on the datasource.
5133 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5134 : or NULL if there is no geometry field.
5135 : @param papszOptions a StringList of name=value options. Options are driver
5136 : specific.
5137 :
5138 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5139 : @since 3.9
5140 :
5141 : */
5142 :
5143 8778 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5144 : const OGRGeomFieldDefn *poGeomFieldDefn,
5145 : CSLConstList papszOptions)
5146 :
5147 : {
5148 8778 : if (CPLTestBool(
5149 : CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
5150 : {
5151 8778 : ValidateLayerCreationOptions(papszOptions);
5152 : }
5153 :
5154 : OGRLayer *poLayer;
5155 8778 : if (poGeomFieldDefn)
5156 : {
5157 8098 : OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);
5158 8191 : if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&
5159 93 : !TestCapability(ODsCCurveGeometries))
5160 : {
5161 23 : oGeomFieldDefn.SetType(
5162 : OGR_GT_GetLinear(poGeomFieldDefn->GetType()));
5163 : }
5164 :
5165 8098 : poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5166 : }
5167 : else
5168 : {
5169 680 : poLayer = ICreateLayer(pszName, nullptr, papszOptions);
5170 : }
5171 : #ifdef DEBUG
5172 8848 : if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
5173 70 : !poLayer->TestCapability(OLCCurveGeometries))
5174 : {
5175 0 : CPLError(CE_Warning, CPLE_AppDefined,
5176 : "Inconsistent driver: Layer geometry type is non-linear, but "
5177 : "TestCapability(OLCCurveGeometries) returns FALSE.");
5178 : }
5179 : #endif
5180 :
5181 8778 : return poLayer;
5182 : }
5183 :
5184 : //! @cond Doxygen_Suppress
5185 :
5186 : // Technical override to avoid ambiguous choice between the old and new
5187 : // new CreateLayer() signatures.
5188 11 : OGRLayer *GDALDataset::CreateLayer(const char *pszName)
5189 : {
5190 22 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5191 22 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5192 : }
5193 :
5194 : // Technical override to avoid ambiguous choice between the old and new
5195 : // new CreateLayer() signatures.
5196 1 : OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)
5197 : {
5198 2 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5199 2 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5200 : }
5201 :
5202 : //!@endcond
5203 :
5204 : /************************************************************************/
5205 : /* GDALDatasetCreateLayer() */
5206 : /************************************************************************/
5207 :
5208 : /**
5209 : \brief This function attempts to create a new layer on the dataset with the
5210 : indicated name, coordinate system, geometry type.
5211 :
5212 : The papszOptions argument can be used to control driver specific creation
5213 : options. These options are normally documented in the format specific
5214 : documentation.
5215 :
5216 : This method is the same as the C++ method GDALDataset::CreateLayer().
5217 :
5218 : Example:
5219 :
5220 : \code{.c}
5221 : #include "gdal.h"
5222 : #include "cpl_string.h"
5223 :
5224 : ...
5225 :
5226 : OGRLayerH hLayer;
5227 : char **papszOptions;
5228 :
5229 : if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
5230 : {
5231 : ...
5232 : }
5233 :
5234 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5235 : hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
5236 : papszOptions );
5237 : CSLDestroy( papszOptions );
5238 :
5239 : if( hLayer == NULL )
5240 : {
5241 : ...
5242 : }
5243 : \endcode
5244 :
5245 : @since GDAL 2.0
5246 :
5247 : @param hDS the dataset handle
5248 : @param pszName the name for the new layer. This should ideally not
5249 : match any existing layer on the datasource.
5250 : @param hSpatialRef the coordinate system to use for the new layer, or NULL if
5251 : no coordinate system is available.
5252 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5253 : are no constraints on the types geometry to be written.
5254 : @param papszOptions a StringList of name=value options. Options are driver
5255 : specific.
5256 :
5257 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5258 :
5259 : */
5260 :
5261 5902 : OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,
5262 : OGRSpatialReferenceH hSpatialRef,
5263 : OGRwkbGeometryType eGType,
5264 : CSLConstList papszOptions)
5265 :
5266 : {
5267 5902 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
5268 :
5269 5902 : if (pszName == nullptr)
5270 : {
5271 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5272 : "Name was NULL in GDALDatasetCreateLayer");
5273 0 : return nullptr;
5274 : }
5275 :
5276 : OGRLayerH hLayer =
5277 11804 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5278 5902 : pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,
5279 : const_cast<char **>(papszOptions)));
5280 :
5281 : #ifdef OGRAPISPY_ENABLED
5282 5902 : if (bOGRAPISpyEnabled)
5283 8 : OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,
5284 : const_cast<char **>(papszOptions), hLayer);
5285 : #endif
5286 :
5287 5902 : return hLayer;
5288 : }
5289 :
5290 : /************************************************************************/
5291 : /* GDALDatasetCreateLayerFromGeomFieldDefn() */
5292 : /************************************************************************/
5293 :
5294 : /**
5295 : \brief This function attempts to create a new layer on the dataset with the
5296 : indicated name and geometry field.
5297 :
5298 : When poGeomFieldDefn is not null, most drivers should honor
5299 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5300 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5301 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5302 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5303 : very few currently.
5304 :
5305 : Note that even if a geometry coordinate precision is set and a driver honors the
5306 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5307 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5308 : with the coordinate precision. That is they are assumed to be valid once their
5309 : coordinates are rounded to it. If it might not be the case, the user may set
5310 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5311 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5312 : the passed geometries.
5313 :
5314 : The papszOptions argument can be used to control driver specific creation
5315 : options. These options are normally documented in the format specific
5316 : documentation.
5317 :
5318 : This method is the same as the C++ method GDALDataset::CreateLayer().
5319 :
5320 : @param hDS the dataset handle
5321 : @param pszName the name for the new layer. This should ideally not
5322 : match any existing layer on the datasource.
5323 : @param hGeomFieldDefn the geometry field definition. May be NULL to indicate
5324 : a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()
5325 : for drivers supporting that interface).
5326 : @param papszOptions a StringList of name=value options. Options are driver
5327 : specific.
5328 :
5329 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5330 :
5331 : @since GDAL 3.9
5332 :
5333 : */
5334 :
5335 : OGRLayerH
5336 14 : GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,
5337 : OGRGeomFieldDefnH hGeomFieldDefn,
5338 : CSLConstList papszOptions)
5339 :
5340 : {
5341 14 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);
5342 :
5343 14 : if (!pszName)
5344 : {
5345 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5346 : "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");
5347 0 : return nullptr;
5348 : }
5349 :
5350 : OGRLayerH hLayer =
5351 28 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5352 14 : pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),
5353 : papszOptions));
5354 14 : return hLayer;
5355 : }
5356 :
5357 : /************************************************************************/
5358 : /* GDALDatasetCopyLayer() */
5359 : /************************************************************************/
5360 :
5361 : /**
5362 : \brief Duplicate an existing layer.
5363 :
5364 : This function creates a new layer, duplicate the field definitions of the
5365 : source layer and then duplicate each features of the source layer.
5366 : The papszOptions argument
5367 : can be used to control driver specific creation options. These options are
5368 : normally documented in the format specific documentation.
5369 : The source layer may come from another dataset.
5370 :
5371 : This method is the same as the C++ method GDALDataset::CopyLayer()
5372 :
5373 : @since GDAL 2.0
5374 :
5375 : @param hDS the dataset handle.
5376 : @param hSrcLayer source layer.
5377 : @param pszNewName the name of the layer to create.
5378 : @param papszOptions a StringList of name=value options. Options are driver
5379 : specific.
5380 :
5381 : @return a handle to the layer, or NULL if an error occurs.
5382 : */
5383 12 : OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,
5384 : const char *pszNewName,
5385 : CSLConstList papszOptions)
5386 :
5387 : {
5388 12 : VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
5389 12 : VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
5390 12 : VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
5391 :
5392 24 : return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(
5393 : OGRLayer::FromHandle(hSrcLayer), pszNewName,
5394 24 : const_cast<char **>(papszOptions)));
5395 : }
5396 :
5397 : /************************************************************************/
5398 : /* GDALDatasetExecuteSQL() */
5399 : /************************************************************************/
5400 :
5401 : /**
5402 : \brief Execute an SQL statement against the data store.
5403 :
5404 : The result of an SQL query is either NULL for statements that are in error,
5405 : or that have no results set, or an OGRLayer pointer representing a results
5406 : set from the query. Note that this OGRLayer is in addition to the layers
5407 : in the data store and must be destroyed with
5408 : ReleaseResultSet() before the dataset is closed
5409 : (destroyed).
5410 :
5411 : This method is the same as the C++ method GDALDataset::ExecuteSQL()
5412 :
5413 : For more information on the SQL dialect supported internally by OGR
5414 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
5415 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
5416 : to the underlying RDBMS.
5417 :
5418 : Starting with OGR 1.10, the <a
5419 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
5420 : also be used.
5421 :
5422 : @since GDAL 2.0
5423 :
5424 : @param hDS the dataset handle.
5425 : @param pszStatement the SQL statement to execute.
5426 : @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
5427 :
5428 : @param pszDialect allows control of the statement dialect. If set to NULL, the
5429 : OGR SQL engine will be used, except for RDBMS drivers that will use their
5430 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
5431 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
5432 :
5433 : @return an OGRLayer containing the results of the query. Deallocate with
5434 : GDALDatasetReleaseResultSet().
5435 :
5436 : */
5437 :
5438 10446 : OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,
5439 : OGRGeometryH hSpatialFilter,
5440 : const char *pszDialect)
5441 :
5442 : {
5443 10446 : VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
5444 :
5445 : OGRLayerH hLayer =
5446 20892 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(
5447 10446 : pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));
5448 :
5449 : #ifdef OGRAPISPY_ENABLED
5450 10446 : if (bOGRAPISpyEnabled)
5451 4 : OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,
5452 : hLayer);
5453 : #endif
5454 :
5455 10446 : return hLayer;
5456 : }
5457 :
5458 : /************************************************************************/
5459 : /* GDALDatasetAbortSQL() */
5460 : /************************************************************************/
5461 :
5462 : /**
5463 : \brief Abort any SQL statement running in the data store.
5464 :
5465 : This function can be safely called from any thread (pending that the dataset
5466 : object is still alive). Driver implementations will make sure that it can be
5467 : called in a thread-safe way.
5468 :
5469 : This might not be implemented by all drivers. At time of writing, only SQLite,
5470 : GPKG and PG drivers implement it
5471 :
5472 : This method is the same as the C++ method GDALDataset::AbortSQL()
5473 :
5474 : @since GDAL 3.2.0
5475 :
5476 : @param hDS the dataset handle.
5477 :
5478 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
5479 : is not supported for this datasource. .
5480 :
5481 : */
5482 :
5483 6 : OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)
5484 :
5485 : {
5486 6 : VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);
5487 6 : return GDALDataset::FromHandle(hDS)->AbortSQL();
5488 : }
5489 :
5490 : /************************************************************************/
5491 : /* GDALDatasetGetStyleTable() */
5492 : /************************************************************************/
5493 :
5494 : /**
5495 : \brief Returns dataset style table.
5496 :
5497 : This function is the same as the C++ method GDALDataset::GetStyleTable()
5498 :
5499 : @since GDAL 2.0
5500 :
5501 : @param hDS the dataset handle
5502 : @return handle to a style table which should not be modified or freed by the
5503 : caller.
5504 : */
5505 :
5506 6 : OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)
5507 :
5508 : {
5509 6 : VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
5510 :
5511 : return reinterpret_cast<OGRStyleTableH>(
5512 6 : GDALDataset::FromHandle(hDS)->GetStyleTable());
5513 : }
5514 :
5515 : /************************************************************************/
5516 : /* GDALDatasetSetStyleTableDirectly() */
5517 : /************************************************************************/
5518 :
5519 : /**
5520 : \brief Set dataset style table.
5521 :
5522 : This function operate exactly as GDALDatasetSetStyleTable() except that it
5523 : assumes ownership of the passed table.
5524 :
5525 : This function is the same as the C++ method
5526 : GDALDataset::SetStyleTableDirectly()
5527 :
5528 : @since GDAL 2.0
5529 :
5530 : @param hDS the dataset handle
5531 : @param hStyleTable style table handle to set
5532 :
5533 : */
5534 :
5535 0 : void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,
5536 : OGRStyleTableH hStyleTable)
5537 :
5538 : {
5539 0 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
5540 :
5541 0 : GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(
5542 0 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5543 : }
5544 :
5545 : /************************************************************************/
5546 : /* GDALDatasetSetStyleTable() */
5547 : /************************************************************************/
5548 :
5549 : /**
5550 : \brief Set dataset style table.
5551 :
5552 : This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
5553 : it assumes ownership of the passed table.
5554 :
5555 : This function is the same as the C++ method GDALDataset::SetStyleTable()
5556 :
5557 : @since GDAL 2.0
5558 :
5559 : @param hDS the dataset handle
5560 : @param hStyleTable style table handle to set
5561 :
5562 : */
5563 :
5564 5 : void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)
5565 :
5566 : {
5567 5 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
5568 5 : VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
5569 :
5570 5 : GDALDataset::FromHandle(hDS)->SetStyleTable(
5571 5 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5572 : }
5573 :
5574 : /************************************************************************/
5575 : /* ValidateLayerCreationOptions() */
5576 : /************************************************************************/
5577 :
5578 : //! @cond Doxygen_Suppress
5579 8778 : int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)
5580 : {
5581 : const char *pszOptionList =
5582 8778 : GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5583 8778 : if (pszOptionList == nullptr && poDriver != nullptr)
5584 : {
5585 : pszOptionList =
5586 8769 : poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5587 : }
5588 17556 : CPLString osDataset;
5589 8778 : osDataset.Printf("dataset %s", GetDescription());
5590 8778 : return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",
5591 17556 : osDataset);
5592 : }
5593 :
5594 : //! @endcond
5595 :
5596 : /************************************************************************/
5597 : /* Release() */
5598 : /************************************************************************/
5599 :
5600 : /**
5601 : \brief Drop a reference to this dataset, and if the reference count drops to one
5602 : close (destroy) the dataset.
5603 :
5604 : This method is the same as the C function OGRReleaseDataSource().
5605 :
5606 : @deprecated. In GDAL 2, use GDALClose() instead
5607 :
5608 : @return OGRERR_NONE on success or an error code.
5609 : */
5610 :
5611 2858 : OGRErr GDALDataset::Release()
5612 :
5613 : {
5614 2858 : ReleaseRef();
5615 2858 : return OGRERR_NONE;
5616 : }
5617 :
5618 : /************************************************************************/
5619 : /* GetRefCount() */
5620 : /************************************************************************/
5621 :
5622 : /**
5623 : \brief Fetch reference count.
5624 :
5625 : This method is the same as the C function OGR_DS_GetRefCount().
5626 :
5627 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5628 :
5629 : @return the current reference count for the datasource object itself.
5630 : */
5631 :
5632 914 : int GDALDataset::GetRefCount() const
5633 : {
5634 914 : return nRefCount;
5635 : }
5636 :
5637 : /************************************************************************/
5638 : /* GetSummaryRefCount() */
5639 : /************************************************************************/
5640 :
5641 : /**
5642 : \brief Fetch reference count of datasource and all owned layers.
5643 :
5644 : This method is the same as the C function OGR_DS_GetSummaryRefCount().
5645 :
5646 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5647 :
5648 : @deprecated
5649 :
5650 : @return the current summary reference count for the datasource and its layers.
5651 : */
5652 :
5653 0 : int GDALDataset::GetSummaryRefCount() const
5654 :
5655 : {
5656 0 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5657 0 : int nSummaryCount = nRefCount;
5658 0 : GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
5659 :
5660 0 : for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)
5661 0 : nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
5662 :
5663 0 : return nSummaryCount;
5664 : }
5665 :
5666 : /************************************************************************/
5667 : /* ICreateLayer() */
5668 : /************************************************************************/
5669 :
5670 : /**
5671 : \brief This method attempts to create a new layer on the dataset with the
5672 : indicated name, coordinate system, geometry type.
5673 :
5674 : This method is reserved to implementation by drivers.
5675 :
5676 : The papszOptions argument can be used to control driver specific creation
5677 : options. These options are normally documented in the format specific
5678 : documentation.
5679 :
5680 : @param pszName the name for the new layer. This should ideally not
5681 : match any existing layer on the datasource.
5682 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5683 : or NULL if there is no geometry field.
5684 : @param papszOptions a StringList of name=value options. Options are driver
5685 : specific.
5686 :
5687 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5688 :
5689 : @since GDAL 2.0 (prototype modified in 3.9)
5690 : */
5691 :
5692 : OGRLayer *
5693 16 : GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,
5694 : CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,
5695 : CPL_UNUSED CSLConstList papszOptions)
5696 :
5697 : {
5698 16 : CPLError(CE_Failure, CPLE_NotSupported,
5699 : "CreateLayer() not supported by this dataset.");
5700 :
5701 16 : return nullptr;
5702 : }
5703 :
5704 : /************************************************************************/
5705 : /* CopyLayer() */
5706 : /************************************************************************/
5707 :
5708 : /**
5709 : \brief Duplicate an existing layer.
5710 :
5711 : This method creates a new layer, duplicate the field definitions of the
5712 : source layer and then duplicate each features of the source layer.
5713 : The papszOptions argument
5714 : can be used to control driver specific creation options. These options are
5715 : normally documented in the format specific documentation.
5716 : The source layer may come from another dataset.
5717 :
5718 : This method is the same as the C function GDALDatasetCopyLayer() and the
5719 : deprecated OGR_DS_CopyLayer().
5720 :
5721 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5722 :
5723 : @param poSrcLayer source layer.
5724 : @param pszNewName the name of the layer to create.
5725 : @param papszOptions a StringList of name=value options. Options are driver
5726 : specific. There is a common option to set output layer
5727 : spatial reference: DST_SRSWKT. The option should be in
5728 : WKT format. Starting with GDAL 3.7, the common option
5729 : COPY_MD can be set to NO to prevent the default copying
5730 : of the metadata from the source layer to the target layer.
5731 :
5732 : @return a handle to the layer, or NULL if an error occurs.
5733 : */
5734 :
5735 128 : OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
5736 : char **papszOptions)
5737 :
5738 : {
5739 : /* -------------------------------------------------------------------- */
5740 : /* Create the layer. */
5741 : /* -------------------------------------------------------------------- */
5742 128 : if (!TestCapability(ODsCCreateLayer))
5743 : {
5744 0 : CPLError(CE_Failure, CPLE_NotSupported,
5745 : "This datasource does not support creation of layers.");
5746 0 : return nullptr;
5747 : }
5748 :
5749 128 : const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
5750 256 : OGRSpatialReference oDstSpaRef(pszSRSWKT);
5751 128 : oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5752 128 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
5753 128 : OGRLayer *poDstLayer = nullptr;
5754 :
5755 256 : CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));
5756 128 : aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr);
5757 128 : aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr);
5758 :
5759 128 : CPLErrorReset();
5760 128 : const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
5761 128 : if (nSrcGeomFieldCount == 1)
5762 : {
5763 76 : OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
5764 76 : if (pszSRSWKT)
5765 5 : oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);
5766 76 : poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,
5767 76 : aosCleanedUpOptions.List());
5768 : }
5769 : else
5770 : {
5771 : poDstLayer =
5772 52 : ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());
5773 : }
5774 :
5775 128 : if (poDstLayer == nullptr)
5776 0 : return nullptr;
5777 :
5778 128 : if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))
5779 : {
5780 127 : char **papszMD = poSrcLayer->GetMetadata();
5781 127 : if (papszMD)
5782 7 : poDstLayer->SetMetadata(papszMD);
5783 : }
5784 :
5785 : /* -------------------------------------------------------------------- */
5786 : /* Add fields. Default to copy all fields, and make sure to */
5787 : /* establish a mapping between indices, rather than names, in */
5788 : /* case the target datasource has altered it (e.g. Shapefile */
5789 : /* limited to 10 char field names). */
5790 : /* -------------------------------------------------------------------- */
5791 128 : const int nSrcFieldCount = poSrcDefn->GetFieldCount();
5792 :
5793 : // Initialize the index-to-index map to -1's.
5794 256 : std::vector<int> anMap(nSrcFieldCount, -1);
5795 :
5796 : // Caution: At the time of writing, the MapInfo driver
5797 : // returns NULL until a field has been added.
5798 128 : OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
5799 128 : int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
5800 279 : for (int iField = 0; iField < nSrcFieldCount; ++iField)
5801 : {
5802 151 : OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
5803 302 : OGRFieldDefn oFieldDefn(poSrcFieldDefn);
5804 :
5805 : // The field may have been already created at layer creation.
5806 151 : int iDstField = -1;
5807 151 : if (poDstFDefn)
5808 151 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
5809 151 : if (iDstField >= 0)
5810 : {
5811 0 : anMap[iField] = iDstField;
5812 : }
5813 151 : else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)
5814 : {
5815 : // Now that we've created a field, GetLayerDefn() won't return NULL.
5816 151 : if (poDstFDefn == nullptr)
5817 0 : poDstFDefn = poDstLayer->GetLayerDefn();
5818 :
5819 : // Sanity check: if it fails, the driver is buggy.
5820 302 : if (poDstFDefn != nullptr &&
5821 151 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
5822 : {
5823 0 : CPLError(CE_Warning, CPLE_AppDefined,
5824 : "The output driver has claimed to have added the %s "
5825 : "field, but it did not!",
5826 : oFieldDefn.GetNameRef());
5827 : }
5828 : else
5829 : {
5830 151 : anMap[iField] = nDstFieldCount;
5831 151 : ++nDstFieldCount;
5832 : }
5833 : }
5834 : }
5835 :
5836 : /* -------------------------------------------------------------------- */
5837 128 : std::unique_ptr<OGRCoordinateTransformation> poCT;
5838 128 : OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
5839 128 : if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&
5840 0 : sourceSRS->IsSame(&oDstSpaRef) == FALSE)
5841 : {
5842 0 : poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));
5843 0 : if (nullptr == poCT)
5844 : {
5845 0 : CPLError(CE_Failure, CPLE_NotSupported,
5846 : "This input/output spatial reference is not supported.");
5847 0 : return nullptr;
5848 : }
5849 : }
5850 : /* -------------------------------------------------------------------- */
5851 : /* Create geometry fields. */
5852 : /* -------------------------------------------------------------------- */
5853 129 : if (nSrcGeomFieldCount > 1 &&
5854 1 : TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
5855 : {
5856 :
5857 3 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5858 : {
5859 2 : if (nullptr == pszSRSWKT)
5860 : {
5861 2 : poDstLayer->CreateGeomField(
5862 2 : poSrcDefn->GetGeomFieldDefn(iField));
5863 : }
5864 : else
5865 : {
5866 : OGRGeomFieldDefn *pDstGeomFieldDefn =
5867 0 : poSrcDefn->GetGeomFieldDefn(iField);
5868 0 : pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
5869 0 : poDstLayer->CreateGeomField(pDstGeomFieldDefn);
5870 : }
5871 : }
5872 : }
5873 :
5874 : /* -------------------------------------------------------------------- */
5875 : /* Check if the destination layer supports transactions and set a */
5876 : /* default number of features in a single transaction. */
5877 : /* -------------------------------------------------------------------- */
5878 : const int nGroupTransactions =
5879 128 : poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
5880 :
5881 : /* -------------------------------------------------------------------- */
5882 : /* Transfer features. */
5883 : /* -------------------------------------------------------------------- */
5884 128 : poSrcLayer->ResetReading();
5885 :
5886 128 : if (nGroupTransactions <= 0)
5887 : {
5888 : while (true)
5889 : {
5890 : auto poFeature =
5891 423 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
5892 :
5893 423 : if (poFeature == nullptr)
5894 125 : break;
5895 :
5896 298 : CPLErrorReset();
5897 : auto poDstFeature =
5898 298 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
5899 :
5900 298 : if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=
5901 : OGRERR_NONE)
5902 : {
5903 0 : CPLError(CE_Failure, CPLE_AppDefined,
5904 : "Unable to translate feature " CPL_FRMT_GIB
5905 : " from layer %s.",
5906 0 : poFeature->GetFID(), poSrcDefn->GetName());
5907 0 : return poDstLayer;
5908 : }
5909 :
5910 298 : if (nullptr != poCT)
5911 : {
5912 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5913 : {
5914 0 : OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
5915 0 : if (nullptr == pGeom)
5916 0 : continue;
5917 :
5918 0 : const OGRErr eErr = pGeom->transform(poCT.get());
5919 0 : if (eErr == OGRERR_NONE)
5920 0 : continue;
5921 :
5922 0 : CPLError(CE_Failure, CPLE_AppDefined,
5923 : "Unable to transform geometry " CPL_FRMT_GIB
5924 : " from layer %s.",
5925 0 : poFeature->GetFID(), poSrcDefn->GetName());
5926 0 : return poDstLayer;
5927 : }
5928 : }
5929 :
5930 298 : poDstFeature->SetFID(poFeature->GetFID());
5931 :
5932 298 : CPLErrorReset();
5933 298 : if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)
5934 : {
5935 0 : return poDstLayer;
5936 : }
5937 298 : }
5938 : }
5939 : else
5940 : {
5941 3 : std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;
5942 : try
5943 : {
5944 3 : apoDstFeatures.resize(nGroupTransactions);
5945 : }
5946 0 : catch (const std::exception &e)
5947 : {
5948 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
5949 0 : return poDstLayer;
5950 : }
5951 3 : bool bStopTransfer = false;
5952 6 : while (!bStopTransfer)
5953 : {
5954 : /* --------------------------------------------------------------------
5955 : */
5956 : /* Fill the array with features. */
5957 : /* --------------------------------------------------------------------
5958 : */
5959 : // Number of features in the temporary array.
5960 3 : int nFeatCount = 0; // Used after for.
5961 33 : for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)
5962 : {
5963 : auto poFeature =
5964 33 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
5965 :
5966 33 : if (poFeature == nullptr)
5967 : {
5968 3 : bStopTransfer = true;
5969 3 : break;
5970 : }
5971 :
5972 30 : CPLErrorReset();
5973 30 : apoDstFeatures[nFeatCount] =
5974 60 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
5975 :
5976 60 : if (apoDstFeatures[nFeatCount]->SetFrom(
5977 60 : poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)
5978 : {
5979 0 : CPLError(CE_Failure, CPLE_AppDefined,
5980 : "Unable to translate feature " CPL_FRMT_GIB
5981 : " from layer %s.",
5982 0 : poFeature->GetFID(), poSrcDefn->GetName());
5983 0 : bStopTransfer = true;
5984 0 : poFeature.reset();
5985 0 : break;
5986 : }
5987 :
5988 30 : if (nullptr != poCT)
5989 : {
5990 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5991 : {
5992 : OGRGeometry *pGeom =
5993 0 : apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);
5994 0 : if (nullptr == pGeom)
5995 0 : continue;
5996 :
5997 0 : const OGRErr eErr = pGeom->transform(poCT.get());
5998 0 : if (eErr == OGRERR_NONE)
5999 0 : continue;
6000 :
6001 0 : CPLError(CE_Failure, CPLE_AppDefined,
6002 : "Unable to transform geometry " CPL_FRMT_GIB
6003 : " from layer %s.",
6004 0 : poFeature->GetFID(), poSrcDefn->GetName());
6005 0 : bStopTransfer = true;
6006 0 : poFeature.reset();
6007 0 : break;
6008 : }
6009 : }
6010 :
6011 30 : if (poFeature)
6012 : {
6013 30 : apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());
6014 : }
6015 : }
6016 :
6017 3 : CPLErrorReset();
6018 3 : bool bStopTransaction = false;
6019 6 : while (!bStopTransaction)
6020 : {
6021 3 : bStopTransaction = true;
6022 3 : if (poDstLayer->StartTransaction() != OGRERR_NONE)
6023 0 : break;
6024 33 : for (int i = 0; i < nFeatCount; ++i)
6025 : {
6026 30 : if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=
6027 : OGRERR_NONE)
6028 : {
6029 0 : bStopTransfer = true;
6030 0 : bStopTransaction = false;
6031 0 : break;
6032 : }
6033 30 : apoDstFeatures[i].reset();
6034 : }
6035 3 : if (bStopTransaction)
6036 : {
6037 3 : if (poDstLayer->CommitTransaction() != OGRERR_NONE)
6038 0 : break;
6039 : }
6040 : else
6041 : {
6042 0 : poDstLayer->RollbackTransaction();
6043 : }
6044 : }
6045 : }
6046 : }
6047 :
6048 128 : return poDstLayer;
6049 : }
6050 :
6051 : /************************************************************************/
6052 : /* DeleteLayer() */
6053 : /************************************************************************/
6054 :
6055 : /**
6056 : \fn GDALDataset::DeleteLayer(int)
6057 : \brief Delete the indicated layer from the datasource.
6058 :
6059 : If this method is supported
6060 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
6061 :
6062 : This method is the same as the C function GDALDatasetDeleteLayer() and the
6063 : deprecated OGR_DS_DeleteLayer().
6064 :
6065 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6066 :
6067 : @param iLayer the index of the layer to delete.
6068 :
6069 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
6070 : layers is not supported for this datasource.
6071 :
6072 : */
6073 :
6074 389 : OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)
6075 :
6076 : {
6077 389 : CPLError(CE_Failure, CPLE_NotSupported,
6078 : "DeleteLayer() not supported by this dataset.");
6079 :
6080 389 : return OGRERR_UNSUPPORTED_OPERATION;
6081 : }
6082 :
6083 : /************************************************************************/
6084 : /* GetLayerByName() */
6085 : /************************************************************************/
6086 :
6087 : /**
6088 : \brief Fetch a layer by name.
6089 :
6090 : The returned layer remains owned by the
6091 : GDALDataset and should not be deleted by the application.
6092 :
6093 : This method is the same as the C function GDALDatasetGetLayerByName() and the
6094 : deprecated OGR_DS_GetLayerByName().
6095 :
6096 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6097 :
6098 : @param pszName the layer name of the layer to fetch.
6099 :
6100 : @return the layer, or NULL if Layer is not found or an error occurs.
6101 : */
6102 :
6103 29404 : OGRLayer *GDALDataset::GetLayerByName(const char *pszName)
6104 :
6105 : {
6106 58808 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
6107 :
6108 29404 : if (!pszName)
6109 0 : return nullptr;
6110 :
6111 : // First a case sensitive check.
6112 931824 : for (int i = 0; i < GetLayerCount(); ++i)
6113 : {
6114 913882 : OGRLayer *poLayer = GetLayer(i);
6115 :
6116 913882 : if (strcmp(pszName, poLayer->GetName()) == 0)
6117 11462 : return poLayer;
6118 : }
6119 :
6120 : // Then case insensitive.
6121 893490 : for (int i = 0; i < GetLayerCount(); ++i)
6122 : {
6123 875736 : OGRLayer *poLayer = GetLayer(i);
6124 :
6125 875736 : if (EQUAL(pszName, poLayer->GetName()))
6126 188 : return poLayer;
6127 : }
6128 :
6129 17754 : return nullptr;
6130 : }
6131 :
6132 : //! @cond Doxygen_Suppress
6133 : /************************************************************************/
6134 : /* ProcessSQLCreateIndex() */
6135 : /* */
6136 : /* The correct syntax for creating an index in our dialect of */
6137 : /* SQL is: */
6138 : /* */
6139 : /* CREATE INDEX ON <layername> USING <columnname> */
6140 : /************************************************************************/
6141 :
6142 28 : OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)
6143 :
6144 : {
6145 28 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6146 :
6147 : /* -------------------------------------------------------------------- */
6148 : /* Do some general syntax checking. */
6149 : /* -------------------------------------------------------------------- */
6150 56 : if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||
6151 84 : !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||
6152 28 : !EQUAL(papszTokens[4], "USING"))
6153 : {
6154 0 : CSLDestroy(papszTokens);
6155 0 : CPLError(CE_Failure, CPLE_AppDefined,
6156 : "Syntax error in CREATE INDEX command.\n"
6157 : "Was '%s'\n"
6158 : "Should be of form 'CREATE INDEX ON <table> USING <field>'",
6159 : pszSQLCommand);
6160 0 : return OGRERR_FAILURE;
6161 : }
6162 :
6163 : /* -------------------------------------------------------------------- */
6164 : /* Find the named layer. */
6165 : /* -------------------------------------------------------------------- */
6166 28 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6167 28 : if (poLayer == nullptr)
6168 : {
6169 0 : CPLError(CE_Failure, CPLE_AppDefined,
6170 : "CREATE INDEX ON failed, no such layer as `%s'.",
6171 0 : papszTokens[3]);
6172 0 : CSLDestroy(papszTokens);
6173 0 : return OGRERR_FAILURE;
6174 : }
6175 :
6176 : /* -------------------------------------------------------------------- */
6177 : /* Does this layer even support attribute indexes? */
6178 : /* -------------------------------------------------------------------- */
6179 28 : if (poLayer->GetIndex() == nullptr)
6180 : {
6181 0 : CPLError(CE_Failure, CPLE_AppDefined,
6182 : "CREATE INDEX ON not supported by this driver.");
6183 0 : CSLDestroy(papszTokens);
6184 0 : return OGRERR_FAILURE;
6185 : }
6186 :
6187 : /* -------------------------------------------------------------------- */
6188 : /* Find the named field. */
6189 : /* -------------------------------------------------------------------- */
6190 28 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6191 :
6192 28 : CSLDestroy(papszTokens);
6193 :
6194 28 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6195 : {
6196 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6197 : pszSQLCommand);
6198 0 : return OGRERR_FAILURE;
6199 : }
6200 :
6201 : /* -------------------------------------------------------------------- */
6202 : /* Attempt to create the index. */
6203 : /* -------------------------------------------------------------------- */
6204 28 : OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
6205 28 : if (eErr == OGRERR_NONE)
6206 : {
6207 28 : eErr = poLayer->GetIndex()->IndexAllFeatures(i);
6208 : }
6209 : else
6210 : {
6211 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
6212 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
6213 : }
6214 :
6215 28 : return eErr;
6216 : }
6217 :
6218 : /************************************************************************/
6219 : /* ProcessSQLDropIndex() */
6220 : /* */
6221 : /* The correct syntax for dropping one or more indexes in */
6222 : /* the OGR SQL dialect is: */
6223 : /* */
6224 : /* DROP INDEX ON <layername> [USING <columnname>] */
6225 : /************************************************************************/
6226 :
6227 10 : OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)
6228 :
6229 : {
6230 10 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6231 :
6232 : /* -------------------------------------------------------------------- */
6233 : /* Do some general syntax checking. */
6234 : /* -------------------------------------------------------------------- */
6235 20 : if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||
6236 10 : !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||
6237 30 : !EQUAL(papszTokens[2], "ON") ||
6238 10 : (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))
6239 : {
6240 0 : CSLDestroy(papszTokens);
6241 0 : CPLError(CE_Failure, CPLE_AppDefined,
6242 : "Syntax error in DROP INDEX command.\n"
6243 : "Was '%s'\n"
6244 : "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
6245 : pszSQLCommand);
6246 0 : return OGRERR_FAILURE;
6247 : }
6248 :
6249 : /* -------------------------------------------------------------------- */
6250 : /* Find the named layer. */
6251 : /* -------------------------------------------------------------------- */
6252 10 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6253 10 : if (poLayer == nullptr)
6254 : {
6255 0 : CPLError(CE_Failure, CPLE_AppDefined,
6256 : "DROP INDEX ON failed, no such layer as `%s'.",
6257 0 : papszTokens[3]);
6258 0 : CSLDestroy(papszTokens);
6259 0 : return OGRERR_FAILURE;
6260 : }
6261 :
6262 : /* -------------------------------------------------------------------- */
6263 : /* Does this layer even support attribute indexes? */
6264 : /* -------------------------------------------------------------------- */
6265 10 : if (poLayer->GetIndex() == nullptr)
6266 : {
6267 0 : CPLError(CE_Failure, CPLE_AppDefined,
6268 : "Indexes not supported by this driver.");
6269 0 : CSLDestroy(papszTokens);
6270 0 : return OGRERR_FAILURE;
6271 : }
6272 :
6273 : /* -------------------------------------------------------------------- */
6274 : /* If we were not given a field name, drop all indexes. */
6275 : /* -------------------------------------------------------------------- */
6276 10 : if (CSLCount(papszTokens) == 4)
6277 : {
6278 0 : for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)
6279 : {
6280 : OGRAttrIndex *poAttrIndex;
6281 :
6282 0 : poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
6283 0 : if (poAttrIndex != nullptr)
6284 : {
6285 0 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6286 0 : if (eErr != OGRERR_NONE)
6287 : {
6288 0 : CSLDestroy(papszTokens);
6289 0 : return eErr;
6290 : }
6291 : }
6292 : }
6293 :
6294 0 : CSLDestroy(papszTokens);
6295 0 : return OGRERR_NONE;
6296 : }
6297 :
6298 : /* -------------------------------------------------------------------- */
6299 : /* Find the named field. */
6300 : /* -------------------------------------------------------------------- */
6301 10 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6302 10 : CSLDestroy(papszTokens);
6303 :
6304 10 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6305 : {
6306 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6307 : pszSQLCommand);
6308 0 : return OGRERR_FAILURE;
6309 : }
6310 :
6311 : /* -------------------------------------------------------------------- */
6312 : /* Attempt to drop the index. */
6313 : /* -------------------------------------------------------------------- */
6314 10 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6315 :
6316 10 : return eErr;
6317 : }
6318 :
6319 : /************************************************************************/
6320 : /* ProcessSQLDropTable() */
6321 : /* */
6322 : /* The correct syntax for dropping a table (layer) in the OGR SQL */
6323 : /* dialect is: */
6324 : /* */
6325 : /* DROP TABLE <layername> */
6326 : /************************************************************************/
6327 :
6328 500 : OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)
6329 :
6330 : {
6331 500 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6332 :
6333 : /* -------------------------------------------------------------------- */
6334 : /* Do some general syntax checking. */
6335 : /* -------------------------------------------------------------------- */
6336 1000 : if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||
6337 500 : !EQUAL(papszTokens[1], "TABLE"))
6338 : {
6339 0 : CSLDestroy(papszTokens);
6340 0 : CPLError(CE_Failure, CPLE_AppDefined,
6341 : "Syntax error in DROP TABLE command.\n"
6342 : "Was '%s'\n"
6343 : "Should be of form 'DROP TABLE <table>'",
6344 : pszSQLCommand);
6345 0 : return OGRERR_FAILURE;
6346 : }
6347 :
6348 : /* -------------------------------------------------------------------- */
6349 : /* Find the named layer. */
6350 : /* -------------------------------------------------------------------- */
6351 500 : OGRLayer *poLayer = nullptr;
6352 :
6353 500 : int i = 0; // Used after for.
6354 40199 : for (; i < GetLayerCount(); ++i)
6355 : {
6356 40199 : poLayer = GetLayer(i);
6357 :
6358 40199 : if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))
6359 500 : break;
6360 39699 : poLayer = nullptr;
6361 : }
6362 :
6363 500 : if (poLayer == nullptr)
6364 : {
6365 0 : CPLError(CE_Failure, CPLE_AppDefined,
6366 0 : "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
6367 0 : CSLDestroy(papszTokens);
6368 0 : return OGRERR_FAILURE;
6369 : }
6370 :
6371 500 : CSLDestroy(papszTokens);
6372 :
6373 : /* -------------------------------------------------------------------- */
6374 : /* Delete it. */
6375 : /* -------------------------------------------------------------------- */
6376 :
6377 500 : return DeleteLayer(i);
6378 : }
6379 :
6380 : //! @endcond
6381 :
6382 : /************************************************************************/
6383 : /* GDALDatasetParseSQLType() */
6384 : /************************************************************************/
6385 :
6386 : /* All arguments will be altered */
6387 6 : static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
6388 : int &nPrecision)
6389 : {
6390 6 : char *pszParenthesis = strchr(pszType, '(');
6391 6 : if (pszParenthesis)
6392 : {
6393 4 : nWidth = atoi(pszParenthesis + 1);
6394 4 : *pszParenthesis = '\0';
6395 4 : char *pszComma = strchr(pszParenthesis + 1, ',');
6396 4 : if (pszComma)
6397 2 : nPrecision = atoi(pszComma + 1);
6398 : }
6399 :
6400 6 : OGRFieldType eType = OFTString;
6401 6 : if (EQUAL(pszType, "INTEGER"))
6402 0 : eType = OFTInteger;
6403 6 : else if (EQUAL(pszType, "INTEGER[]"))
6404 0 : eType = OFTIntegerList;
6405 6 : else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||
6406 4 : EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
6407 4 : EQUAL(pszType, "REAL") /* unofficial alias */)
6408 2 : eType = OFTReal;
6409 4 : else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||
6410 4 : EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
6411 4 : EQUAL(pszType, "REAL[]") /* unofficial alias */)
6412 0 : eType = OFTRealList;
6413 4 : else if (EQUAL(pszType, "CHARACTER") ||
6414 0 : EQUAL(pszType, "TEXT") /* unofficial alias */ ||
6415 0 : EQUAL(pszType, "STRING") /* unofficial alias */ ||
6416 0 : EQUAL(pszType, "VARCHAR") /* unofficial alias */)
6417 4 : eType = OFTString;
6418 0 : else if (EQUAL(pszType, "TEXT[]") ||
6419 0 : EQUAL(pszType, "STRING[]") /* unofficial alias */ ||
6420 0 : EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
6421 0 : eType = OFTStringList;
6422 0 : else if (EQUAL(pszType, "DATE"))
6423 0 : eType = OFTDate;
6424 0 : else if (EQUAL(pszType, "TIME"))
6425 0 : eType = OFTTime;
6426 0 : else if (EQUAL(pszType, "TIMESTAMP") ||
6427 0 : EQUAL(pszType, "DATETIME") /* unofficial alias */)
6428 0 : eType = OFTDateTime;
6429 : else
6430 0 : CPLError(CE_Warning, CPLE_NotSupported,
6431 : "Unsupported column type '%s'. Defaulting to VARCHAR",
6432 : pszType);
6433 :
6434 6 : return eType;
6435 : }
6436 :
6437 : /************************************************************************/
6438 : /* ProcessSQLAlterTableAddColumn() */
6439 : /* */
6440 : /* The correct syntax for adding a column in the OGR SQL */
6441 : /* dialect is: */
6442 : /* */
6443 : /* ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
6444 : /************************************************************************/
6445 :
6446 : //! @cond Doxygen_Suppress
6447 2 : OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)
6448 :
6449 : {
6450 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6451 :
6452 : /* -------------------------------------------------------------------- */
6453 : /* Do some general syntax checking. */
6454 : /* -------------------------------------------------------------------- */
6455 2 : const char *pszLayerName = nullptr;
6456 2 : const char *pszColumnName = nullptr;
6457 2 : int iTypeIndex = 0;
6458 2 : const int nTokens = CSLCount(papszTokens);
6459 :
6460 2 : if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6461 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&
6462 2 : EQUAL(papszTokens[4], "COLUMN"))
6463 : {
6464 1 : pszLayerName = papszTokens[2];
6465 1 : pszColumnName = papszTokens[5];
6466 1 : iTypeIndex = 6;
6467 : }
6468 1 : else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&
6469 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))
6470 : {
6471 1 : pszLayerName = papszTokens[2];
6472 1 : pszColumnName = papszTokens[4];
6473 1 : iTypeIndex = 5;
6474 : }
6475 : else
6476 : {
6477 0 : CSLDestroy(papszTokens);
6478 0 : CPLError(CE_Failure, CPLE_AppDefined,
6479 : "Syntax error in ALTER TABLE ADD COLUMN command.\n"
6480 : "Was '%s'\n"
6481 : "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
6482 : "<columnname> <columntype>'",
6483 : pszSQLCommand);
6484 0 : return OGRERR_FAILURE;
6485 : }
6486 :
6487 : /* -------------------------------------------------------------------- */
6488 : /* Merge type components into a single string if there were split */
6489 : /* with spaces */
6490 : /* -------------------------------------------------------------------- */
6491 4 : CPLString osType;
6492 6 : for (int i = iTypeIndex; i < nTokens; ++i)
6493 : {
6494 4 : osType += papszTokens[i];
6495 4 : CPLFree(papszTokens[i]);
6496 : }
6497 2 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6498 2 : papszTokens[iTypeIndex + 1] = nullptr;
6499 :
6500 : /* -------------------------------------------------------------------- */
6501 : /* Find the named layer. */
6502 : /* -------------------------------------------------------------------- */
6503 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6504 2 : if (poLayer == nullptr)
6505 : {
6506 0 : CPLError(CE_Failure, CPLE_AppDefined,
6507 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6508 : pszLayerName);
6509 0 : CSLDestroy(papszTokens);
6510 0 : return OGRERR_FAILURE;
6511 : }
6512 :
6513 : /* -------------------------------------------------------------------- */
6514 : /* Add column. */
6515 : /* -------------------------------------------------------------------- */
6516 :
6517 2 : int nWidth = 0;
6518 2 : int nPrecision = 0;
6519 2 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6520 4 : OGRFieldDefn oFieldDefn(pszColumnName, eType);
6521 2 : oFieldDefn.SetWidth(nWidth);
6522 2 : oFieldDefn.SetPrecision(nPrecision);
6523 :
6524 2 : CSLDestroy(papszTokens);
6525 :
6526 2 : return poLayer->CreateField(&oFieldDefn);
6527 : }
6528 :
6529 : /************************************************************************/
6530 : /* ProcessSQLAlterTableDropColumn() */
6531 : /* */
6532 : /* The correct syntax for dropping a column in the OGR SQL */
6533 : /* dialect is: */
6534 : /* */
6535 : /* ALTER TABLE <layername> DROP [COLUMN] <columnname> */
6536 : /************************************************************************/
6537 :
6538 2 : OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)
6539 :
6540 : {
6541 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6542 :
6543 : /* -------------------------------------------------------------------- */
6544 : /* Do some general syntax checking. */
6545 : /* -------------------------------------------------------------------- */
6546 2 : const char *pszLayerName = nullptr;
6547 2 : const char *pszColumnName = nullptr;
6548 3 : if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&
6549 4 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&
6550 1 : EQUAL(papszTokens[4], "COLUMN"))
6551 : {
6552 1 : pszLayerName = papszTokens[2];
6553 1 : pszColumnName = papszTokens[5];
6554 : }
6555 2 : else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&
6556 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))
6557 : {
6558 1 : pszLayerName = papszTokens[2];
6559 1 : pszColumnName = papszTokens[4];
6560 : }
6561 : else
6562 : {
6563 0 : CSLDestroy(papszTokens);
6564 0 : CPLError(CE_Failure, CPLE_AppDefined,
6565 : "Syntax error in ALTER TABLE DROP COLUMN command.\n"
6566 : "Was '%s'\n"
6567 : "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
6568 : "<columnname>'",
6569 : pszSQLCommand);
6570 0 : return OGRERR_FAILURE;
6571 : }
6572 :
6573 : /* -------------------------------------------------------------------- */
6574 : /* Find the named layer. */
6575 : /* -------------------------------------------------------------------- */
6576 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6577 2 : if (poLayer == nullptr)
6578 : {
6579 0 : CPLError(CE_Failure, CPLE_AppDefined,
6580 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6581 : pszLayerName);
6582 0 : CSLDestroy(papszTokens);
6583 0 : return OGRERR_FAILURE;
6584 : }
6585 :
6586 : /* -------------------------------------------------------------------- */
6587 : /* Find the field. */
6588 : /* -------------------------------------------------------------------- */
6589 :
6590 2 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6591 2 : if (nFieldIndex < 0)
6592 : {
6593 0 : CPLError(CE_Failure, CPLE_AppDefined,
6594 : "%s failed, no such field as `%s'.", pszSQLCommand,
6595 : pszColumnName);
6596 0 : CSLDestroy(papszTokens);
6597 0 : return OGRERR_FAILURE;
6598 : }
6599 :
6600 : /* -------------------------------------------------------------------- */
6601 : /* Remove it. */
6602 : /* -------------------------------------------------------------------- */
6603 :
6604 2 : CSLDestroy(papszTokens);
6605 :
6606 2 : return poLayer->DeleteField(nFieldIndex);
6607 : }
6608 :
6609 : /************************************************************************/
6610 : /* ProcessSQLAlterTableRenameColumn() */
6611 : /* */
6612 : /* The correct syntax for renaming a column in the OGR SQL */
6613 : /* dialect is: */
6614 : /* */
6615 : /* ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
6616 : /************************************************************************/
6617 :
6618 2 : OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)
6619 :
6620 : {
6621 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6622 :
6623 : /* -------------------------------------------------------------------- */
6624 : /* Do some general syntax checking. */
6625 : /* -------------------------------------------------------------------- */
6626 2 : const char *pszLayerName = nullptr;
6627 2 : const char *pszOldColName = nullptr;
6628 2 : const char *pszNewColName = nullptr;
6629 3 : if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&
6630 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&
6631 3 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))
6632 : {
6633 1 : pszLayerName = papszTokens[2];
6634 1 : pszOldColName = papszTokens[5];
6635 1 : pszNewColName = papszTokens[7];
6636 : }
6637 2 : else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&
6638 1 : EQUAL(papszTokens[1], "TABLE") &&
6639 2 : EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))
6640 : {
6641 1 : pszLayerName = papszTokens[2];
6642 1 : pszOldColName = papszTokens[4];
6643 1 : pszNewColName = papszTokens[6];
6644 : }
6645 : else
6646 : {
6647 0 : CSLDestroy(papszTokens);
6648 0 : CPLError(CE_Failure, CPLE_AppDefined,
6649 : "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
6650 : "Was '%s'\n"
6651 : "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
6652 : "<columnname> TO <newname>'",
6653 : pszSQLCommand);
6654 0 : return OGRERR_FAILURE;
6655 : }
6656 :
6657 : /* -------------------------------------------------------------------- */
6658 : /* Find the named layer. */
6659 : /* -------------------------------------------------------------------- */
6660 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6661 2 : if (poLayer == nullptr)
6662 : {
6663 0 : CPLError(CE_Failure, CPLE_AppDefined,
6664 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6665 : pszLayerName);
6666 0 : CSLDestroy(papszTokens);
6667 0 : return OGRERR_FAILURE;
6668 : }
6669 :
6670 : /* -------------------------------------------------------------------- */
6671 : /* Find the field. */
6672 : /* -------------------------------------------------------------------- */
6673 :
6674 : const int nFieldIndex =
6675 2 : poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
6676 2 : if (nFieldIndex < 0)
6677 : {
6678 0 : CPLError(CE_Failure, CPLE_AppDefined,
6679 : "%s failed, no such field as `%s'.", pszSQLCommand,
6680 : pszOldColName);
6681 0 : CSLDestroy(papszTokens);
6682 0 : return OGRERR_FAILURE;
6683 : }
6684 :
6685 : /* -------------------------------------------------------------------- */
6686 : /* Rename column. */
6687 : /* -------------------------------------------------------------------- */
6688 : OGRFieldDefn *poOldFieldDefn =
6689 2 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6690 4 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6691 2 : oNewFieldDefn.SetName(pszNewColName);
6692 :
6693 2 : CSLDestroy(papszTokens);
6694 :
6695 2 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6696 2 : ALTER_NAME_FLAG);
6697 : }
6698 :
6699 : /************************************************************************/
6700 : /* ProcessSQLAlterTableAlterColumn() */
6701 : /* */
6702 : /* The correct syntax for altering the type of a column in the */
6703 : /* OGR SQL dialect is: */
6704 : /* */
6705 : /* ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
6706 : /************************************************************************/
6707 :
6708 4 : OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)
6709 :
6710 : {
6711 4 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6712 :
6713 : /* -------------------------------------------------------------------- */
6714 : /* Do some general syntax checking. */
6715 : /* -------------------------------------------------------------------- */
6716 4 : const char *pszLayerName = nullptr;
6717 4 : const char *pszColumnName = nullptr;
6718 4 : int iTypeIndex = 0;
6719 4 : const int nTokens = CSLCount(papszTokens);
6720 :
6721 4 : if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&
6722 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6723 2 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))
6724 : {
6725 2 : pszLayerName = papszTokens[2];
6726 2 : pszColumnName = papszTokens[5];
6727 2 : iTypeIndex = 7;
6728 : }
6729 2 : else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6730 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6731 2 : EQUAL(papszTokens[5], "TYPE"))
6732 : {
6733 2 : pszLayerName = papszTokens[2];
6734 2 : pszColumnName = papszTokens[4];
6735 2 : iTypeIndex = 6;
6736 : }
6737 : else
6738 : {
6739 0 : CSLDestroy(papszTokens);
6740 0 : CPLError(CE_Failure, CPLE_AppDefined,
6741 : "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
6742 : "Was '%s'\n"
6743 : "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
6744 : "<columnname> TYPE <columntype>'",
6745 : pszSQLCommand);
6746 0 : return OGRERR_FAILURE;
6747 : }
6748 :
6749 : /* -------------------------------------------------------------------- */
6750 : /* Merge type components into a single string if there were split */
6751 : /* with spaces */
6752 : /* -------------------------------------------------------------------- */
6753 8 : CPLString osType;
6754 8 : for (int i = iTypeIndex; i < nTokens; ++i)
6755 : {
6756 4 : osType += papszTokens[i];
6757 4 : CPLFree(papszTokens[i]);
6758 : }
6759 4 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6760 4 : papszTokens[iTypeIndex + 1] = nullptr;
6761 :
6762 : /* -------------------------------------------------------------------- */
6763 : /* Find the named layer. */
6764 : /* -------------------------------------------------------------------- */
6765 4 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6766 4 : if (poLayer == nullptr)
6767 : {
6768 0 : CPLError(CE_Failure, CPLE_AppDefined,
6769 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6770 : pszLayerName);
6771 0 : CSLDestroy(papszTokens);
6772 0 : return OGRERR_FAILURE;
6773 : }
6774 :
6775 : /* -------------------------------------------------------------------- */
6776 : /* Find the field. */
6777 : /* -------------------------------------------------------------------- */
6778 :
6779 : const int nFieldIndex =
6780 4 : poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6781 4 : if (nFieldIndex < 0)
6782 : {
6783 0 : CPLError(CE_Failure, CPLE_AppDefined,
6784 : "%s failed, no such field as `%s'.", pszSQLCommand,
6785 : pszColumnName);
6786 0 : CSLDestroy(papszTokens);
6787 0 : return OGRERR_FAILURE;
6788 : }
6789 :
6790 : /* -------------------------------------------------------------------- */
6791 : /* Alter column. */
6792 : /* -------------------------------------------------------------------- */
6793 :
6794 : OGRFieldDefn *poOldFieldDefn =
6795 4 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6796 8 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6797 :
6798 4 : int nWidth = 0;
6799 4 : int nPrecision = 0;
6800 4 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6801 4 : oNewFieldDefn.SetType(eType);
6802 4 : oNewFieldDefn.SetWidth(nWidth);
6803 4 : oNewFieldDefn.SetPrecision(nPrecision);
6804 :
6805 4 : int l_nFlags = 0;
6806 4 : if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
6807 2 : l_nFlags |= ALTER_TYPE_FLAG;
6808 4 : if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
6809 0 : poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
6810 4 : l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
6811 :
6812 4 : CSLDestroy(papszTokens);
6813 :
6814 4 : if (l_nFlags == 0)
6815 0 : return OGRERR_NONE;
6816 :
6817 4 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
6818 : }
6819 :
6820 : //! @endcond
6821 :
6822 : /************************************************************************/
6823 : /* ExecuteSQL() */
6824 : /************************************************************************/
6825 :
6826 : /**
6827 : \brief Execute an SQL statement against the data store.
6828 :
6829 : The result of an SQL query is either NULL for statements that are in error,
6830 : or that have no results set, or an OGRLayer pointer representing a results
6831 : set from the query. Note that this OGRLayer is in addition to the layers
6832 : in the data store and must be destroyed with
6833 : ReleaseResultSet() before the dataset is closed
6834 : (destroyed).
6835 :
6836 : This method is the same as the C function GDALDatasetExecuteSQL() and the
6837 : deprecated OGR_DS_ExecuteSQL().
6838 :
6839 : For more information on the SQL dialect supported internally by OGR
6840 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
6841 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
6842 : to the underlying RDBMS.
6843 :
6844 : Starting with OGR 1.10, the <a
6845 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
6846 : also be used.
6847 :
6848 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6849 :
6850 : @param pszStatement the SQL statement to execute.
6851 : @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
6852 : @param pszDialect allows control of the statement dialect. If set to NULL, the
6853 : OGR SQL engine will be used, except for RDBMS drivers that will use their
6854 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
6855 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
6856 :
6857 : @return an OGRLayer containing the results of the query. Deallocate with
6858 : ReleaseResultSet().
6859 :
6860 : */
6861 :
6862 3556 : OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,
6863 : OGRGeometry *poSpatialFilter,
6864 : const char *pszDialect)
6865 :
6866 : {
6867 3556 : return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
6868 : }
6869 :
6870 : //! @cond Doxygen_Suppress
6871 : OGRLayer *
6872 3564 : GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
6873 : const char *pszDialect,
6874 : swq_select_parse_options *poSelectParseOptions)
6875 :
6876 : {
6877 3564 : if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))
6878 : {
6879 : #ifdef SQLITE_ENABLED
6880 649 : return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
6881 649 : pszDialect);
6882 : #else
6883 : CPLError(CE_Failure, CPLE_NotSupported,
6884 : "The SQLite driver needs to be compiled to support the "
6885 : "SQLite SQL dialect");
6886 : return nullptr;
6887 : #endif
6888 : }
6889 :
6890 2915 : if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
6891 14 : !EQUAL(pszDialect, "OGRSQL"))
6892 : {
6893 6 : std::string osDialectList = "'OGRSQL'";
6894 : #ifdef SQLITE_ENABLED
6895 3 : osDialectList += ", 'SQLITE'";
6896 : #endif
6897 : const char *pszDialects =
6898 3 : GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);
6899 3 : if (pszDialects)
6900 : {
6901 : const CPLStringList aosTokens(
6902 0 : CSLTokenizeString2(pszDialects, " ", 0));
6903 0 : for (int i = 0; i < aosTokens.size(); ++i)
6904 : {
6905 0 : if (!EQUAL(aosTokens[i], "OGRSQL") &&
6906 0 : !EQUAL(aosTokens[i], "SQLITE"))
6907 : {
6908 0 : osDialectList += ", '";
6909 0 : osDialectList += aosTokens[i];
6910 0 : osDialectList += "'";
6911 : }
6912 : }
6913 : }
6914 3 : CPLError(CE_Warning, CPLE_NotSupported,
6915 : "Dialect '%s' is unsupported. Only supported dialects are %s. "
6916 : "Defaulting to OGRSQL",
6917 : pszDialect, osDialectList.c_str());
6918 : }
6919 :
6920 : /* -------------------------------------------------------------------- */
6921 : /* Handle CREATE INDEX statements specially. */
6922 : /* -------------------------------------------------------------------- */
6923 2915 : if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))
6924 : {
6925 28 : ProcessSQLCreateIndex(pszStatement);
6926 28 : return nullptr;
6927 : }
6928 :
6929 : /* -------------------------------------------------------------------- */
6930 : /* Handle DROP INDEX statements specially. */
6931 : /* -------------------------------------------------------------------- */
6932 2887 : if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))
6933 : {
6934 10 : ProcessSQLDropIndex(pszStatement);
6935 10 : return nullptr;
6936 : }
6937 :
6938 : /* -------------------------------------------------------------------- */
6939 : /* Handle DROP TABLE statements specially. */
6940 : /* -------------------------------------------------------------------- */
6941 2877 : if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))
6942 : {
6943 500 : ProcessSQLDropTable(pszStatement);
6944 500 : return nullptr;
6945 : }
6946 :
6947 : /* -------------------------------------------------------------------- */
6948 : /* Handle ALTER TABLE statements specially. */
6949 : /* -------------------------------------------------------------------- */
6950 2377 : if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))
6951 : {
6952 11 : char **papszTokens = CSLTokenizeString(pszStatement);
6953 11 : const int nTokens = CSLCount(papszTokens);
6954 11 : if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))
6955 : {
6956 2 : ProcessSQLAlterTableAddColumn(pszStatement);
6957 2 : CSLDestroy(papszTokens);
6958 2 : return nullptr;
6959 : }
6960 9 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))
6961 : {
6962 2 : ProcessSQLAlterTableDropColumn(pszStatement);
6963 2 : CSLDestroy(papszTokens);
6964 2 : return nullptr;
6965 : }
6966 7 : else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&
6967 1 : EQUAL(papszTokens[4], "TO"))
6968 : {
6969 1 : const char *pszSrcTableName = papszTokens[2];
6970 1 : const char *pszDstTableName = papszTokens[5];
6971 1 : auto poSrcLayer = GetLayerByName(pszSrcTableName);
6972 1 : if (poSrcLayer)
6973 : {
6974 1 : CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));
6975 : }
6976 : else
6977 : {
6978 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");
6979 : }
6980 1 : CSLDestroy(papszTokens);
6981 1 : return nullptr;
6982 : }
6983 6 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))
6984 : {
6985 2 : ProcessSQLAlterTableRenameColumn(pszStatement);
6986 2 : CSLDestroy(papszTokens);
6987 2 : return nullptr;
6988 : }
6989 4 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))
6990 : {
6991 4 : ProcessSQLAlterTableAlterColumn(pszStatement);
6992 4 : CSLDestroy(papszTokens);
6993 4 : return nullptr;
6994 : }
6995 : else
6996 : {
6997 0 : CPLError(CE_Failure, CPLE_AppDefined,
6998 : "Unsupported ALTER TABLE command : %s", pszStatement);
6999 0 : CSLDestroy(papszTokens);
7000 0 : return nullptr;
7001 : }
7002 : }
7003 :
7004 : /* -------------------------------------------------------------------- */
7005 : /* Preparse the SQL statement. */
7006 : /* -------------------------------------------------------------------- */
7007 2366 : swq_select *psSelectInfo = new swq_select();
7008 2366 : swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
7009 2366 : if (poSelectParseOptions != nullptr)
7010 8 : poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
7011 2366 : if (psSelectInfo->preparse(pszStatement,
7012 2366 : poCustomFuncRegistrar != nullptr) != CE_None)
7013 : {
7014 141 : delete psSelectInfo;
7015 141 : return nullptr;
7016 : }
7017 :
7018 : /* -------------------------------------------------------------------- */
7019 : /* If there is no UNION ALL, build result layer. */
7020 : /* -------------------------------------------------------------------- */
7021 2225 : if (psSelectInfo->poOtherSelect == nullptr)
7022 : {
7023 2219 : return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
7024 2219 : pszDialect, poSelectParseOptions);
7025 : }
7026 :
7027 : /* -------------------------------------------------------------------- */
7028 : /* Build result union layer. */
7029 : /* -------------------------------------------------------------------- */
7030 6 : int nSrcLayers = 0;
7031 6 : OGRLayer **papoSrcLayers = nullptr;
7032 :
7033 6 : do
7034 : {
7035 12 : swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
7036 12 : psSelectInfo->poOtherSelect = nullptr;
7037 :
7038 12 : OGRLayer *poLayer = BuildLayerFromSelectInfo(
7039 : psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
7040 12 : if (poLayer == nullptr)
7041 : {
7042 : // Each source layer owns an independent select info.
7043 0 : for (int i = 0; i < nSrcLayers; ++i)
7044 0 : delete papoSrcLayers[i];
7045 0 : CPLFree(papoSrcLayers);
7046 :
7047 : // So we just have to destroy the remaining select info.
7048 0 : delete psNextSelectInfo;
7049 :
7050 0 : return nullptr;
7051 : }
7052 : else
7053 : {
7054 24 : papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
7055 12 : papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
7056 12 : papoSrcLayers[nSrcLayers] = poLayer;
7057 12 : ++nSrcLayers;
7058 :
7059 12 : psSelectInfo = psNextSelectInfo;
7060 : }
7061 12 : } while (psSelectInfo != nullptr);
7062 :
7063 6 : return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
7064 : }
7065 :
7066 : //! @endcond
7067 :
7068 : /************************************************************************/
7069 : /* AbortSQL() */
7070 : /************************************************************************/
7071 :
7072 : /**
7073 : \brief Abort any SQL statement running in the data store.
7074 :
7075 : This function can be safely called from any thread (pending that the dataset
7076 : object is still alive). Driver implementations will make sure that it can be
7077 : called in a thread-safe way.
7078 :
7079 : This might not be implemented by all drivers. At time of writing, only SQLite,
7080 : GPKG and PG drivers implement it
7081 :
7082 : This method is the same as the C method GDALDatasetAbortSQL()
7083 :
7084 : @since GDAL 3.2.0
7085 :
7086 :
7087 : */
7088 :
7089 0 : OGRErr GDALDataset::AbortSQL()
7090 : {
7091 0 : CPLError(CE_Failure, CPLE_NotSupported,
7092 : "AbortSQL is not supported for this driver.");
7093 0 : return OGRERR_UNSUPPORTED_OPERATION;
7094 : }
7095 :
7096 : /************************************************************************/
7097 : /* BuildLayerFromSelectInfo() */
7098 : /************************************************************************/
7099 :
7100 : struct GDALSQLParseInfo
7101 : {
7102 : swq_field_list sFieldList;
7103 : int nExtraDSCount;
7104 : GDALDataset **papoExtraDS;
7105 : char *pszWHERE;
7106 : };
7107 :
7108 2231 : OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
7109 : swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
7110 : const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
7111 : {
7112 4462 : std::unique_ptr<swq_select> psSelectInfoUnique(psSelectInfo);
7113 :
7114 2231 : std::unique_ptr<OGRGenSQLResultsLayer> poResults;
7115 : GDALSQLParseInfo *psParseInfo =
7116 2231 : BuildParseInfo(psSelectInfoUnique.get(), poSelectParseOptions);
7117 :
7118 2231 : if (psParseInfo)
7119 : {
7120 2196 : const auto nErrorCounter = CPLGetErrorCounter();
7121 4392 : poResults = std::make_unique<OGRGenSQLResultsLayer>(
7122 2196 : this, std::move(psSelectInfoUnique), poSpatialFilter,
7123 4392 : psParseInfo->pszWHERE, pszDialect);
7124 2273 : if (CPLGetErrorCounter() > nErrorCounter &&
7125 77 : CPLGetLastErrorType() != CE_None)
7126 77 : poResults.reset();
7127 : }
7128 :
7129 2231 : DestroyParseInfo(psParseInfo);
7130 :
7131 4462 : return poResults.release();
7132 : }
7133 :
7134 : /************************************************************************/
7135 : /* DestroyParseInfo() */
7136 : /************************************************************************/
7137 :
7138 : //! @cond Doxygen_Suppress
7139 2300 : void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
7140 : {
7141 2300 : if (psParseInfo == nullptr)
7142 35 : return;
7143 :
7144 2265 : CPLFree(psParseInfo->sFieldList.names);
7145 2265 : CPLFree(psParseInfo->sFieldList.types);
7146 2265 : CPLFree(psParseInfo->sFieldList.table_ids);
7147 2265 : CPLFree(psParseInfo->sFieldList.ids);
7148 :
7149 : // Release the datasets we have opened with OGROpenShared()
7150 : // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
7151 : // has taken a reference on them, which it will release in its
7152 : // destructor.
7153 2272 : for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)
7154 7 : GDALClose(psParseInfo->papoExtraDS[iEDS]);
7155 :
7156 2265 : CPLFree(psParseInfo->papoExtraDS);
7157 2265 : CPLFree(psParseInfo->pszWHERE);
7158 2265 : CPLFree(psParseInfo);
7159 : }
7160 :
7161 : /************************************************************************/
7162 : /* BuildParseInfo() */
7163 : /************************************************************************/
7164 :
7165 : GDALSQLParseInfo *
7166 2265 : GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
7167 : swq_select_parse_options *poSelectParseOptions)
7168 : {
7169 2265 : int nFirstLayerFirstSpecialFieldIndex = 0;
7170 :
7171 : GDALSQLParseInfo *psParseInfo =
7172 2265 : static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
7173 :
7174 : /* -------------------------------------------------------------------- */
7175 : /* Validate that all the source tables are recognized, count */
7176 : /* fields. */
7177 : /* -------------------------------------------------------------------- */
7178 2265 : int nFieldCount = 0;
7179 :
7180 4598 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7181 : {
7182 2336 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7183 2336 : GDALDataset *poTableDS = this;
7184 :
7185 2336 : if (psTableDef->data_source != nullptr)
7186 : {
7187 7 : poTableDS = GDALDataset::FromHandle(
7188 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7189 7 : if (poTableDS == nullptr)
7190 : {
7191 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
7192 0 : CPLError(CE_Failure, CPLE_AppDefined,
7193 : "Unable to open secondary datasource "
7194 : "`%s' required by JOIN.",
7195 : psTableDef->data_source);
7196 :
7197 0 : DestroyParseInfo(psParseInfo);
7198 0 : return nullptr;
7199 : }
7200 :
7201 : // Keep in an array to release at the end of this function.
7202 14 : psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
7203 7 : psParseInfo->papoExtraDS,
7204 7 : sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
7205 7 : psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
7206 : }
7207 :
7208 : OGRLayer *poSrcLayer =
7209 2336 : poTableDS->GetLayerByName(psTableDef->table_name);
7210 :
7211 2336 : if (poSrcLayer == nullptr)
7212 : {
7213 3 : CPLError(CE_Failure, CPLE_AppDefined,
7214 : "SELECT from table %s failed, no such table/featureclass.",
7215 : psTableDef->table_name);
7216 :
7217 3 : DestroyParseInfo(psParseInfo);
7218 3 : return nullptr;
7219 : }
7220 :
7221 2333 : nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
7222 2333 : if (iTable == 0 ||
7223 34 : (poSelectParseOptions &&
7224 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7225 2296 : nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7226 :
7227 2333 : const char *pszFID = poSrcLayer->GetFIDColumn();
7228 2943 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7229 610 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7230 560 : nFieldCount++;
7231 : }
7232 :
7233 : /* -------------------------------------------------------------------- */
7234 : /* Build the field list for all indicated tables. */
7235 : /* -------------------------------------------------------------------- */
7236 :
7237 2262 : psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
7238 2262 : psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
7239 :
7240 2262 : psParseInfo->sFieldList.count = 0;
7241 2262 : psParseInfo->sFieldList.names = static_cast<char **>(
7242 2262 : CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7243 4524 : psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
7244 2262 : sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7245 2262 : psParseInfo->sFieldList.table_ids = static_cast<int *>(
7246 2262 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7247 2262 : psParseInfo->sFieldList.ids = static_cast<int *>(
7248 2262 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7249 :
7250 2262 : bool bIsFID64 = false;
7251 4595 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7252 : {
7253 2333 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7254 2333 : GDALDataset *poTableDS = this;
7255 :
7256 2333 : if (psTableDef->data_source != nullptr)
7257 : {
7258 7 : poTableDS = GDALDataset::FromHandle(
7259 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7260 7 : CPLAssert(poTableDS != nullptr);
7261 7 : poTableDS->Dereference();
7262 : }
7263 :
7264 : OGRLayer *poSrcLayer =
7265 2333 : poTableDS->GetLayerByName(psTableDef->table_name);
7266 :
7267 2333 : for (int iField = 0;
7268 18501 : iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)
7269 : {
7270 : OGRFieldDefn *poFDefn =
7271 16168 : poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
7272 16168 : const int iOutField = psParseInfo->sFieldList.count++;
7273 32336 : psParseInfo->sFieldList.names[iOutField] =
7274 16168 : const_cast<char *>(poFDefn->GetNameRef());
7275 16168 : if (poFDefn->GetType() == OFTInteger)
7276 : {
7277 4082 : if (poFDefn->GetSubType() == OFSTBoolean)
7278 160 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7279 : else
7280 3922 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7281 : }
7282 12086 : else if (poFDefn->GetType() == OFTInteger64)
7283 : {
7284 751 : if (poFDefn->GetSubType() == OFSTBoolean)
7285 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7286 : else
7287 751 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7288 : }
7289 11335 : else if (poFDefn->GetType() == OFTReal)
7290 2708 : psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
7291 8627 : else if (poFDefn->GetType() == OFTString)
7292 5573 : psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
7293 3054 : else if (poFDefn->GetType() == OFTTime)
7294 83 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
7295 2971 : else if (poFDefn->GetType() == OFTDate)
7296 143 : psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
7297 2828 : else if (poFDefn->GetType() == OFTDateTime)
7298 939 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
7299 : else
7300 1889 : psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
7301 :
7302 16168 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7303 16168 : psParseInfo->sFieldList.ids[iOutField] = iField;
7304 : }
7305 :
7306 2333 : if (iTable == 0)
7307 : {
7308 2262 : nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
7309 : }
7310 :
7311 2333 : if (iTable == 0 ||
7312 34 : (poSelectParseOptions &&
7313 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7314 : {
7315 :
7316 2296 : for (int iField = 0;
7317 4242 : iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7318 : iField++)
7319 : {
7320 : OGRGeomFieldDefn *poFDefn =
7321 1946 : poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
7322 1946 : const int iOutField = psParseInfo->sFieldList.count++;
7323 3892 : psParseInfo->sFieldList.names[iOutField] =
7324 1946 : const_cast<char *>(poFDefn->GetNameRef());
7325 1946 : if (*psParseInfo->sFieldList.names[iOutField] == '\0')
7326 1131 : psParseInfo->sFieldList.names[iOutField] =
7327 : const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
7328 1946 : psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
7329 :
7330 1946 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7331 1946 : psParseInfo->sFieldList.ids[iOutField] =
7332 1946 : GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
7333 : poSrcLayer->GetLayerDefn(), iField);
7334 : }
7335 : }
7336 :
7337 2334 : if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7338 1 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7339 : {
7340 1 : bIsFID64 = true;
7341 : }
7342 : }
7343 :
7344 : /* -------------------------------------------------------------------- */
7345 : /* Expand '*' in 'SELECT *' now before we add the pseudo fields */
7346 : /* -------------------------------------------------------------------- */
7347 2262 : const bool bAlwaysPrefixWithTableName =
7348 2304 : poSelectParseOptions &&
7349 42 : poSelectParseOptions->bAlwaysPrefixWithTableName;
7350 2262 : if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
7351 2262 : bAlwaysPrefixWithTableName) != CE_None)
7352 : {
7353 2 : DestroyParseInfo(psParseInfo);
7354 2 : return nullptr;
7355 : }
7356 :
7357 13560 : for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
7358 : {
7359 11300 : psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
7360 11300 : const_cast<char *>(SpecialFieldNames[iField]);
7361 11300 : psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
7362 11300 : (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
7363 : : SpecialFieldTypes[iField];
7364 11300 : psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
7365 11300 : psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
7366 11300 : nFirstLayerFirstSpecialFieldIndex + iField;
7367 11300 : psParseInfo->sFieldList.count++;
7368 : }
7369 :
7370 : /* In the case a layer has an explicit FID column name, then add it */
7371 : /* so it can be selected */
7372 4591 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7373 : {
7374 2331 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7375 2331 : GDALDataset *poTableDS = this;
7376 :
7377 2331 : if (psTableDef->data_source != nullptr)
7378 : {
7379 7 : poTableDS = GDALDataset::FromHandle(
7380 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7381 7 : CPLAssert(poTableDS != nullptr);
7382 7 : poTableDS->Dereference();
7383 : }
7384 :
7385 : OGRLayer *poSrcLayer =
7386 2331 : poTableDS->GetLayerByName(psTableDef->table_name);
7387 :
7388 2331 : const char *pszFID = poSrcLayer->GetFIDColumn();
7389 2941 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7390 610 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7391 : {
7392 560 : const int iOutField = psParseInfo->sFieldList.count++;
7393 560 : psParseInfo->sFieldList.names[iOutField] =
7394 : const_cast<char *>(pszFID);
7395 560 : if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7396 0 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7397 : {
7398 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7399 : }
7400 : else
7401 : {
7402 560 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7403 : }
7404 560 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7405 1120 : psParseInfo->sFieldList.ids[iOutField] =
7406 560 : poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
7407 : }
7408 : }
7409 :
7410 : /* -------------------------------------------------------------------- */
7411 : /* Finish the parse operation. */
7412 : /* -------------------------------------------------------------------- */
7413 2260 : if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
7414 : CE_None)
7415 : {
7416 30 : DestroyParseInfo(psParseInfo);
7417 30 : return nullptr;
7418 : }
7419 :
7420 : /* -------------------------------------------------------------------- */
7421 : /* Extract the WHERE expression to use separately. */
7422 : /* -------------------------------------------------------------------- */
7423 2230 : if (psSelectInfo->where_expr != nullptr)
7424 : {
7425 956 : psParseInfo->pszWHERE =
7426 956 : psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
7427 : // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
7428 : }
7429 :
7430 2230 : return psParseInfo;
7431 : }
7432 :
7433 : //! @endcond
7434 :
7435 : /************************************************************************/
7436 : /* ReleaseResultSet() */
7437 : /************************************************************************/
7438 :
7439 : /**
7440 : \brief Release results of ExecuteSQL().
7441 :
7442 : This method should only be used to deallocate OGRLayers resulting from
7443 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
7444 : results set before destroying the GDALDataset may cause errors.
7445 :
7446 : This method is the same as the C function GDALDatasetReleaseResultSet() and the
7447 : deprecated OGR_DS_ReleaseResultSet().
7448 :
7449 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7450 :
7451 : @param poResultsSet the result of a previous ExecuteSQL() call.
7452 : */
7453 :
7454 2147 : void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)
7455 :
7456 : {
7457 2147 : delete poResultsSet;
7458 2147 : }
7459 :
7460 : /************************************************************************/
7461 : /* GetStyleTable() */
7462 : /************************************************************************/
7463 :
7464 : /**
7465 : \brief Returns dataset style table.
7466 :
7467 : This method is the same as the C function GDALDatasetGetStyleTable() and the
7468 : deprecated OGR_DS_GetStyleTable().
7469 :
7470 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7471 :
7472 : @return pointer to a style table which should not be modified or freed by the
7473 : caller.
7474 : */
7475 :
7476 819 : OGRStyleTable *GDALDataset::GetStyleTable()
7477 : {
7478 819 : return m_poStyleTable;
7479 : }
7480 :
7481 : /************************************************************************/
7482 : /* SetStyleTableDirectly() */
7483 : /************************************************************************/
7484 :
7485 : /**
7486 : \brief Set dataset style table.
7487 :
7488 : This method operate exactly as SetStyleTable() except that it
7489 : assumes ownership of the passed table.
7490 :
7491 : This method is the same as the C function GDALDatasetSetStyleTableDirectly()
7492 : and the deprecated OGR_DS_SetStyleTableDirectly().
7493 :
7494 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7495 :
7496 : @param poStyleTable pointer to style table to set
7497 :
7498 : */
7499 0 : void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
7500 : {
7501 0 : if (m_poStyleTable)
7502 0 : delete m_poStyleTable;
7503 0 : m_poStyleTable = poStyleTable;
7504 0 : }
7505 :
7506 : /************************************************************************/
7507 : /* SetStyleTable() */
7508 : /************************************************************************/
7509 :
7510 : /**
7511 : \brief Set dataset style table.
7512 :
7513 : This method operate exactly as SetStyleTableDirectly() except
7514 : that it does not assume ownership of the passed table.
7515 :
7516 : This method is the same as the C function GDALDatasetSetStyleTable() and the
7517 : deprecated OGR_DS_SetStyleTable().
7518 :
7519 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7520 :
7521 : @param poStyleTable pointer to style table to set
7522 :
7523 : */
7524 :
7525 815 : void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
7526 : {
7527 815 : if (m_poStyleTable)
7528 0 : delete m_poStyleTable;
7529 815 : if (poStyleTable)
7530 1 : m_poStyleTable = poStyleTable->Clone();
7531 815 : }
7532 :
7533 : /************************************************************************/
7534 : /* IsGenericSQLDialect() */
7535 : /************************************************************************/
7536 :
7537 : //! @cond Doxygen_Suppress
7538 1745 : int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
7539 : {
7540 3182 : return pszDialect != nullptr &&
7541 3182 : (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
7542 : }
7543 :
7544 : //! @endcond
7545 :
7546 : /************************************************************************/
7547 : /* GetLayerCount() */
7548 : /************************************************************************/
7549 :
7550 : /**
7551 : \brief Get the number of layers in this dataset.
7552 :
7553 : This method is the same as the C function GDALDatasetGetLayerCount(),
7554 : and the deprecated OGR_DS_GetLayerCount().
7555 :
7556 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7557 :
7558 : @return layer count.
7559 : */
7560 :
7561 78941 : int GDALDataset::GetLayerCount()
7562 : {
7563 78941 : return 0;
7564 : }
7565 :
7566 : /************************************************************************/
7567 : /* GetLayer() */
7568 : /************************************************************************/
7569 :
7570 : /**
7571 : \fn GDALDataset::GetLayer(int)
7572 : \brief Fetch a layer by index.
7573 :
7574 : The returned layer remains owned by the
7575 : GDALDataset and should not be deleted by the application.
7576 :
7577 : See GetLayers() for a C++ iterator version of this method.
7578 :
7579 : This method is the same as the C function GDALDatasetGetLayer() and the
7580 : deprecated OGR_DS_GetLayer().
7581 :
7582 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7583 :
7584 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7585 :
7586 : @return the layer, or NULL if iLayer is out of range or an error occurs.
7587 :
7588 : @see GetLayers()
7589 : */
7590 :
7591 0 : OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer)
7592 : {
7593 0 : return nullptr;
7594 : }
7595 :
7596 : /************************************************************************/
7597 : /* IsLayerPrivate() */
7598 : /************************************************************************/
7599 :
7600 : /**
7601 : \fn GDALDataset::IsLayerPrivate(int)
7602 : \brief Returns true if the layer at the specified index is deemed a private or
7603 : system table, or an internal detail only.
7604 :
7605 : This method is the same as the C function GDALDatasetIsLayerPrivate().
7606 :
7607 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7608 :
7609 : @return true if the layer is a private or system table.
7610 :
7611 : @since GDAL 3.4
7612 : */
7613 :
7614 833 : bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const
7615 : {
7616 833 : return false;
7617 : }
7618 :
7619 : /************************************************************************/
7620 : /* ResetReading() */
7621 : /************************************************************************/
7622 :
7623 : /**
7624 : \brief Reset feature reading to start on the first feature.
7625 :
7626 : This affects GetNextFeature().
7627 :
7628 : Depending on drivers, this may also have the side effect of calling
7629 : OGRLayer::ResetReading() on the layers of this dataset.
7630 :
7631 : This method is the same as the C function GDALDatasetResetReading().
7632 :
7633 : @since GDAL 2.2
7634 : */
7635 7 : void GDALDataset::ResetReading()
7636 : {
7637 7 : if (!m_poPrivate)
7638 0 : return;
7639 7 : m_poPrivate->nCurrentLayerIdx = 0;
7640 7 : m_poPrivate->nLayerCount = -1;
7641 7 : m_poPrivate->poCurrentLayer = nullptr;
7642 7 : m_poPrivate->nFeatureReadInLayer = 0;
7643 7 : m_poPrivate->nFeatureReadInDataset = 0;
7644 7 : m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
7645 7 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
7646 : }
7647 :
7648 : /************************************************************************/
7649 : /* GDALDatasetResetReading() */
7650 : /************************************************************************/
7651 :
7652 : /**
7653 : \brief Reset feature reading to start on the first feature.
7654 :
7655 : This affects GDALDatasetGetNextFeature().
7656 :
7657 : Depending on drivers, this may also have the side effect of calling
7658 : OGR_L_ResetReading() on the layers of this dataset.
7659 :
7660 : This method is the same as the C++ method GDALDataset::ResetReading()
7661 :
7662 : @param hDS dataset handle
7663 : @since GDAL 2.2
7664 : */
7665 14 : void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)
7666 : {
7667 14 : VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
7668 :
7669 14 : return GDALDataset::FromHandle(hDS)->ResetReading();
7670 : }
7671 :
7672 : /************************************************************************/
7673 : /* GetNextFeature() */
7674 : /************************************************************************/
7675 :
7676 : /**
7677 : \brief Fetch the next available feature from this dataset.
7678 :
7679 : This method is intended for the few drivers where OGRLayer::GetNextFeature()
7680 : is not efficient, but in general OGRLayer::GetNextFeature() is a more
7681 : natural API.
7682 :
7683 : See GetFeatures() for a C++ iterator version of this method.
7684 :
7685 : The returned feature becomes the responsibility of the caller to
7686 : delete with OGRFeature::DestroyFeature().
7687 :
7688 : Depending on the driver, this method may return features from layers in a
7689 : non sequential way. This is what may happen when the
7690 : ODsCRandomLayerRead capability is declared (for example for the
7691 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7692 : advised to use GDALDataset::GetNextFeature() instead of
7693 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7694 : implementation.
7695 :
7696 : The default implementation, used by most drivers, will
7697 : however iterate over each layer, and then over each feature within this
7698 : layer.
7699 :
7700 : This method takes into account spatial and attribute filters set on layers that
7701 : will be iterated upon.
7702 :
7703 : The ResetReading() method can be used to start at the beginning again.
7704 :
7705 : Depending on drivers, this may also have the side effect of calling
7706 : OGRLayer::GetNextFeature() on the layers of this dataset.
7707 :
7708 : This method is the same as the C function GDALDatasetGetNextFeature().
7709 :
7710 : @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
7711 : layer to which the object belongs to, or NULL.
7712 : It is possible that the output of *ppoBelongingLayer
7713 : to be NULL despite the feature not being NULL.
7714 : @param pdfProgressPct a pointer to a double variable to receive the
7715 : percentage progress (in [0,1] range), or NULL.
7716 : On return, the pointed value might be negative if
7717 : determining the progress is not possible.
7718 : @param pfnProgress a progress callback to report progress (for
7719 : GetNextFeature() calls that might have a long
7720 : duration) and offer cancellation possibility, or NULL.
7721 : @param pProgressData user data provided to pfnProgress, or NULL
7722 : @return a feature, or NULL if no more features are available.
7723 : @since GDAL 2.2
7724 : @see GetFeatures()
7725 : */
7726 :
7727 60 : OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,
7728 : double *pdfProgressPct,
7729 : GDALProgressFunc pfnProgress,
7730 : void *pProgressData)
7731 : {
7732 60 : if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)
7733 : {
7734 2 : if (ppoBelongingLayer != nullptr)
7735 2 : *ppoBelongingLayer = nullptr;
7736 2 : if (pdfProgressPct != nullptr)
7737 1 : *pdfProgressPct = 1.0;
7738 2 : if (pfnProgress != nullptr)
7739 0 : pfnProgress(1.0, "", pProgressData);
7740 2 : return nullptr;
7741 : }
7742 :
7743 58 : if (m_poPrivate->poCurrentLayer == nullptr &&
7744 8 : (pdfProgressPct != nullptr || pfnProgress != nullptr))
7745 : {
7746 1 : if (m_poPrivate->nLayerCount < 0)
7747 : {
7748 1 : m_poPrivate->nLayerCount = GetLayerCount();
7749 : }
7750 :
7751 1 : if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)
7752 : {
7753 1 : m_poPrivate->nTotalFeatures = 0;
7754 5 : for (int i = 0; i < m_poPrivate->nLayerCount; i++)
7755 : {
7756 4 : OGRLayer *poLayer = GetLayer(i);
7757 8 : if (poLayer == nullptr ||
7758 4 : !poLayer->TestCapability(OLCFastFeatureCount))
7759 : {
7760 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7761 0 : break;
7762 : }
7763 4 : GIntBig nCount = poLayer->GetFeatureCount(FALSE);
7764 4 : if (nCount < 0)
7765 : {
7766 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7767 0 : break;
7768 : }
7769 4 : m_poPrivate->nTotalFeatures += nCount;
7770 : }
7771 : }
7772 : }
7773 :
7774 : while (true)
7775 : {
7776 71 : if (m_poPrivate->poCurrentLayer == nullptr)
7777 : {
7778 44 : m_poPrivate->poCurrentLayer =
7779 22 : GetLayer(m_poPrivate->nCurrentLayerIdx);
7780 22 : if (m_poPrivate->poCurrentLayer == nullptr)
7781 : {
7782 7 : m_poPrivate->nCurrentLayerIdx = -1;
7783 7 : if (ppoBelongingLayer != nullptr)
7784 7 : *ppoBelongingLayer = nullptr;
7785 7 : if (pdfProgressPct != nullptr)
7786 1 : *pdfProgressPct = 1.0;
7787 7 : return nullptr;
7788 : }
7789 15 : m_poPrivate->poCurrentLayer->ResetReading();
7790 15 : m_poPrivate->nFeatureReadInLayer = 0;
7791 15 : if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)
7792 : {
7793 0 : if (m_poPrivate->poCurrentLayer->TestCapability(
7794 0 : OLCFastFeatureCount))
7795 0 : m_poPrivate->nTotalFeaturesInLayer =
7796 0 : m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
7797 : else
7798 0 : m_poPrivate->nTotalFeaturesInLayer = 0;
7799 : }
7800 : }
7801 64 : OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
7802 64 : if (poFeature == nullptr)
7803 : {
7804 13 : m_poPrivate->nCurrentLayerIdx++;
7805 13 : m_poPrivate->poCurrentLayer = nullptr;
7806 13 : continue;
7807 : }
7808 :
7809 51 : m_poPrivate->nFeatureReadInLayer++;
7810 51 : m_poPrivate->nFeatureReadInDataset++;
7811 51 : if (pdfProgressPct != nullptr || pfnProgress != nullptr)
7812 : {
7813 4 : double dfPct = 0.0;
7814 4 : if (m_poPrivate->nTotalFeatures > 0)
7815 : {
7816 4 : dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
7817 4 : m_poPrivate->nTotalFeatures;
7818 : }
7819 : else
7820 : {
7821 0 : dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /
7822 0 : m_poPrivate->nLayerCount;
7823 0 : if (m_poPrivate->nTotalFeaturesInLayer > 0)
7824 : {
7825 0 : dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
7826 0 : m_poPrivate->nTotalFeaturesInLayer /
7827 0 : m_poPrivate->nLayerCount;
7828 : }
7829 : }
7830 4 : if (pdfProgressPct)
7831 4 : *pdfProgressPct = dfPct;
7832 4 : if (pfnProgress)
7833 0 : pfnProgress(dfPct, "", nullptr);
7834 : }
7835 :
7836 51 : if (ppoBelongingLayer != nullptr)
7837 51 : *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
7838 51 : return poFeature;
7839 13 : }
7840 : }
7841 :
7842 : /************************************************************************/
7843 : /* GDALDatasetGetNextFeature() */
7844 : /************************************************************************/
7845 : /**
7846 : \brief Fetch the next available feature from this dataset.
7847 :
7848 : This method is intended for the few drivers where OGR_L_GetNextFeature()
7849 : is not efficient, but in general OGR_L_GetNextFeature() is a more
7850 : natural API.
7851 :
7852 : The returned feature becomes the responsibility of the caller to
7853 : delete with OGRFeature::DestroyFeature().
7854 :
7855 : Depending on the driver, this method may return features from layers in a
7856 : non sequential way. This is what may happen when the
7857 : ODsCRandomLayerRead capability is declared (for example for the
7858 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7859 : advised to use GDALDataset::GetNextFeature() instead of
7860 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7861 : implementation.
7862 :
7863 : The default implementation, used by most drivers, will
7864 : however iterate over each layer, and then over each feature within this
7865 : layer.
7866 :
7867 : This method takes into account spatial and attribute filters set on layers that
7868 : will be iterated upon.
7869 :
7870 : The ResetReading() method can be used to start at the beginning again.
7871 :
7872 : Depending on drivers, this may also have the side effect of calling
7873 : OGRLayer::GetNextFeature() on the layers of this dataset.
7874 :
7875 : This method is the same as the C++ method GDALDataset::GetNextFeature()
7876 :
7877 : @param hDS dataset handle.
7878 : @param phBelongingLayer a pointer to a OGRLayer* variable to receive the
7879 : layer to which the object belongs to, or NULL.
7880 : It is possible that the output of *ppoBelongingLayer
7881 : to be NULL despite the feature not being NULL.
7882 : @param pdfProgressPct a pointer to a double variable to receive the
7883 : percentage progress (in [0,1] range), or NULL.
7884 : On return, the pointed value might be negative if
7885 : determining the progress is not possible.
7886 : @param pfnProgress a progress callback to report progress (for
7887 : GetNextFeature() calls that might have a long
7888 : duration) and offer cancellation possibility, or NULL
7889 : @param pProgressData user data provided to pfnProgress, or NULL
7890 : @return a feature, or NULL if no more features are available.
7891 : @since GDAL 2.2
7892 : */
7893 1917 : OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,
7894 : OGRLayerH *phBelongingLayer,
7895 : double *pdfProgressPct,
7896 : GDALProgressFunc pfnProgress,
7897 : void *pProgressData)
7898 : {
7899 1917 : VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
7900 :
7901 3834 : return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(
7902 : reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
7903 3834 : pfnProgress, pProgressData));
7904 : }
7905 :
7906 : /************************************************************************/
7907 : /* TestCapability() */
7908 : /************************************************************************/
7909 :
7910 : /**
7911 : \fn GDALDataset::TestCapability( const char * pszCap )
7912 : \brief Test if capability is available.
7913 :
7914 : One of the following dataset capability names can be passed into this
7915 : method, and a TRUE or FALSE value will be returned indicating whether or not
7916 : the capability is available for this object.
7917 :
7918 : <ul>
7919 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7920 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7921 : layers.<p>
7922 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7923 : datasource support CreateGeomField() just after layer creation.<p>
7924 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7925 : geometries.<p>
7926 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7927 : transactions.<p>
7928 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7929 : transactions through emulation.<p>
7930 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7931 : GetNextFeature() implementation, potentially returning features from
7932 : layers in a non sequential way.<p>
7933 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7934 : CreateFeature() on layers in a non sequential way.<p>
7935 : </ul>
7936 :
7937 : The \#define macro forms of the capability names should be used in preference
7938 : to the strings themselves to avoid misspelling.
7939 :
7940 : This method is the same as the C function GDALDatasetTestCapability() and the
7941 : deprecated OGR_DS_TestCapability().
7942 :
7943 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7944 :
7945 : @param pszCap the capability to test.
7946 :
7947 : @return TRUE if capability available otherwise FALSE.
7948 : */
7949 :
7950 241 : int GDALDataset::TestCapability(CPL_UNUSED const char *pszCap)
7951 : {
7952 241 : return FALSE;
7953 : }
7954 :
7955 : /************************************************************************/
7956 : /* GDALDatasetTestCapability() */
7957 : /************************************************************************/
7958 :
7959 : /**
7960 : \brief Test if capability is available.
7961 :
7962 : One of the following dataset capability names can be passed into this
7963 : function, and a TRUE or FALSE value will be returned indicating whether or not
7964 : the capability is available for this object.
7965 :
7966 : <ul>
7967 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7968 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7969 : layers.<p>
7970 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7971 : datasource support CreateGeomField() just after layer creation.<p>
7972 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7973 : geometries.<p>
7974 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7975 : transactions.<p>
7976 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7977 : transactions through emulation.<p>
7978 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7979 : GetNextFeature() implementation, potentially returning features from
7980 : layers in a non sequential way.<p>
7981 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7982 : CreateFeature() on layers in a non sequential way.<p>
7983 : </ul>
7984 :
7985 : The \#define macro forms of the capability names should be used in preference
7986 : to the strings themselves to avoid misspelling.
7987 :
7988 : This function is the same as the C++ method GDALDataset::TestCapability()
7989 :
7990 : @since GDAL 2.0
7991 :
7992 : @param hDS the dataset handle.
7993 : @param pszCap the capability to test.
7994 :
7995 : @return TRUE if capability available otherwise FALSE.
7996 : */
7997 118 : int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)
7998 :
7999 : {
8000 118 : VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
8001 118 : VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
8002 :
8003 118 : return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
8004 : }
8005 :
8006 : /************************************************************************/
8007 : /* StartTransaction() */
8008 : /************************************************************************/
8009 :
8010 : /**
8011 : \fn GDALDataset::StartTransaction(int)
8012 : \brief For datasources which support transactions, StartTransaction creates a
8013 : `transaction.
8014 :
8015 : If starting the transaction fails, will return
8016 : OGRERR_FAILURE. Datasources which do not support transactions will
8017 : always return OGRERR_UNSUPPORTED_OPERATION.
8018 :
8019 : Nested transactions are not supported.
8020 :
8021 : All changes done after the start of the transaction are definitely applied in
8022 : the datasource if CommitTransaction() is called. They may be canceled by
8023 : calling RollbackTransaction() instead.
8024 :
8025 : At the time of writing, transactions only apply on vector layers.
8026 :
8027 : Datasets that support transactions will advertise the ODsCTransactions
8028 : capability. Use of transactions at dataset level is generally preferred to
8029 : transactions at layer level, whose scope is rarely limited to the layer from
8030 : which it was started.
8031 :
8032 : In case StartTransaction() fails, neither CommitTransaction() or
8033 : RollbackTransaction() should be called.
8034 :
8035 : If an error occurs after a successful StartTransaction(), the whole transaction
8036 : may or may not be implicitly canceled, depending on drivers. (e.g. the PG
8037 : driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
8038 : an explicit call to RollbackTransaction() should be done to keep things
8039 : balanced.
8040 :
8041 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8042 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8043 : with significant overhead, in which case the user must explicitly allow for
8044 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8045 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8046 : ODsCTransactions).
8047 :
8048 : This function is the same as the C function GDALDatasetStartTransaction().
8049 :
8050 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8051 : transaction
8052 : mechanism is acceptable.
8053 :
8054 : @return OGRERR_NONE on success.
8055 : @since GDAL 2.0
8056 : */
8057 :
8058 37 : OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
8059 : {
8060 37 : return OGRERR_UNSUPPORTED_OPERATION;
8061 : }
8062 :
8063 : /************************************************************************/
8064 : /* GDALDatasetStartTransaction() */
8065 : /************************************************************************/
8066 :
8067 : /**
8068 : \brief For datasources which support transactions, StartTransaction creates a
8069 : transaction.
8070 :
8071 : If starting the transaction fails, will return
8072 : OGRERR_FAILURE. Datasources which do not support transactions will
8073 : always return OGRERR_UNSUPPORTED_OPERATION.
8074 :
8075 : Nested transactions are not supported.
8076 :
8077 : All changes done after the start of the transaction are definitely applied in
8078 : the datasource if CommitTransaction() is called. They may be canceled by
8079 : calling RollbackTransaction() instead.
8080 :
8081 : At the time of writing, transactions only apply on vector layers.
8082 :
8083 : Datasets that support transactions will advertise the ODsCTransactions
8084 : capability.
8085 : Use of transactions at dataset level is generally preferred to transactions at
8086 : layer level, whose scope is rarely limited to the layer from which it was
8087 : started.
8088 :
8089 : In case StartTransaction() fails, neither CommitTransaction() or
8090 : RollbackTransaction() should be called.
8091 :
8092 : If an error occurs after a successful StartTransaction(), the whole
8093 : transaction may or may not be implicitly canceled, depending on drivers. (e.g.
8094 : the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
8095 : error, an explicit call to RollbackTransaction() should be done to keep things
8096 : balanced.
8097 :
8098 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8099 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8100 : with significant overhead, in which case the user must explicitly allow for
8101 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8102 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8103 : ODsCTransactions).
8104 :
8105 : This function is the same as the C++ method GDALDataset::StartTransaction()
8106 :
8107 : @param hDS the dataset handle.
8108 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8109 : transaction
8110 : mechanism is acceptable.
8111 :
8112 : @return OGRERR_NONE on success.
8113 : @since GDAL 2.0
8114 : */
8115 105 : OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
8116 : {
8117 105 : VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
8118 : OGRERR_INVALID_HANDLE);
8119 :
8120 : #ifdef OGRAPISPY_ENABLED
8121 105 : if (bOGRAPISpyEnabled)
8122 2 : OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
8123 : #endif
8124 :
8125 105 : return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
8126 : }
8127 :
8128 : /************************************************************************/
8129 : /* CommitTransaction() */
8130 : /************************************************************************/
8131 :
8132 : /**
8133 : \brief For datasources which support transactions, CommitTransaction commits a
8134 : transaction.
8135 :
8136 : If no transaction is active, or the commit fails, will return
8137 : OGRERR_FAILURE. Datasources which do not support transactions will
8138 : always return OGRERR_UNSUPPORTED_OPERATION.
8139 :
8140 : Depending on drivers, this may or may not abort layer sequential readings that
8141 : are active.
8142 :
8143 : This function is the same as the C function GDALDatasetCommitTransaction().
8144 :
8145 : @return OGRERR_NONE on success.
8146 : @since GDAL 2.0
8147 : */
8148 37 : OGRErr GDALDataset::CommitTransaction()
8149 : {
8150 37 : return OGRERR_UNSUPPORTED_OPERATION;
8151 : }
8152 :
8153 : /************************************************************************/
8154 : /* GDALDatasetCommitTransaction() */
8155 : /************************************************************************/
8156 :
8157 : /**
8158 : \brief For datasources which support transactions, CommitTransaction commits a
8159 : transaction.
8160 :
8161 : If no transaction is active, or the commit fails, will return
8162 : OGRERR_FAILURE. Datasources which do not support transactions will
8163 : always return OGRERR_UNSUPPORTED_OPERATION.
8164 :
8165 : Depending on drivers, this may or may not abort layer sequential readings that
8166 : are active.
8167 :
8168 : This function is the same as the C++ method GDALDataset::CommitTransaction()
8169 :
8170 : @return OGRERR_NONE on success.
8171 : @since GDAL 2.0
8172 : */
8173 76 : OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
8174 : {
8175 76 : VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
8176 : OGRERR_INVALID_HANDLE);
8177 :
8178 : #ifdef OGRAPISPY_ENABLED
8179 76 : if (bOGRAPISpyEnabled)
8180 2 : OGRAPISpy_Dataset_CommitTransaction(hDS);
8181 : #endif
8182 :
8183 76 : return GDALDataset::FromHandle(hDS)->CommitTransaction();
8184 : }
8185 :
8186 : /************************************************************************/
8187 : /* RollbackTransaction() */
8188 : /************************************************************************/
8189 :
8190 : /**
8191 : \brief For datasources which support transactions, RollbackTransaction will
8192 : roll back a datasource to its state before the start of the current
8193 : transaction.
8194 : If no transaction is active, or the rollback fails, will return
8195 : OGRERR_FAILURE. Datasources which do not support transactions will
8196 : always return OGRERR_UNSUPPORTED_OPERATION.
8197 :
8198 : This function is the same as the C function GDALDatasetRollbackTransaction().
8199 :
8200 : @return OGRERR_NONE on success.
8201 : @since GDAL 2.0
8202 : */
8203 2 : OGRErr GDALDataset::RollbackTransaction()
8204 : {
8205 2 : return OGRERR_UNSUPPORTED_OPERATION;
8206 : }
8207 :
8208 : /************************************************************************/
8209 : /* GDALDatasetRollbackTransaction() */
8210 : /************************************************************************/
8211 :
8212 : /**
8213 : \brief For datasources which support transactions, RollbackTransaction will
8214 : roll back a datasource to its state before the start of the current
8215 : transaction.
8216 : If no transaction is active, or the rollback fails, will return
8217 : OGRERR_FAILURE. Datasources which do not support transactions will
8218 : always return OGRERR_UNSUPPORTED_OPERATION.
8219 :
8220 : This function is the same as the C++ method GDALDataset::RollbackTransaction().
8221 :
8222 : @return OGRERR_NONE on success.
8223 : @since GDAL 2.0
8224 : */
8225 44 : OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
8226 : {
8227 44 : VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
8228 : OGRERR_INVALID_HANDLE);
8229 :
8230 : #ifdef OGRAPISPY_ENABLED
8231 44 : if (bOGRAPISpyEnabled)
8232 2 : OGRAPISpy_Dataset_RollbackTransaction(hDS);
8233 : #endif
8234 :
8235 44 : return GDALDataset::FromHandle(hDS)->RollbackTransaction();
8236 : }
8237 :
8238 : //! @cond Doxygen_Suppress
8239 :
8240 : /************************************************************************/
8241 : /* ShareLockWithParentDataset() */
8242 : /************************************************************************/
8243 :
8244 : /* To be used typically by the GTiff driver to link overview datasets */
8245 : /* with their main dataset, so that they share the same lock */
8246 : /* Cf https://github.com/OSGeo/gdal/issues/1488 */
8247 : /* The parent dataset should remain alive while the this dataset is alive */
8248 :
8249 2351 : void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)
8250 : {
8251 2351 : if (m_poPrivate != nullptr)
8252 : {
8253 2351 : m_poPrivate->poParentDataset = poParentDataset;
8254 : }
8255 2351 : }
8256 :
8257 : /************************************************************************/
8258 : /* SetQueryLoggerFunc() */
8259 : /************************************************************************/
8260 :
8261 0 : bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,
8262 : CPL_UNUSED void *context)
8263 : {
8264 0 : return false;
8265 : }
8266 :
8267 : /************************************************************************/
8268 : /* EnterReadWrite() */
8269 : /************************************************************************/
8270 :
8271 7766490 : int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
8272 : {
8273 15532600 : if (m_poPrivate == nullptr ||
8274 7766410 : IsThreadSafe(GDAL_OF_RASTER | (nOpenFlags & GDAL_OF_UPDATE)))
8275 11986 : return FALSE;
8276 :
8277 7754230 : if (m_poPrivate->poParentDataset)
8278 242548 : return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
8279 :
8280 7511680 : if (eAccess == GA_Update)
8281 : {
8282 2133540 : if (m_poPrivate->eStateReadWriteMutex ==
8283 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8284 : {
8285 : // In case dead-lock would occur, which is not impossible,
8286 : // this can be used to prevent it, but at the risk of other
8287 : // issues.
8288 10186 : if (CPLTestBool(
8289 : CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
8290 : {
8291 10186 : m_poPrivate->eStateReadWriteMutex =
8292 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
8293 : }
8294 : else
8295 : {
8296 0 : m_poPrivate->eStateReadWriteMutex =
8297 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8298 : }
8299 : }
8300 2133540 : if (m_poPrivate->eStateReadWriteMutex ==
8301 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)
8302 : {
8303 : // There should be no race related to creating this mutex since
8304 : // it should be first created through IWriteBlock() / IRasterIO()
8305 : // and then GDALRasterBlock might call it from another thread.
8306 : #ifdef DEBUG_VERBOSE
8307 : CPLDebug("GDAL",
8308 : "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
8309 : CPLGetPID(), GetDescription());
8310 : #endif
8311 1434940 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8312 :
8313 : const int nCountMutex =
8314 1435630 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
8315 1435610 : if (nCountMutex == 0 && eRWFlag == GF_Read)
8316 : {
8317 519859 : CPLReleaseMutex(m_poPrivate->hMutex);
8318 1650520 : for (int i = 0; i < nBands; i++)
8319 : {
8320 1130660 : auto blockCache = papoBands[i]->poBandBlockCache;
8321 1130660 : if (blockCache)
8322 816437 : blockCache->WaitCompletionPendingTasks();
8323 : }
8324 519859 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8325 : }
8326 :
8327 1435570 : return TRUE;
8328 : }
8329 : }
8330 6076740 : return FALSE;
8331 : }
8332 :
8333 : /************************************************************************/
8334 : /* LeaveReadWrite() */
8335 : /************************************************************************/
8336 :
8337 1664660 : void GDALDataset::LeaveReadWrite()
8338 : {
8339 1664660 : if (m_poPrivate)
8340 : {
8341 1664660 : if (m_poPrivate->poParentDataset)
8342 : {
8343 228939 : m_poPrivate->poParentDataset->LeaveReadWrite();
8344 228939 : return;
8345 : }
8346 :
8347 1435720 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
8348 1435440 : CPLReleaseMutex(m_poPrivate->hMutex);
8349 : #ifdef DEBUG_VERBOSE
8350 : CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
8351 : CPLGetPID(), GetDescription());
8352 : #endif
8353 : }
8354 : }
8355 :
8356 : /************************************************************************/
8357 : /* InitRWLock() */
8358 : /************************************************************************/
8359 :
8360 3864340 : void GDALDataset::InitRWLock()
8361 : {
8362 3864340 : if (m_poPrivate)
8363 : {
8364 3864340 : if (m_poPrivate->poParentDataset)
8365 : {
8366 8590 : m_poPrivate->poParentDataset->InitRWLock();
8367 8590 : return;
8368 : }
8369 :
8370 3855750 : if (m_poPrivate->eStateReadWriteMutex ==
8371 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8372 : {
8373 1 : if (EnterReadWrite(GF_Write))
8374 1 : LeaveReadWrite();
8375 : }
8376 : }
8377 : }
8378 :
8379 : /************************************************************************/
8380 : /* DisableReadWriteMutex() */
8381 : /************************************************************************/
8382 :
8383 : // The mutex logic is broken in multi-threaded situations, for example
8384 : // with 2 WarpedVRT datasets being read at the same time. In that
8385 : // particular case, the mutex is not needed, so allow the VRTWarpedDataset code
8386 : // to disable it.
8387 19087 : void GDALDataset::DisableReadWriteMutex()
8388 : {
8389 19087 : if (m_poPrivate)
8390 : {
8391 19087 : if (m_poPrivate->poParentDataset)
8392 : {
8393 0 : m_poPrivate->poParentDataset->DisableReadWriteMutex();
8394 0 : return;
8395 : }
8396 :
8397 19087 : m_poPrivate->eStateReadWriteMutex =
8398 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8399 : }
8400 : }
8401 :
8402 : /************************************************************************/
8403 : /* TemporarilyDropReadWriteLock() */
8404 : /************************************************************************/
8405 :
8406 3189120 : void GDALDataset::TemporarilyDropReadWriteLock()
8407 : {
8408 3189120 : if (m_poPrivate == nullptr)
8409 0 : return;
8410 :
8411 3189120 : if (m_poPrivate->poParentDataset)
8412 : {
8413 26290 : m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
8414 26289 : return;
8415 : }
8416 :
8417 3162840 : if (m_poPrivate->hMutex)
8418 : {
8419 : #ifdef DEBUG_VERBOSE
8420 : CPLDebug("GDAL",
8421 : "[Thread " CPL_FRMT_GIB "] "
8422 : "Temporarily drop RW mutex for %s",
8423 : CPLGetPID(), GetDescription());
8424 : #endif
8425 311988 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8426 : const int nCount =
8427 311988 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8428 : #ifdef DEBUG_EXTRA
8429 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
8430 : #endif
8431 950294 : for (int i = 0; i < nCount + 1; i++)
8432 : {
8433 : // The mutex is recursive
8434 : // coverity[double_unlock]
8435 638306 : CPLReleaseMutex(m_poPrivate->hMutex);
8436 : }
8437 : }
8438 : }
8439 :
8440 : /************************************************************************/
8441 : /* ReacquireReadWriteLock() */
8442 : /************************************************************************/
8443 :
8444 3189130 : void GDALDataset::ReacquireReadWriteLock()
8445 : {
8446 3189130 : if (m_poPrivate == nullptr)
8447 0 : return;
8448 :
8449 3189130 : if (m_poPrivate->poParentDataset)
8450 : {
8451 26289 : m_poPrivate->poParentDataset->ReacquireReadWriteLock();
8452 26289 : return;
8453 : }
8454 :
8455 3162840 : if (m_poPrivate->hMutex)
8456 : {
8457 : #ifdef DEBUG_VERBOSE
8458 : CPLDebug("GDAL",
8459 : "[Thread " CPL_FRMT_GIB "] "
8460 : "Reacquire temporarily dropped RW mutex for %s",
8461 : CPLGetPID(), GetDescription());
8462 : #endif
8463 311989 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8464 : const int nCount =
8465 311989 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8466 : #ifdef DEBUG_EXTRA
8467 : CPLAssert(nCount ==
8468 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
8469 : #endif
8470 311989 : if (nCount == 0)
8471 11353 : CPLReleaseMutex(m_poPrivate->hMutex);
8472 337671 : for (int i = 0; i < nCount - 1; i++)
8473 : {
8474 : // The mutex is recursive
8475 : // coverity[double_lock]
8476 25682 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8477 : }
8478 : }
8479 : }
8480 :
8481 : /************************************************************************/
8482 : /* AcquireMutex() */
8483 : /************************************************************************/
8484 :
8485 196 : int GDALDataset::AcquireMutex()
8486 : {
8487 196 : if (m_poPrivate == nullptr)
8488 0 : return 0;
8489 196 : if (m_poPrivate->poParentDataset)
8490 : {
8491 0 : return m_poPrivate->poParentDataset->AcquireMutex();
8492 : }
8493 :
8494 196 : return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8495 : }
8496 :
8497 : /************************************************************************/
8498 : /* ReleaseMutex() */
8499 : /************************************************************************/
8500 :
8501 196 : void GDALDataset::ReleaseMutex()
8502 : {
8503 196 : if (m_poPrivate)
8504 : {
8505 196 : if (m_poPrivate->poParentDataset)
8506 : {
8507 0 : m_poPrivate->poParentDataset->ReleaseMutex();
8508 0 : return;
8509 : }
8510 :
8511 196 : CPLReleaseMutex(m_poPrivate->hMutex);
8512 : }
8513 : }
8514 :
8515 : //! @endcond
8516 :
8517 : /************************************************************************/
8518 : /* GDALDataset::Features::Iterator::Private */
8519 : /************************************************************************/
8520 :
8521 : struct GDALDataset::Features::Iterator::Private
8522 : {
8523 : GDALDataset::FeatureLayerPair m_oPair{};
8524 : GDALDataset *m_poDS = nullptr;
8525 : bool m_bEOF = true;
8526 : };
8527 :
8528 4 : GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8529 4 : : m_poPrivate(new GDALDataset::Features::Iterator::Private())
8530 : {
8531 4 : m_poPrivate->m_poDS = poDS;
8532 4 : if (bStart)
8533 : {
8534 2 : poDS->ResetReading();
8535 4 : m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(
8536 2 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8537 2 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8538 : }
8539 4 : }
8540 :
8541 : GDALDataset::Features::Iterator::~Iterator() = default;
8542 :
8543 : const GDALDataset::FeatureLayerPair &
8544 20 : GDALDataset::Features::Iterator::operator*() const
8545 : {
8546 20 : return m_poPrivate->m_oPair;
8547 : }
8548 :
8549 20 : GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()
8550 : {
8551 40 : m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(
8552 20 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8553 20 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8554 20 : return *this;
8555 : }
8556 :
8557 22 : bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const
8558 : {
8559 22 : return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
8560 : }
8561 :
8562 : /************************************************************************/
8563 : /* GetFeatures() */
8564 : /************************************************************************/
8565 :
8566 : /** Function that return an iterable object over features in the dataset
8567 : * layer.
8568 : *
8569 : * This is a C++ iterator friendly version of GetNextFeature().
8570 : *
8571 : * Using this iterator for standard range-based loops is safe, but
8572 : * due to implementation limitations, you shouldn't try to access
8573 : * (dereference) more than one iterator step at a time, since the
8574 : * FeatureLayerPair reference which is returned is reused.
8575 : *
8576 : * Typical use is:
8577 : * \code{.cpp}
8578 : * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
8579 : * {
8580 : * std::cout << "Feature of layer " <<
8581 : * oFeatureLayerPair.layer->GetName() << std::endl;
8582 : * oFeatureLayerPair.feature->DumpReadable();
8583 : * }
8584 : * \endcode
8585 : *
8586 : * @see GetNextFeature()
8587 : *
8588 : * @since GDAL 2.3
8589 : */
8590 2 : GDALDataset::Features GDALDataset::GetFeatures()
8591 : {
8592 2 : return Features(this);
8593 : }
8594 :
8595 : /************************************************************************/
8596 : /* begin() */
8597 : /************************************************************************/
8598 :
8599 : /**
8600 : \brief Return beginning of feature iterator.
8601 :
8602 : @since GDAL 2.3
8603 : */
8604 :
8605 2 : const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
8606 : {
8607 2 : return {m_poSelf, true};
8608 : }
8609 :
8610 : /************************************************************************/
8611 : /* end() */
8612 : /************************************************************************/
8613 :
8614 : /**
8615 : \brief Return end of feature iterator.
8616 :
8617 : @since GDAL 2.3
8618 : */
8619 :
8620 2 : const GDALDataset::Features::Iterator GDALDataset::Features::end() const
8621 : {
8622 2 : return {m_poSelf, false};
8623 : }
8624 :
8625 : /************************************************************************/
8626 : /* GDALDataset::Layers::Iterator::Private */
8627 : /************************************************************************/
8628 :
8629 : struct GDALDataset::Layers::Iterator::Private
8630 : {
8631 : OGRLayer *m_poLayer = nullptr;
8632 : int m_iCurLayer = 0;
8633 : int m_nLayerCount = 0;
8634 : GDALDataset *m_poDS = nullptr;
8635 : };
8636 :
8637 2 : GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())
8638 : {
8639 2 : }
8640 :
8641 : // False positive of cppcheck 1.72
8642 : // cppcheck-suppress uninitMemberVar
8643 9 : GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)
8644 9 : : m_poPrivate(new Private(*(oOther.m_poPrivate)))
8645 : {
8646 9 : }
8647 :
8648 5 : GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept
8649 5 : : m_poPrivate(std::move(oOther.m_poPrivate))
8650 : {
8651 5 : }
8652 :
8653 392 : GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8654 392 : : m_poPrivate(new Private())
8655 : {
8656 392 : m_poPrivate->m_poDS = poDS;
8657 392 : m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
8658 392 : if (bStart)
8659 : {
8660 197 : if (m_poPrivate->m_nLayerCount)
8661 196 : m_poPrivate->m_poLayer = poDS->GetLayer(0);
8662 : }
8663 : else
8664 : {
8665 195 : m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
8666 : }
8667 392 : }
8668 :
8669 : GDALDataset::Layers::Iterator::~Iterator() = default;
8670 :
8671 : // False positive of cppcheck 1.72
8672 : // cppcheck-suppress operatorEqVarError
8673 : GDALDataset::Layers::Iterator &
8674 1 : GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)
8675 : {
8676 1 : *m_poPrivate = *oOther.m_poPrivate;
8677 1 : return *this;
8678 : }
8679 :
8680 1 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(
8681 : GDALDataset::Layers::Iterator &&oOther) noexcept
8682 : {
8683 1 : m_poPrivate = std::move(oOther.m_poPrivate);
8684 1 : return *this;
8685 : }
8686 :
8687 233 : OGRLayer *GDALDataset::Layers::Iterator::operator*() const
8688 : {
8689 233 : return m_poPrivate->m_poLayer;
8690 : }
8691 :
8692 226 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()
8693 : {
8694 226 : m_poPrivate->m_iCurLayer++;
8695 226 : if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
8696 : {
8697 41 : m_poPrivate->m_poLayer =
8698 41 : m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
8699 : }
8700 : else
8701 : {
8702 185 : m_poPrivate->m_poLayer = nullptr;
8703 : }
8704 226 : return *this;
8705 : }
8706 :
8707 2 : GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
8708 : {
8709 2 : GDALDataset::Layers::Iterator temp = *this;
8710 2 : ++(*this);
8711 2 : return temp;
8712 : }
8713 :
8714 415 : bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const
8715 : {
8716 415 : return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
8717 : }
8718 :
8719 : /************************************************************************/
8720 : /* GetLayers() */
8721 : /************************************************************************/
8722 :
8723 : /** Function that returns an iterable object over layers in the dataset.
8724 : *
8725 : * This is a C++ iterator friendly version of GetLayer().
8726 : *
8727 : * Typical use is:
8728 : * \code{.cpp}
8729 : * for( auto&& poLayer: poDS->GetLayers() )
8730 : * {
8731 : * std::cout << "Layer << poLayer->GetName() << std::endl;
8732 : * }
8733 : * \endcode
8734 : *
8735 : * @see GetLayer()
8736 : *
8737 : * @since GDAL 2.3
8738 : */
8739 200 : GDALDataset::Layers GDALDataset::GetLayers()
8740 : {
8741 200 : return Layers(this);
8742 : }
8743 :
8744 : /************************************************************************/
8745 : /* begin() */
8746 : /************************************************************************/
8747 :
8748 : /**
8749 : \brief Return beginning of layer iterator.
8750 :
8751 : @since GDAL 2.3
8752 : */
8753 :
8754 197 : GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
8755 : {
8756 197 : return {m_poSelf, true};
8757 : }
8758 :
8759 : /************************************************************************/
8760 : /* end() */
8761 : /************************************************************************/
8762 :
8763 : /**
8764 : \brief Return end of layer iterator.
8765 :
8766 : @since GDAL 2.3
8767 : */
8768 :
8769 195 : GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
8770 : {
8771 195 : return {m_poSelf, false};
8772 : }
8773 :
8774 : /************************************************************************/
8775 : /* size() */
8776 : /************************************************************************/
8777 :
8778 : /**
8779 : \brief Get the number of layers in this dataset.
8780 :
8781 : @return layer count.
8782 :
8783 : @since GDAL 2.3
8784 : */
8785 :
8786 1 : size_t GDALDataset::Layers::size() const
8787 : {
8788 1 : return static_cast<size_t>(m_poSelf->GetLayerCount());
8789 : }
8790 :
8791 : /************************************************************************/
8792 : /* operator[]() */
8793 : /************************************************************************/
8794 : /**
8795 : \brief Fetch a layer by index.
8796 :
8797 : The returned layer remains owned by the
8798 : GDALDataset and should not be deleted by the application.
8799 :
8800 : @param iLayer a layer number between 0 and size()-1.
8801 :
8802 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
8803 :
8804 : @since GDAL 2.3
8805 : */
8806 :
8807 9 : OGRLayer *GDALDataset::Layers::operator[](int iLayer)
8808 : {
8809 9 : return m_poSelf->GetLayer(iLayer);
8810 : }
8811 :
8812 : /************************************************************************/
8813 : /* operator[]() */
8814 : /************************************************************************/
8815 : /**
8816 : \brief Fetch a layer by index.
8817 :
8818 : The returned layer remains owned by the
8819 : GDALDataset and should not be deleted by the application.
8820 :
8821 : @param iLayer a layer number between 0 and size()-1.
8822 :
8823 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
8824 :
8825 : @since GDAL 2.3
8826 : */
8827 :
8828 1 : OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)
8829 : {
8830 1 : return m_poSelf->GetLayer(static_cast<int>(iLayer));
8831 : }
8832 :
8833 : /************************************************************************/
8834 : /* operator[]() */
8835 : /************************************************************************/
8836 : /**
8837 : \brief Fetch a layer by name.
8838 :
8839 : The returned layer remains owned by the
8840 : GDALDataset and should not be deleted by the application.
8841 :
8842 : @param pszLayerName layer name
8843 :
8844 : @return the layer, or nullptr if pszLayerName does not match with a layer
8845 :
8846 : @since GDAL 2.3
8847 : */
8848 :
8849 1 : OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)
8850 : {
8851 1 : return m_poSelf->GetLayerByName(pszLayerName);
8852 : }
8853 :
8854 : /************************************************************************/
8855 : /* GDALDataset::Bands::Iterator::Private */
8856 : /************************************************************************/
8857 :
8858 : struct GDALDataset::Bands::Iterator::Private
8859 : {
8860 : GDALRasterBand *m_poBand = nullptr;
8861 : int m_iCurBand = 0;
8862 : int m_nBandCount = 0;
8863 : GDALDataset *m_poDS = nullptr;
8864 : };
8865 :
8866 6 : GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8867 6 : : m_poPrivate(new GDALDataset::Bands::Iterator::Private())
8868 : {
8869 6 : m_poPrivate->m_poDS = poDS;
8870 6 : m_poPrivate->m_nBandCount = poDS->GetRasterCount();
8871 6 : if (bStart)
8872 : {
8873 3 : if (m_poPrivate->m_nBandCount)
8874 3 : m_poPrivate->m_poBand = poDS->GetRasterBand(1);
8875 : }
8876 : else
8877 : {
8878 3 : m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
8879 : }
8880 6 : }
8881 :
8882 : GDALDataset::Bands::Iterator::~Iterator() = default;
8883 :
8884 5 : GDALRasterBand *GDALDataset::Bands::Iterator::operator*()
8885 : {
8886 5 : return m_poPrivate->m_poBand;
8887 : }
8888 :
8889 3 : GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()
8890 : {
8891 3 : m_poPrivate->m_iCurBand++;
8892 3 : if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
8893 : {
8894 2 : m_poPrivate->m_poBand =
8895 2 : m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
8896 : }
8897 : else
8898 : {
8899 1 : m_poPrivate->m_poBand = nullptr;
8900 : }
8901 3 : return *this;
8902 : }
8903 :
8904 6 : bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const
8905 : {
8906 6 : return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
8907 : }
8908 :
8909 : /************************************************************************/
8910 : /* GetBands() */
8911 : /************************************************************************/
8912 :
8913 : /** Function that returns an iterable object over GDALRasterBand in the dataset.
8914 : *
8915 : * This is a C++ iterator friendly version of GetRasterBand().
8916 : *
8917 : * Typical use is:
8918 : * \code{.cpp}
8919 : * for( auto&& poBand: poDS->GetBands() )
8920 : * {
8921 : * std::cout << "Band << poBand->GetDescription() << std::endl;
8922 : * }
8923 : * \endcode
8924 : *
8925 : * @see GetRasterBand()
8926 : *
8927 : * @since GDAL 2.3
8928 : */
8929 7 : GDALDataset::Bands GDALDataset::GetBands()
8930 : {
8931 7 : return Bands(this);
8932 : }
8933 :
8934 : /************************************************************************/
8935 : /* begin() */
8936 : /************************************************************************/
8937 :
8938 : /**
8939 : \brief Return beginning of band iterator.
8940 :
8941 : @since GDAL 2.3
8942 : */
8943 :
8944 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
8945 : {
8946 3 : return {m_poSelf, true};
8947 : }
8948 :
8949 : /************************************************************************/
8950 : /* end() */
8951 : /************************************************************************/
8952 :
8953 : /**
8954 : \brief Return end of band iterator.
8955 :
8956 : @since GDAL 2.3
8957 : */
8958 :
8959 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
8960 : {
8961 3 : return {m_poSelf, false};
8962 : }
8963 :
8964 : /************************************************************************/
8965 : /* size() */
8966 : /************************************************************************/
8967 :
8968 : /**
8969 : \brief Get the number of raster bands in this dataset.
8970 :
8971 : @return raster band count.
8972 :
8973 : @since GDAL 2.3
8974 : */
8975 :
8976 2 : size_t GDALDataset::Bands::size() const
8977 : {
8978 2 : return static_cast<size_t>(m_poSelf->GetRasterCount());
8979 : }
8980 :
8981 : /************************************************************************/
8982 : /* operator[]() */
8983 : /************************************************************************/
8984 : /**
8985 : \brief Fetch a raster band by index.
8986 :
8987 : The returned band remains owned by the
8988 : GDALDataset and should not be deleted by the application.
8989 :
8990 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
8991 : consistent with the conventions of C/C++, i.e. starting at 0.
8992 :
8993 : @param iBand a band index between 0 and size()-1.
8994 :
8995 : @return the band, or nullptr if iBand is out of range or an error occurs.
8996 :
8997 : @since GDAL 2.3
8998 : */
8999 :
9000 1 : GDALRasterBand *GDALDataset::Bands::operator[](int iBand)
9001 : {
9002 1 : return m_poSelf->GetRasterBand(1 + iBand);
9003 : }
9004 :
9005 : /************************************************************************/
9006 : /* operator[]() */
9007 : /************************************************************************/
9008 :
9009 : /**
9010 : \brief Fetch a raster band by index.
9011 :
9012 : The returned band remains owned by the
9013 : GDALDataset and should not be deleted by the application.
9014 :
9015 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9016 : consistent with the conventions of C/C++, i.e. starting at 0.
9017 :
9018 : @param iBand a band index between 0 and size()-1.
9019 :
9020 : @return the band, or nullptr if iBand is out of range or an error occurs.
9021 :
9022 : @since GDAL 2.3
9023 : */
9024 :
9025 1 : GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)
9026 : {
9027 1 : return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
9028 : }
9029 :
9030 : /************************************************************************/
9031 : /* GetRootGroup() */
9032 : /************************************************************************/
9033 :
9034 : /**
9035 : \brief Return the root GDALGroup of this dataset.
9036 :
9037 : Only valid for multidimensional datasets.
9038 :
9039 : This is the same as the C function GDALDatasetGetRootGroup().
9040 :
9041 : @since GDAL 3.1
9042 : */
9043 :
9044 2672 : std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
9045 : {
9046 2672 : return nullptr;
9047 : }
9048 :
9049 : /************************************************************************/
9050 : /* GetRawBinaryLayout() */
9051 : /************************************************************************/
9052 :
9053 : //! @cond Doxygen_Suppress
9054 : /**
9055 : \brief Return the layout of a dataset that can be considered as a raw binary
9056 : format.
9057 :
9058 : @param sLayout Structure that will be set if the dataset is a raw binary one.
9059 : @return true if the dataset is a raw binary one.
9060 : @since GDAL 3.1
9061 : */
9062 :
9063 0 : bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)
9064 : {
9065 0 : CPL_IGNORE_RET_VAL(sLayout);
9066 0 : return false;
9067 : }
9068 :
9069 : //! @endcond
9070 :
9071 : /************************************************************************/
9072 : /* ClearStatistics() */
9073 : /************************************************************************/
9074 :
9075 : /**
9076 : \brief Clear statistics
9077 :
9078 : Only implemented for now in PAM supported datasets
9079 :
9080 : This is the same as the C function GDALDatasetClearStatistics().
9081 :
9082 : @since GDAL 3.2
9083 : */
9084 :
9085 4 : void GDALDataset::ClearStatistics()
9086 : {
9087 8 : auto poRootGroup = GetRootGroup();
9088 4 : if (poRootGroup)
9089 1 : poRootGroup->ClearStatistics();
9090 4 : }
9091 :
9092 : /************************************************************************/
9093 : /* GDALDatasetClearStatistics() */
9094 : /************************************************************************/
9095 :
9096 : /**
9097 : \brief Clear statistics
9098 :
9099 : This is the same as the C++ method GDALDataset::ClearStatistics().
9100 :
9101 : @since GDAL 3.2
9102 : */
9103 :
9104 2 : void GDALDatasetClearStatistics(GDALDatasetH hDS)
9105 : {
9106 2 : VALIDATE_POINTER0(hDS, __func__);
9107 2 : GDALDataset::FromHandle(hDS)->ClearStatistics();
9108 : }
9109 :
9110 : /************************************************************************/
9111 : /* GetFieldDomainNames() */
9112 : /************************************************************************/
9113 :
9114 : /** Returns a list of the names of all field domains stored in the dataset.
9115 : *
9116 : * @note The default implementation assumes that drivers fully populate
9117 : * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect
9118 : * then a specialized implementation of GetFieldDomainNames() must be
9119 : * implemented.
9120 : *
9121 : * @param papszOptions Driver specific options determining how attributes
9122 : * should be retrieved. Pass nullptr for default behavior.
9123 : *
9124 : * @return list of field domain names
9125 : * @since GDAL 3.5
9126 : */
9127 : std::vector<std::string>
9128 40 : GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const
9129 : {
9130 :
9131 40 : std::vector<std::string> names;
9132 40 : names.reserve(m_oMapFieldDomains.size());
9133 52 : for (const auto &it : m_oMapFieldDomains)
9134 : {
9135 12 : names.emplace_back(it.first);
9136 : }
9137 40 : return names;
9138 : }
9139 :
9140 : /************************************************************************/
9141 : /* GDALDatasetGetFieldDomainNames() */
9142 : /************************************************************************/
9143 :
9144 : /** Returns a list of the names of all field domains stored in the dataset.
9145 : *
9146 : * This is the same as the C++ method GDALDataset::GetFieldDomainNames().
9147 : *
9148 : * @param hDS Dataset handle.
9149 : * @param papszOptions Driver specific options determining how attributes
9150 : * should be retrieved. Pass nullptr for default behavior.
9151 : *
9152 : * @return list of field domain names, to be freed with CSLDestroy()
9153 : * @since GDAL 3.5
9154 : */
9155 32 : char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,
9156 : CSLConstList papszOptions)
9157 : {
9158 32 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9159 : auto names =
9160 64 : GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);
9161 64 : CPLStringList res;
9162 137 : for (const auto &name : names)
9163 : {
9164 105 : res.AddString(name.c_str());
9165 : }
9166 32 : return res.StealList();
9167 : }
9168 :
9169 : /************************************************************************/
9170 : /* GetFieldDomain() */
9171 : /************************************************************************/
9172 :
9173 : /** Get a field domain from its name.
9174 : *
9175 : * @return the field domain, or nullptr if not found.
9176 : * @since GDAL 3.3
9177 : */
9178 265 : const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const
9179 : {
9180 265 : const auto iter = m_oMapFieldDomains.find(name);
9181 265 : if (iter == m_oMapFieldDomains.end())
9182 113 : return nullptr;
9183 152 : return iter->second.get();
9184 : }
9185 :
9186 : /************************************************************************/
9187 : /* GDALDatasetGetFieldDomain() */
9188 : /************************************************************************/
9189 :
9190 : /** Get a field domain from its name.
9191 : *
9192 : * This is the same as the C++ method GDALDataset::GetFieldDomain().
9193 : *
9194 : * @param hDS Dataset handle.
9195 : * @param pszName Name of field domain.
9196 : * @return the field domain (ownership remains to the dataset), or nullptr if
9197 : * not found.
9198 : * @since GDAL 3.3
9199 : */
9200 112 : OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)
9201 : {
9202 112 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9203 112 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9204 112 : return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(
9205 112 : GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
9206 : }
9207 :
9208 : /************************************************************************/
9209 : /* AddFieldDomain() */
9210 : /************************************************************************/
9211 :
9212 : /** Add a field domain to the dataset.
9213 : *
9214 : * Only a few drivers will support this operation, and some of them might only
9215 : * support it only for some types of field domains.
9216 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9217 : * support this operation. A dataset having at least some support for this
9218 : * operation should report the ODsCAddFieldDomain dataset capability.
9219 : *
9220 : * Anticipated failures will not be emitted through the CPLError()
9221 : * infrastructure, but will be reported in the failureReason output parameter.
9222 : *
9223 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9224 : * default implementation of GetFieldDomainNames() to work correctly, or
9225 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9226 : * implemented.
9227 : *
9228 : * @param domain The domain definition.
9229 : * @param failureReason Output parameter. Will contain an error message if
9230 : * an error occurs.
9231 : * @return true in case of success.
9232 : * @since GDAL 3.3
9233 : */
9234 0 : bool GDALDataset::AddFieldDomain(
9235 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9236 : std::string &failureReason)
9237 : {
9238 0 : failureReason = "AddFieldDomain not supported by this driver";
9239 0 : return false;
9240 : }
9241 :
9242 : /************************************************************************/
9243 : /* GDALDatasetAddFieldDomain() */
9244 : /************************************************************************/
9245 :
9246 : /** Add a field domain to the dataset.
9247 : *
9248 : * Only a few drivers will support this operation, and some of them might only
9249 : * support it only for some types of field domains.
9250 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9251 : * support this operation. A dataset having at least some support for this
9252 : * operation should report the ODsCAddFieldDomain dataset capability.
9253 : *
9254 : * Anticipated failures will not be emitted through the CPLError()
9255 : * infrastructure, but will be reported in the ppszFailureReason output
9256 : * parameter.
9257 : *
9258 : * @param hDS Dataset handle.
9259 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9260 : * the passed object is copied.
9261 : * @param ppszFailureReason Output parameter. Will contain an error message if
9262 : * an error occurs (*ppszFailureReason to be freed
9263 : * with CPLFree). May be NULL.
9264 : * @return true in case of success.
9265 : * @since GDAL 3.3
9266 : */
9267 34 : bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,
9268 : char **ppszFailureReason)
9269 : {
9270 34 : VALIDATE_POINTER1(hDS, __func__, false);
9271 34 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9272 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9273 68 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9274 34 : if (poDomain == nullptr)
9275 0 : return false;
9276 34 : std::string failureReason;
9277 68 : const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(
9278 34 : std::move(poDomain), failureReason);
9279 34 : if (ppszFailureReason)
9280 : {
9281 0 : *ppszFailureReason =
9282 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9283 : }
9284 34 : return bRet;
9285 : }
9286 :
9287 : /************************************************************************/
9288 : /* DeleteFieldDomain() */
9289 : /************************************************************************/
9290 :
9291 : /** Removes a field domain from the dataset.
9292 : *
9293 : * Only a few drivers will support this operation.
9294 : *
9295 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9296 : * support this operation. A dataset having at least some support for this
9297 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9298 : *
9299 : * Anticipated failures will not be emitted through the CPLError()
9300 : * infrastructure, but will be reported in the failureReason output parameter.
9301 : *
9302 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9303 : * default implementation of GetFieldDomainNames() to work correctly, or
9304 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9305 : * implemented.
9306 : *
9307 : * @param name The domain name.
9308 : * @param failureReason Output parameter. Will contain an error message if
9309 : * an error occurs.
9310 : * @return true in case of success.
9311 : * @since GDAL 3.5
9312 : */
9313 0 : bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,
9314 : std::string &failureReason)
9315 : {
9316 0 : failureReason = "DeleteFieldDomain not supported by this driver";
9317 0 : return false;
9318 : }
9319 :
9320 : /************************************************************************/
9321 : /* GDALDatasetDeleteFieldDomain() */
9322 : /************************************************************************/
9323 :
9324 : /** Removes a field domain from the dataset.
9325 : *
9326 : * Only a few drivers will support this operation.
9327 : *
9328 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9329 : * support this operation. A dataset having at least some support for this
9330 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9331 : *
9332 : * Anticipated failures will not be emitted through the CPLError()
9333 : * infrastructure, but will be reported in the ppszFailureReason output
9334 : * parameter.
9335 : *
9336 : * @param hDS Dataset handle.
9337 : * @param pszName The domain name.
9338 : * @param ppszFailureReason Output parameter. Will contain an error message if
9339 : * an error occurs (*ppszFailureReason to be freed
9340 : * with CPLFree). May be NULL.
9341 : * @return true in case of success.
9342 : * @since GDAL 3.3
9343 : */
9344 8 : bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,
9345 : char **ppszFailureReason)
9346 : {
9347 8 : VALIDATE_POINTER1(hDS, __func__, false);
9348 8 : VALIDATE_POINTER1(pszName, __func__, false);
9349 8 : std::string failureReason;
9350 : const bool bRet =
9351 8 : GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);
9352 8 : if (ppszFailureReason)
9353 : {
9354 0 : *ppszFailureReason =
9355 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9356 : }
9357 8 : return bRet;
9358 : }
9359 :
9360 : /************************************************************************/
9361 : /* UpdateFieldDomain() */
9362 : /************************************************************************/
9363 :
9364 : /** Updates an existing field domain by replacing its definition.
9365 : *
9366 : * The existing field domain with matching name will be replaced.
9367 : *
9368 : * Only a few drivers will support this operation, and some of them might only
9369 : * support it only for some types of field domains.
9370 : * At the time of writing (GDAL 3.5), only the Memory driver
9371 : * supports this operation. A dataset having at least some support for this
9372 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9373 : *
9374 : * Anticipated failures will not be emitted through the CPLError()
9375 : * infrastructure, but will be reported in the failureReason output parameter.
9376 : *
9377 : * @param domain The domain definition.
9378 : * @param failureReason Output parameter. Will contain an error message if
9379 : * an error occurs.
9380 : * @return true in case of success.
9381 : * @since GDAL 3.5
9382 : */
9383 0 : bool GDALDataset::UpdateFieldDomain(
9384 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9385 : std::string &failureReason)
9386 : {
9387 0 : failureReason = "UpdateFieldDomain not supported by this driver";
9388 0 : return false;
9389 : }
9390 :
9391 : /************************************************************************/
9392 : /* GDALDatasetUpdateFieldDomain() */
9393 : /************************************************************************/
9394 :
9395 : /** Updates an existing field domain by replacing its definition.
9396 : *
9397 : * The existing field domain with matching name will be replaced.
9398 : *
9399 : * Only a few drivers will support this operation, and some of them might only
9400 : * support it only for some types of field domains.
9401 : * At the time of writing (GDAL 3.5), only the Memory driver
9402 : * supports this operation. A dataset having at least some support for this
9403 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9404 : *
9405 : * Anticipated failures will not be emitted through the CPLError()
9406 : * infrastructure, but will be reported in the failureReason output parameter.
9407 : *
9408 : * @param hDS Dataset handle.
9409 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9410 : * the passed object is copied.
9411 : * @param ppszFailureReason Output parameter. Will contain an error message if
9412 : * an error occurs (*ppszFailureReason to be freed
9413 : * with CPLFree). May be NULL.
9414 : * @return true in case of success.
9415 : * @since GDAL 3.5
9416 : */
9417 4 : bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,
9418 : OGRFieldDomainH hFieldDomain,
9419 : char **ppszFailureReason)
9420 : {
9421 4 : VALIDATE_POINTER1(hDS, __func__, false);
9422 4 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9423 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9424 8 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9425 4 : if (poDomain == nullptr)
9426 0 : return false;
9427 4 : std::string failureReason;
9428 8 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(
9429 4 : std::move(poDomain), failureReason);
9430 4 : if (ppszFailureReason)
9431 : {
9432 0 : *ppszFailureReason =
9433 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9434 : }
9435 4 : return bRet;
9436 : }
9437 :
9438 : /************************************************************************/
9439 : /* GetRelationshipNames() */
9440 : /************************************************************************/
9441 :
9442 : /** Returns a list of the names of all relationships stored in the dataset.
9443 : *
9444 : * @param papszOptions Driver specific options determining how relationships
9445 : * should be retrieved. Pass nullptr for default behavior.
9446 : *
9447 : * @return list of relationship names
9448 : * @since GDAL 3.6
9449 : */
9450 : std::vector<std::string>
9451 155 : GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const
9452 : {
9453 155 : return {};
9454 : }
9455 :
9456 : /************************************************************************/
9457 : /* GDALDatasetGetRelationshipNames() */
9458 : /************************************************************************/
9459 :
9460 : /** Returns a list of the names of all relationships stored in the dataset.
9461 : *
9462 : * This is the same as the C++ method GDALDataset::GetRelationshipNames().
9463 : *
9464 : * @param hDS Dataset handle.
9465 : * @param papszOptions Driver specific options determining how relationships
9466 : * should be retrieved. Pass nullptr for default behavior.
9467 : *
9468 : * @return list of relationship names, to be freed with CSLDestroy()
9469 : * @since GDAL 3.6
9470 : */
9471 46 : char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,
9472 : CSLConstList papszOptions)
9473 : {
9474 46 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9475 : auto names =
9476 92 : GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);
9477 92 : CPLStringList res;
9478 146 : for (const auto &name : names)
9479 : {
9480 100 : res.AddString(name.c_str());
9481 : }
9482 46 : return res.StealList();
9483 : }
9484 :
9485 : /************************************************************************/
9486 : /* GetRelationship() */
9487 : /************************************************************************/
9488 :
9489 : /** Get a relationship from its name.
9490 : *
9491 : * @return the relationship, or nullptr if not found.
9492 : * @since GDAL 3.6
9493 : */
9494 : const GDALRelationship *
9495 0 : GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const
9496 : {
9497 0 : return nullptr;
9498 : }
9499 :
9500 : /************************************************************************/
9501 : /* GDALDatasetGetRelationship() */
9502 : /************************************************************************/
9503 :
9504 : /** Get a relationship from its name.
9505 : *
9506 : * This is the same as the C++ method GDALDataset::GetRelationship().
9507 : *
9508 : * @param hDS Dataset handle.
9509 : * @param pszName Name of relationship.
9510 : * @return the relationship (ownership remains to the dataset), or nullptr if
9511 : * not found.
9512 : * @since GDAL 3.6
9513 : */
9514 52 : GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,
9515 : const char *pszName)
9516 : {
9517 52 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9518 52 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9519 52 : return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(
9520 52 : GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));
9521 : }
9522 :
9523 : /************************************************************************/
9524 : /* AddRelationship() */
9525 : /************************************************************************/
9526 :
9527 : /** Add a relationship to the dataset.
9528 : *
9529 : * Only a few drivers will support this operation, and some of them might only
9530 : * support it only for some types of relationships.
9531 : *
9532 : * A dataset having at least some support for this
9533 : * operation should report the GDsCAddRelationship dataset capability.
9534 : *
9535 : * Anticipated failures will not be emitted through the CPLError()
9536 : * infrastructure, but will be reported in the failureReason output parameter.
9537 : *
9538 : * When adding a many-to-many relationship
9539 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9540 : * mapping table name (see GDALRelationship::GetMappingTableName) to instruct
9541 : * the driver to create an appropriately named and structured mapping table.
9542 : * Some dataset formats require particular naming conventions and field
9543 : * structures for the mapping table, and delegating the construction of the
9544 : * mapping table to the driver will avoid these pitfalls.
9545 : *
9546 : * @param relationship The relationship definition.
9547 : * @param failureReason Output parameter. Will contain an error message if
9548 : * an error occurs.
9549 : * @return true in case of success.
9550 : * @since GDAL 3.6
9551 : */
9552 0 : bool GDALDataset::AddRelationship(
9553 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9554 : std::string &failureReason)
9555 : {
9556 0 : failureReason = "AddRelationship not supported by this driver";
9557 0 : return false;
9558 : }
9559 :
9560 : /************************************************************************/
9561 : /* GDALDatasetAddRelationship() */
9562 : /************************************************************************/
9563 :
9564 : /** Add a relationship to the dataset.
9565 : *
9566 : * Only a few drivers will support this operation, and some of them might only
9567 : * support it only for some types of relationships.
9568 : *
9569 : * A dataset having at least some support for this
9570 : * operation should report the GDsCAddRelationship dataset capability.
9571 : *
9572 : * Anticipated failures will not be emitted through the CPLError()
9573 : * infrastructure, but will be reported in the failureReason output parameter.
9574 : *
9575 : * When adding a many-to-many relationship
9576 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9577 : * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the
9578 : * driver to create an appropriately named and structured mapping table. Some
9579 : * dataset formats require particular naming conventions and field structures
9580 : * for the mapping table, and delegating the construction of the mapping table
9581 : * to the driver will avoid these pitfalls.
9582 : *
9583 : * @param hDS Dataset handle.
9584 : * @param hRelationship The relationship definition. Contrary to the C++
9585 : * version, the passed object is copied.
9586 : * @param ppszFailureReason Output parameter. Will contain an error message if
9587 : * an error occurs (*ppszFailureReason to be freed
9588 : * with CPLFree). May be NULL.
9589 : * @return true in case of success.
9590 : * @since GDAL 3.6
9591 : */
9592 42 : bool GDALDatasetAddRelationship(GDALDatasetH hDS,
9593 : GDALRelationshipH hRelationship,
9594 : char **ppszFailureReason)
9595 : {
9596 42 : VALIDATE_POINTER1(hDS, __func__, false);
9597 42 : VALIDATE_POINTER1(hRelationship, __func__, false);
9598 : std::unique_ptr<GDALRelationship> poRelationship(
9599 84 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9600 42 : std::string failureReason;
9601 84 : const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(
9602 42 : std::move(poRelationship), failureReason);
9603 42 : if (ppszFailureReason)
9604 : {
9605 0 : *ppszFailureReason =
9606 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9607 : }
9608 42 : return bRet;
9609 : }
9610 :
9611 : /************************************************************************/
9612 : /* DeleteRelationship() */
9613 : /************************************************************************/
9614 :
9615 : /** Removes a relationship from the dataset.
9616 : *
9617 : * Only a few drivers will support this operation.
9618 : *
9619 : * A dataset having at least some support for this
9620 : * operation should report the GDsCDeleteRelationship dataset capability.
9621 : *
9622 : * Anticipated failures will not be emitted through the CPLError()
9623 : * infrastructure, but will be reported in the failureReason output parameter.
9624 : *
9625 : * @param name The relationship name.
9626 : * @param failureReason Output parameter. Will contain an error message if
9627 : * an error occurs.
9628 : * @return true in case of success.
9629 : * @since GDAL 3.6
9630 : */
9631 0 : bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,
9632 : std::string &failureReason)
9633 : {
9634 0 : failureReason = "DeleteRelationship not supported by this driver";
9635 0 : return false;
9636 : }
9637 :
9638 : /************************************************************************/
9639 : /* GDALDatasetDeleteRelationship() */
9640 : /************************************************************************/
9641 :
9642 : /** Removes a relationship from the dataset.
9643 : *
9644 : * Only a few drivers will support this operation.
9645 : *
9646 : * A dataset having at least some support for this
9647 : * operation should report the GDsCDeleteRelationship dataset capability.
9648 : *
9649 : * Anticipated failures will not be emitted through the CPLError()
9650 : * infrastructure, but will be reported in the ppszFailureReason output
9651 : * parameter.
9652 : *
9653 : * @param hDS Dataset handle.
9654 : * @param pszName The relationship name.
9655 : * @param ppszFailureReason Output parameter. Will contain an error message if
9656 : * an error occurs (*ppszFailureReason to be freed
9657 : * with CPLFree). May be NULL.
9658 : * @return true in case of success.
9659 : * @since GDAL 3.6
9660 : */
9661 6 : bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,
9662 : char **ppszFailureReason)
9663 : {
9664 6 : VALIDATE_POINTER1(hDS, __func__, false);
9665 6 : VALIDATE_POINTER1(pszName, __func__, false);
9666 6 : std::string failureReason;
9667 12 : const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(
9668 6 : pszName, failureReason);
9669 6 : if (ppszFailureReason)
9670 : {
9671 0 : *ppszFailureReason =
9672 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9673 : }
9674 6 : return bRet;
9675 : }
9676 :
9677 : /************************************************************************/
9678 : /* UpdateRelationship() */
9679 : /************************************************************************/
9680 :
9681 : /** Updates an existing relationship by replacing its definition.
9682 : *
9683 : * The existing relationship with matching name will be replaced.
9684 : *
9685 : * Only a few drivers will support this operation, and some of them might only
9686 : * support it only for some types of relationships.
9687 : * A dataset having at least some support for this
9688 : * operation should report the GDsCUpdateRelationship dataset capability.
9689 : *
9690 : * Anticipated failures will not be emitted through the CPLError()
9691 : * infrastructure, but will be reported in the failureReason output parameter.
9692 : *
9693 : * @param relationship The relationship definition.
9694 : * @param failureReason Output parameter. Will contain an error message if
9695 : * an error occurs.
9696 : * @return true in case of success.
9697 : * @since GDAL 3.6
9698 : */
9699 0 : bool GDALDataset::UpdateRelationship(
9700 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9701 : std::string &failureReason)
9702 : {
9703 0 : failureReason = "UpdateRelationship not supported by this driver";
9704 0 : return false;
9705 : }
9706 :
9707 : /************************************************************************/
9708 : /* GDALDatasetUpdateRelationship() */
9709 : /************************************************************************/
9710 :
9711 : /** Updates an existing relationship by replacing its definition.
9712 : *
9713 : * The existing relationship with matching name will be replaced.
9714 : *
9715 : * Only a few drivers will support this operation, and some of them might only
9716 : * support it only for some types of relationships.
9717 : * A dataset having at least some support for this
9718 : * operation should report the GDsCUpdateRelationship dataset capability.
9719 : *
9720 : * Anticipated failures will not be emitted through the CPLError()
9721 : * infrastructure, but will be reported in the failureReason output parameter.
9722 : *
9723 : * @param hDS Dataset handle.
9724 : * @param hRelationship The relationship definition. Contrary to the C++
9725 : * version, the passed object is copied.
9726 : * @param ppszFailureReason Output parameter. Will contain an error message if
9727 : * an error occurs (*ppszFailureReason to be freed
9728 : * with CPLFree). May be NULL.
9729 : * @return true in case of success.
9730 : * @since GDAL 3.5
9731 : */
9732 9 : bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,
9733 : GDALRelationshipH hRelationship,
9734 : char **ppszFailureReason)
9735 : {
9736 9 : VALIDATE_POINTER1(hDS, __func__, false);
9737 9 : VALIDATE_POINTER1(hRelationship, __func__, false);
9738 : std::unique_ptr<GDALRelationship> poRelationship(
9739 18 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9740 9 : std::string failureReason;
9741 18 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(
9742 9 : std::move(poRelationship), failureReason);
9743 9 : if (ppszFailureReason)
9744 : {
9745 0 : *ppszFailureReason =
9746 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9747 : }
9748 9 : return bRet;
9749 : }
9750 :
9751 : /************************************************************************/
9752 : /* GDALDatasetSetQueryLoggerFunc() */
9753 : /************************************************************************/
9754 :
9755 : /**
9756 : * Sets the SQL query logger callback.
9757 : *
9758 : * When supported by the driver, the callback will be called with
9759 : * the executed SQL text, the error message, the execution time in milliseconds,
9760 : * the number of records fetched/affected and the client status data.
9761 : *
9762 : * A value of -1 in the execution time or in the number of records indicates
9763 : * that the values are unknown.
9764 : *
9765 : * @param hDS Dataset handle.
9766 : * @param pfnQueryLoggerFunc Callback function
9767 : * @param poQueryLoggerArg Opaque client status data
9768 : * @return true in case of success.
9769 : * @since GDAL 3.7
9770 : */
9771 1 : bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,
9772 : GDALQueryLoggerFunc pfnQueryLoggerFunc,
9773 : void *poQueryLoggerArg)
9774 : {
9775 1 : VALIDATE_POINTER1(hDS, __func__, false);
9776 2 : return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,
9777 1 : poQueryLoggerArg);
9778 : }
9779 :
9780 : //! @cond Doxygen_Suppress
9781 :
9782 : /************************************************************************/
9783 : /* SetEnableOverviews() */
9784 : /************************************************************************/
9785 :
9786 7491 : void GDALDataset::SetEnableOverviews(bool bEnable)
9787 : {
9788 7491 : if (m_poPrivate)
9789 : {
9790 7491 : m_poPrivate->m_bOverviewsEnabled = bEnable;
9791 : }
9792 7491 : }
9793 :
9794 : /************************************************************************/
9795 : /* AreOverviewsEnabled() */
9796 : /************************************************************************/
9797 :
9798 2005460 : bool GDALDataset::AreOverviewsEnabled() const
9799 : {
9800 2005460 : return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
9801 : }
9802 :
9803 : /************************************************************************/
9804 : /* IsAllBands() */
9805 : /************************************************************************/
9806 :
9807 3414 : bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const
9808 : {
9809 3414 : if (nBands != nBandCount)
9810 1 : return false;
9811 3413 : if (panBandList)
9812 : {
9813 12308 : for (int i = 0; i < nBandCount; ++i)
9814 : {
9815 8984 : if (panBandList[i] != i + 1)
9816 25 : return false;
9817 : }
9818 : }
9819 3388 : return true;
9820 : }
9821 :
9822 : //! @endcond
9823 :
9824 : /************************************************************************/
9825 : /* GetCompressionFormats() */
9826 : /************************************************************************/
9827 :
9828 : /** Return the compression formats that can be natively obtained for the
9829 : * window of interest and requested bands.
9830 : *
9831 : * For example, a tiled dataset may be able to return data in a compressed
9832 : * format if the window of interest matches exactly a tile. For some formats,
9833 : * drivers may also be able to merge several tiles together (not currently
9834 : * implemented though).
9835 : *
9836 : * Each format string is a pseudo MIME type, whose first part can be passed
9837 : * as the pszFormat argument of ReadCompressedData(), with additional
9838 : * parameters specified as key=value with a semi-colon separator.
9839 : *
9840 : * The amount and types of optional parameters passed after the MIME type is
9841 : * format dependent, and driver dependent (some drivers might not be able to
9842 : * return those extra information without doing a rather costly processing).
9843 : *
9844 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9845 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9846 : * consequently "JPEG" can be passed as the pszFormat argument of
9847 : * ReadCompressedData(). For JPEG, implementations can use the
9848 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9849 : * above from a JPEG codestream.
9850 : *
9851 : * Several values might be returned. For example,
9852 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9853 : * if the JPEGXL codestream includes a JPEG reconstruction box.
9854 : *
9855 : * In the general case this method will return an empty list.
9856 : *
9857 : * This is the same as C function GDALDatasetGetCompressionFormats().
9858 : *
9859 : * @param nXOff The pixel offset to the top left corner of the region
9860 : * of the band to be accessed. This would be zero to start from the left side.
9861 : *
9862 : * @param nYOff The line offset to the top left corner of the region
9863 : * of the band to be accessed. This would be zero to start from the top.
9864 : *
9865 : * @param nXSize The width of the region of the band to be accessed in pixels.
9866 : *
9867 : * @param nYSize The height of the region of the band to be accessed in lines.
9868 : *
9869 : * @param nBandCount the number of bands being requested.
9870 : *
9871 : * @param panBandList the list of nBandCount band numbers.
9872 : * Note band numbers are 1 based. This may be NULL to select the first
9873 : * nBandCount bands.
9874 : *
9875 : * @return a list of compatible formats (which may be empty)
9876 : *
9877 : * For example, to check if native compression format(s) are available on the
9878 : * whole image:
9879 : * \code{.cpp}
9880 : * const CPLStringList aosFormats =
9881 : * poDataset->GetCompressionFormats(0, 0,
9882 : * poDataset->GetRasterXSize(),
9883 : * poDataset->GetRasterYSize(),
9884 : * poDataset->GetRasterCount(),
9885 : * nullptr);
9886 : * for( const char* pszFormat: aosFormats )
9887 : * {
9888 : * // Remove optional parameters and just print out the MIME type.
9889 : * const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));
9890 : * printf("Found format %s\n, aosTokens[0]);
9891 : * }
9892 : * \endcode
9893 : *
9894 : * @since GDAL 3.7
9895 : */
9896 : CPLStringList
9897 0 : GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
9898 : CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
9899 : CPL_UNUSED int nBandCount,
9900 : CPL_UNUSED const int *panBandList)
9901 : {
9902 0 : return CPLStringList();
9903 : }
9904 :
9905 : /************************************************************************/
9906 : /* GDALDatasetGetCompressionFormats() */
9907 : /************************************************************************/
9908 :
9909 : /** Return the compression formats that can be natively obtained for the
9910 : * window of interest and requested bands.
9911 : *
9912 : * For example, a tiled dataset may be able to return data in a compressed
9913 : * format if the window of interest matches exactly a tile. For some formats,
9914 : * drivers may also be able to merge several tiles together (not currently
9915 : * implemented though).
9916 : *
9917 : * Each format string is a pseudo MIME type, whose first part can be passed
9918 : * as the pszFormat argument of ReadCompressedData(), with additional
9919 : * parameters specified as key=value with a semi-colon separator.
9920 : *
9921 : * The amount and types of optional parameters passed after the MIME type is
9922 : * format dependent, and driver dependent (some drivers might not be able to
9923 : * return those extra information without doing a rather costly processing).
9924 : *
9925 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9926 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9927 : * consequently "JPEG" can be passed as the pszFormat argument of
9928 : * ReadCompressedData(). For JPEG, implementations can use the
9929 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9930 : * above from a JPEG codestream.
9931 : *
9932 : * Several values might be returned. For example,
9933 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9934 : * if the JPEGXL codestream includes a JPEG reconstruction box.
9935 : *
9936 : * In the general case this method will return an empty list.
9937 : *
9938 : * This is the same as C++ method GDALDataset::GetCompressionFormats().
9939 : *
9940 : * @param hDS Dataset handle.
9941 : *
9942 : * @param nXOff The pixel offset to the top left corner of the region
9943 : * of the band to be accessed. This would be zero to start from the left side.
9944 : *
9945 : * @param nYOff The line offset to the top left corner of the region
9946 : * of the band to be accessed. This would be zero to start from the top.
9947 : *
9948 : * @param nXSize The width of the region of the band to be accessed in pixels.
9949 : *
9950 : * @param nYSize The height of the region of the band to be accessed in lines.
9951 : *
9952 : * @param nBandCount the number of bands being requested.
9953 : *
9954 : * @param panBandList the list of nBandCount band numbers.
9955 : * Note band numbers are 1 based. This may be NULL to select the first
9956 : * nBandCount bands.
9957 : *
9958 : * @return a list of compatible formats (which may be empty) that should be
9959 : * freed with CSLDestroy(), or nullptr.
9960 : *
9961 : * @since GDAL 3.7
9962 : */
9963 9 : char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,
9964 : int nXSize, int nYSize, int nBandCount,
9965 : const int *panBandList)
9966 : {
9967 9 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9968 9 : return GDALDataset::FromHandle(hDS)
9969 9 : ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,
9970 9 : panBandList)
9971 9 : .StealList();
9972 : }
9973 :
9974 : /************************************************************************/
9975 : /* ReadCompressedData() */
9976 : /************************************************************************/
9977 :
9978 : /** Return the compressed content that can be natively obtained for the
9979 : * window of interest and requested bands.
9980 : *
9981 : * For example, a tiled dataset may be able to return data in compressed format
9982 : * if the window of interest matches exactly a tile. For some formats, drivers
9983 : * may also be example to merge several tiles together (not currently
9984 : * implemented though).
9985 : *
9986 : * The implementation should make sure that the content returned forms a valid
9987 : * standalone file. For example, for the GeoTIFF implementation of this method,
9988 : * when extracting a JPEG tile, the method will automatically add the content
9989 : * of the JPEG Huffman and/or quantization tables that might be stored in the
9990 : * TIFF JpegTables tag, and not in tile data itself.
9991 : *
9992 : * In the general case this method will return CE_Failure.
9993 : *
9994 : * This is the same as C function GDALDatasetReadCompressedData().
9995 : *
9996 : * @param pszFormat Requested compression format (e.g. "JPEG",
9997 : * "WEBP", "JXL"). This is the MIME type of one of the values
9998 : * returned by GetCompressionFormats(). The format string is designed to
9999 : * potentially include at a later point key=value optional parameters separated
10000 : * by a semi-colon character. At time of writing, none are implemented.
10001 : * ReadCompressedData() implementations should verify optional parameters and
10002 : * return CE_Failure if they cannot support one of them.
10003 : *
10004 : * @param nXOff The pixel offset to the top left corner of the region
10005 : * of the band to be accessed. This would be zero to start from the left side.
10006 : *
10007 : * @param nYOff The line offset to the top left corner of the region
10008 : * of the band to be accessed. This would be zero to start from the top.
10009 : *
10010 : * @param nXSize The width of the region of the band to be accessed in pixels.
10011 : *
10012 : * @param nYSize The height of the region of the band to be accessed in lines.
10013 : *
10014 : * @param nBandCount the number of bands being requested.
10015 : *
10016 : * @param panBandList the list of nBandCount band numbers.
10017 : * Note band numbers are 1 based. This may be NULL to select the first
10018 : * nBandCount bands.
10019 : *
10020 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10021 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10022 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10023 : * buffer will be filled with the compressed data, provided that pnBufferSize
10024 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10025 : * of *ppBuffer, is sufficiently large to hold the data.
10026 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10027 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10028 : * free it with VSIFree().
10029 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10030 : * but *pnBufferSize will be updated with an upper bound of the size that would
10031 : * be necessary to hold it (if pnBufferSize != nullptr).
10032 : *
10033 : * @param pnBufferSize Output buffer size, or nullptr.
10034 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10035 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10036 : * method is successful, *pnBufferSize will be updated with the actual size
10037 : * used.
10038 : *
10039 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10040 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10041 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10042 : * *ppszDetailedFormat might contain strings like
10043 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10044 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10045 : * The string will contain at least as much information as what
10046 : * GetCompressionFormats() returns, and potentially more when
10047 : * ppBuffer != nullptr.
10048 : *
10049 : * @return CE_None in case of success, CE_Failure otherwise.
10050 : *
10051 : * For example, to request JPEG content on the whole image and let GDAL deal
10052 : * with the buffer allocation.
10053 : * \code{.cpp}
10054 : * void* pBuffer = nullptr;
10055 : * size_t nBufferSize = 0;
10056 : * CPLErr eErr =
10057 : * poDataset->ReadCompressedData("JPEG",
10058 : * 0, 0,
10059 : * poDataset->GetRasterXSize(),
10060 : * poDataset->GetRasterYSize(),
10061 : * poDataset->GetRasterCount(),
10062 : * nullptr, // panBandList
10063 : * &pBuffer,
10064 : * &nBufferSize,
10065 : * nullptr // ppszDetailedFormat
10066 : * );
10067 : * if (eErr == CE_None)
10068 : * {
10069 : * CPLAssert(pBuffer != nullptr);
10070 : * CPLAssert(nBufferSize > 0);
10071 : * VSILFILE* fp = VSIFOpenL("my.jpeg", "wb");
10072 : * if (fp)
10073 : * {
10074 : * VSIFWriteL(pBuffer, nBufferSize, 1, fp);
10075 : * VSIFCloseL(fp);
10076 : * }
10077 : * VSIFree(pBuffer);
10078 : * }
10079 : * \endcode
10080 : *
10081 : * Or to manage the buffer allocation on your side:
10082 : * \code{.cpp}
10083 : * size_t nUpperBoundBufferSize = 0;
10084 : * CPLErr eErr =
10085 : * poDataset->ReadCompressedData("JPEG",
10086 : * 0, 0,
10087 : * poDataset->GetRasterXSize(),
10088 : * poDataset->GetRasterYSize(),
10089 : * poDataset->GetRasterCount(),
10090 : * nullptr, // panBandList
10091 : * nullptr, // ppBuffer,
10092 : * &nUpperBoundBufferSize,
10093 : * nullptr // ppszDetailedFormat
10094 : * );
10095 : * if (eErr == CE_None)
10096 : * {
10097 : * std::vector<uint8_t> myBuffer;
10098 : * myBuffer.resize(nUpperBoundBufferSize);
10099 : * void* pBuffer = myBuffer.data();
10100 : * size_t nActualSize = nUpperBoundBufferSize;
10101 : * char* pszDetailedFormat = nullptr;
10102 : * // We also request detailed format, but we could have passed it to
10103 : * // nullptr as well.
10104 : * eErr =
10105 : * poDataset->ReadCompressedData("JPEG",
10106 : * 0, 0,
10107 : * poDataset->GetRasterXSize(),
10108 : * poDataset->GetRasterYSize(),
10109 : * poDataset->GetRasterCount(),
10110 : * nullptr, // panBandList
10111 : * &pBuffer,
10112 : * &nActualSize,
10113 : * &pszDetailedFormat);
10114 : * if (eErr == CE_None)
10115 : * {
10116 : * CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified
10117 : * CPLAssert(nActualSize <= nUpperBoundBufferSize);
10118 : * myBuffer.resize(nActualSize);
10119 : * // do something useful
10120 : * VSIFree(pszDetailedFormat);
10121 : * }
10122 : * }
10123 : * \endcode
10124 : *
10125 : * @since GDAL 3.7
10126 : */
10127 462 : CPLErr GDALDataset::ReadCompressedData(
10128 : CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,
10129 : CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10130 : CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,
10131 : CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,
10132 : CPL_UNUSED char **ppszDetailedFormat)
10133 : {
10134 462 : return CE_Failure;
10135 : }
10136 :
10137 : /************************************************************************/
10138 : /* GDALDatasetReadCompressedData() */
10139 : /************************************************************************/
10140 :
10141 : /** Return the compressed content that can be natively obtained for the
10142 : * window of interest and requested bands.
10143 : *
10144 : * For example, a tiled dataset may be able to return data in compressed format
10145 : * if the window of interest matches exactly a tile. For some formats, drivers
10146 : * may also be example to merge several tiles together (not currently
10147 : * implemented though).
10148 : *
10149 : * The implementation should make sure that the content returned forms a valid
10150 : * standalone file. For example, for the GeoTIFF implementation of this method,
10151 : * when extracting a JPEG tile, the method will automatically adds the content
10152 : * of the JPEG Huffman and/or quantization tables that might be stored in the
10153 : * TIFF JpegTables tag, and not in tile data itself.
10154 : *
10155 : * In the general case this method will return CE_Failure.
10156 : *
10157 : * This is the same as C++ method GDALDataset:ReadCompressedData().
10158 : *
10159 : * @param hDS Dataset handle.
10160 : *
10161 : * @param pszFormat Requested compression format (e.g. "JPEG",
10162 : * "WEBP", "JXL"). This is the MIME type of one of the values
10163 : * returned by GetCompressionFormats(). The format string is designed to
10164 : * potentially include at a later point key=value optional parameters separated
10165 : * by a semi-colon character. At time of writing, none are implemented.
10166 : * ReadCompressedData() implementations should verify optional parameters and
10167 : * return CE_Failure if they cannot support one of them.
10168 : *
10169 : * @param nXOff The pixel offset to the top left corner of the region
10170 : * of the band to be accessed. This would be zero to start from the left side.
10171 : *
10172 : * @param nYOff The line offset to the top left corner of the region
10173 : * of the band to be accessed. This would be zero to start from the top.
10174 : *
10175 : * @param nXSize The width of the region of the band to be accessed in pixels.
10176 : *
10177 : * @param nYSize The height of the region of the band to be accessed in lines.
10178 : *
10179 : * @param nBandCount the number of bands being requested.
10180 : *
10181 : * @param panBandList the list of nBandCount band numbers.
10182 : * Note band numbers are 1 based. This may be NULL to select the first
10183 : * nBandCount bands.
10184 : *
10185 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10186 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10187 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10188 : * buffer will be filled with the compressed data, provided that pnBufferSize
10189 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10190 : * of *ppBuffer, is sufficiently large to hold the data.
10191 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10192 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10193 : * free it with VSIFree().
10194 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10195 : * but *pnBufferSize will be updated with an upper bound of the size that would
10196 : * be necessary to hold it (if pnBufferSize != nullptr).
10197 : *
10198 : * @param pnBufferSize Output buffer size, or nullptr.
10199 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10200 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10201 : * method is successful, *pnBufferSize will be updated with the actual size
10202 : * used.
10203 : *
10204 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10205 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10206 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10207 : * *ppszDetailedFormat might contain strings like
10208 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10209 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10210 : * The string will contain at least as much information as what
10211 : * GetCompressionFormats() returns, and potentially more when
10212 : * ppBuffer != nullptr.
10213 : *
10214 : * @return CE_None in case of success, CE_Failure otherwise.
10215 : *
10216 : * @since GDAL 3.7
10217 : */
10218 28 : CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,
10219 : int nXOff, int nYOff, int nXSize,
10220 : int nYSize, int nBandCount,
10221 : const int *panBandList, void **ppBuffer,
10222 : size_t *pnBufferSize,
10223 : char **ppszDetailedFormat)
10224 : {
10225 28 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10226 56 : return GDALDataset::FromHandle(hDS)->ReadCompressedData(
10227 : pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,
10228 28 : ppBuffer, pnBufferSize, ppszDetailedFormat);
10229 : }
10230 :
10231 : /************************************************************************/
10232 : /* CanBeCloned() */
10233 : /************************************************************************/
10234 :
10235 : //! @cond Doxygen_Suppress
10236 :
10237 : /** This method is called by GDALThreadSafeDataset::Create() to determine if
10238 : * it is possible to create a thread-safe wrapper for a dataset, which involves
10239 : * the ability to Clone() it.
10240 : *
10241 : * Implementations of this method must be thread-safe.
10242 : *
10243 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10244 : * expressing the intended use for thread-safety.
10245 : * Currently, the only valid scope is in the base
10246 : * implementation is GDAL_OF_RASTER.
10247 : * @param bCanShareState Determines if cloned datasets are allowed to share
10248 : * state with the dataset they have been cloned from.
10249 : * If set to true, the dataset from which they have been
10250 : * cloned from must remain opened during the lifetime of
10251 : * its clones.
10252 : * @return true if the Clone() method is expected to succeed with the same values
10253 : * of nScopeFlags and bCanShareState.
10254 : */
10255 197 : bool GDALDataset::CanBeCloned(int nScopeFlags,
10256 : [[maybe_unused]] bool bCanShareState) const
10257 : {
10258 197 : return m_bCanBeReopened && nScopeFlags == GDAL_OF_RASTER;
10259 : }
10260 :
10261 : //! @endcond
10262 :
10263 : /************************************************************************/
10264 : /* Clone() */
10265 : /************************************************************************/
10266 :
10267 : //! @cond Doxygen_Suppress
10268 :
10269 : /** This method "clones" the current dataset, that is it returns a new instance
10270 : * that is opened on the same underlying "file".
10271 : *
10272 : * The base implementation uses GDALDataset::Open() to re-open the dataset.
10273 : * The MEM driver has a specialized implementation that returns a new instance,
10274 : * but which shares the same memory buffer as this.
10275 : *
10276 : * Implementations of this method must be thread-safe.
10277 : *
10278 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10279 : * expressing the intended use for thread-safety.
10280 : * Currently, the only valid scope is in the base
10281 : * implementation is GDAL_OF_RASTER.
10282 : * @param bCanShareState Determines if cloned datasets are allowed to share
10283 : * state with the dataset they have been cloned from.
10284 : * If set to true, the dataset from which they have been
10285 : * cloned from must remain opened during the lifetime of
10286 : * its clones.
10287 : * @return a new instance, or nullptr in case of error.
10288 : */
10289 : std::unique_ptr<GDALDataset>
10290 2095 : GDALDataset::Clone(int nScopeFlags, [[maybe_unused]] bool bCanShareState) const
10291 : {
10292 4189 : CPLStringList aosAllowedDrivers;
10293 2095 : if (poDriver)
10294 2095 : aosAllowedDrivers.AddString(poDriver->GetDescription());
10295 : return std::unique_ptr<GDALDataset>(GDALDataset::Open(
10296 2095 : GetDescription(),
10297 2095 : nScopeFlags | GDAL_OF_INTERNAL | GDAL_OF_VERBOSE_ERROR,
10298 4190 : aosAllowedDrivers.List(), papszOpenOptions));
10299 : }
10300 :
10301 : //! @endcond
10302 :
10303 : /************************************************************************/
10304 : /* GeolocationToPixelLine() */
10305 : /************************************************************************/
10306 :
10307 : /** Transform georeferenced coordinates to pixel/line coordinates.
10308 : *
10309 : * When poSRS is null, those georeferenced coordinates (dfGeolocX, dfGeolocY)
10310 : * must be in the "natural" SRS of the dataset, that is the one returned by
10311 : * GetSpatialRef() if there is a geotransform, GetGCPSpatialRef() if there are
10312 : * GCPs, WGS 84 if there are RPC coefficients, or the SRS of the geolocation
10313 : * array (generally WGS 84) if there is a geolocation array.
10314 : * If that natural SRS is a geographic one, dfGeolocX must be a longitude, and
10315 : * dfGeolocY a latitude. If that natural SRS is a projected one, dfGeolocX must
10316 : * be a easting, and dfGeolocY a northing.
10317 : *
10318 : * When poSRS is set to a non-null value, (dfGeolocX, dfGeolocY) must be
10319 : * expressed in that CRS, and that tuple must be conformant with the
10320 : * data-axis-to-crs-axis setting of poSRS, that is the one returned by
10321 : * the OGRSpatialReference::GetDataAxisToSRSAxisMapping(). If you want to be sure
10322 : * of the axis order, then make sure to call poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER)
10323 : * before calling this method, and in that case, dfGeolocX must be a longitude
10324 : * or an easting value, and dfGeolocX a latitude or a northing value.
10325 : *
10326 : * This method uses GDALCreateGenImgProjTransformer2() underneath.
10327 : *
10328 : * @param dfGeolocX X coordinate of the position (longitude or easting if poSRS
10329 : * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10330 : * where interpolation should be done.
10331 : * @param dfGeolocY Y coordinate of the position (latitude or northing if poSRS
10332 : * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10333 : * where interpolation should be done.
10334 : * @param poSRS If set, override the natural CRS in which dfGeolocX, dfGeolocY are expressed
10335 : * @param[out] pdfPixel Pointer to the variable where to the store the pixel/column coordinate.
10336 : * @param[out] pdfLine Pointer to the variable where to the store the line coordinate.
10337 : * @param papszTransformerOptions Options accepted by GDALCreateGenImgProjTransformer2(), or nullptr.
10338 : *
10339 : * @return CE_None on success, or an error code on failure.
10340 : * @since GDAL 3.11
10341 : */
10342 :
10343 : CPLErr
10344 15 : GDALDataset::GeolocationToPixelLine(double dfGeolocX, double dfGeolocY,
10345 : const OGRSpatialReference *poSRS,
10346 : double *pdfPixel, double *pdfLine,
10347 : CSLConstList papszTransformerOptions) const
10348 : {
10349 30 : CPLStringList aosTO(papszTransformerOptions);
10350 :
10351 15 : if (poSRS)
10352 : {
10353 4 : const char *const apszOptions[] = {"FORMAT=WKT2", nullptr};
10354 8 : const std::string osWKT = poSRS->exportToWkt(apszOptions);
10355 4 : aosTO.SetNameValue("DST_SRS", osWKT.c_str());
10356 4 : const auto eAxisMappingStrategy = poSRS->GetAxisMappingStrategy();
10357 4 : if (eAxisMappingStrategy == OAMS_TRADITIONAL_GIS_ORDER)
10358 : aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10359 1 : "TRADITIONAL_GIS_ORDER");
10360 3 : else if (eAxisMappingStrategy == OAMS_AUTHORITY_COMPLIANT)
10361 : aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10362 1 : "AUTHORITY_COMPLIANT");
10363 : else
10364 : {
10365 2 : const auto &anValues = poSRS->GetDataAxisToSRSAxisMapping();
10366 4 : std::string osVal;
10367 6 : for (int v : anValues)
10368 : {
10369 4 : if (!osVal.empty())
10370 2 : osVal += ',';
10371 4 : osVal += std::to_string(v);
10372 : }
10373 : aosTO.SetNameValue("DST_SRS_DATA_AXIS_TO_SRS_AXIS_MAPPING",
10374 2 : osVal.c_str());
10375 : }
10376 : }
10377 :
10378 15 : auto hTransformer = GDALCreateGenImgProjTransformer2(
10379 : GDALDataset::ToHandle(const_cast<GDALDataset *>(this)), nullptr,
10380 15 : aosTO.List());
10381 15 : if (hTransformer == nullptr)
10382 : {
10383 1 : return CE_Failure;
10384 : }
10385 :
10386 14 : double z = 0;
10387 14 : int bSuccess = 0;
10388 14 : GDALGenImgProjTransform(hTransformer, TRUE, 1, &dfGeolocX, &dfGeolocY, &z,
10389 : &bSuccess);
10390 14 : GDALDestroyTransformer(hTransformer);
10391 14 : if (bSuccess)
10392 : {
10393 14 : if (pdfPixel)
10394 14 : *pdfPixel = dfGeolocX;
10395 14 : if (pdfLine)
10396 14 : *pdfLine = dfGeolocY;
10397 14 : return CE_None;
10398 : }
10399 : else
10400 : {
10401 0 : return CE_Failure;
10402 : }
10403 : }
10404 :
10405 : /************************************************************************/
10406 : /* GDALDatasetGeolocationToPixelLine() */
10407 : /************************************************************************/
10408 :
10409 : /** Transform georeferenced coordinates to pixel/line coordinates.
10410 : *
10411 : * @see GDALDataset::GeolocationToPixelLine()
10412 : * @since GDAL 3.11
10413 : */
10414 :
10415 0 : CPLErr GDALDatasetGeolocationToPixelLine(GDALDatasetH hDS, double dfGeolocX,
10416 : double dfGeolocY,
10417 : OGRSpatialReferenceH hSRS,
10418 : double *pdfPixel, double *pdfLine,
10419 : CSLConstList papszTransformerOptions)
10420 : {
10421 0 : VALIDATE_POINTER1(hDS, "GDALDatasetGeolocationToPixelLine", CE_Failure);
10422 :
10423 0 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
10424 0 : return poDS->GeolocationToPixelLine(
10425 0 : dfGeolocX, dfGeolocY, OGRSpatialReference::FromHandle(hSRS), pdfPixel,
10426 0 : pdfLine, papszTransformerOptions);
10427 : }
10428 :
10429 : /************************************************************************/
10430 : /* ReportUpdateNotSupportedByDriver() */
10431 : /************************************************************************/
10432 :
10433 : //! @cond Doxygen_Suppress
10434 :
10435 : /* static */
10436 1 : void GDALDataset::ReportUpdateNotSupportedByDriver(const char *pszDriverName)
10437 : {
10438 1 : CPLError(CE_Failure, CPLE_NotSupported,
10439 : "The %s driver does not support update access to existing "
10440 : "datasets.",
10441 : pszDriverName);
10442 1 : }
10443 :
10444 : //! @endcond
10445 :
10446 : /************************************************************************/
10447 : /* BuildFilename() */
10448 : /************************************************************************/
10449 :
10450 : /** Generates a filename, potentially relative to another one.
10451 : *
10452 : * Given the path to a reference directory, and a path to a file
10453 : * referenced from it, build a path to the file that the current application
10454 : * can use. If the file path is already absolute, rather than relative, or if
10455 : * bRelativeToReferencePath is false, then the filename of interest will be
10456 : * returned unaltered.
10457 : *
10458 : * This is enhanced version of CPLProjectRelativeFilenameSafe() that takes
10459 : * into account the subdataset syntax.
10460 : *
10461 : * Examples:
10462 : * \code{.cpp}
10463 : * BuildFilename("tmp/abc.gif", "abc/def", true) == "abc/def/tmp/abc.gif"
10464 : * BuildFilename("../abc.gif", "/abc/def") == "/abc/abc.gif"
10465 : * BuildFilename("abc.gif", "C:\WIN", true) == "C:\WIN\abc.gif"
10466 : * BuildFilename("abc.gif", "C:\WIN", false) == "abc.gif"
10467 : * BuildFilename("/home/even/foo.tif", "/home/even/workdir", true) == "/home/even/foo.tif"
10468 : * \endcode
10469 : *
10470 : * @param pszFilename Filename of interest.
10471 : * @param pszReferencePath Path to a reference directory.
10472 : * @param bRelativeToReferencePath Whether pszFilename, if a relative path, is
10473 : * relative to pszReferencePath
10474 : * @since 3.11
10475 : */
10476 :
10477 : /* static */
10478 5394 : std::string GDALDataset::BuildFilename(const char *pszFilename,
10479 : const char *pszReferencePath,
10480 : bool bRelativeToReferencePath)
10481 : {
10482 5394 : std::string osSrcDSName;
10483 5394 : if (pszReferencePath != nullptr && bRelativeToReferencePath)
10484 : {
10485 : // Try subdatasetinfo API first
10486 : // Note: this will become the only branch when subdatasetinfo will become
10487 : // available for NITF_IM, RASTERLITE and TILEDB
10488 2592 : const auto oSubDSInfo{GDALGetSubdatasetInfo(pszFilename)};
10489 2592 : if (oSubDSInfo && !oSubDSInfo->GetPathComponent().empty())
10490 : {
10491 8 : auto path{oSubDSInfo->GetPathComponent()};
10492 12 : osSrcDSName = oSubDSInfo->ModifyPathComponent(
10493 8 : CPLProjectRelativeFilenameSafe(pszReferencePath, path.c_str())
10494 4 : .c_str());
10495 4 : GDALDestroySubdatasetInfo(oSubDSInfo);
10496 : }
10497 : else
10498 : {
10499 2588 : bool bDone = false;
10500 15518 : for (const char *pszSyntax : apszSpecialSubDatasetSyntax)
10501 : {
10502 12932 : CPLString osPrefix(pszSyntax);
10503 12932 : osPrefix.resize(strchr(pszSyntax, ':') - pszSyntax + 1);
10504 12932 : if (pszSyntax[osPrefix.size()] == '"')
10505 2586 : osPrefix += '"';
10506 12932 : if (EQUALN(pszFilename, osPrefix, osPrefix.size()))
10507 : {
10508 2 : if (STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}"))
10509 : {
10510 2 : const char *pszLastPart = strrchr(pszFilename, ':') + 1;
10511 : // CSV:z:/foo.xyz
10512 2 : if ((pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
10513 0 : pszLastPart - pszFilename >= 3 &&
10514 0 : pszLastPart[-3] == ':')
10515 : {
10516 0 : pszLastPart -= 2;
10517 : }
10518 2 : CPLString osPrefixFilename = pszFilename;
10519 2 : osPrefixFilename.resize(pszLastPart - pszFilename);
10520 4 : osSrcDSName = osPrefixFilename +
10521 4 : CPLProjectRelativeFilenameSafe(
10522 2 : pszReferencePath, pszLastPart);
10523 2 : bDone = true;
10524 : }
10525 0 : else if (STARTS_WITH_CI(pszSyntax + osPrefix.size(),
10526 : "{FILENAME}"))
10527 : {
10528 0 : CPLString osFilename(pszFilename + osPrefix.size());
10529 0 : size_t nPos = 0;
10530 0 : if (osFilename.size() >= 3 && osFilename[1] == ':' &&
10531 0 : (osFilename[2] == '\\' || osFilename[2] == '/'))
10532 0 : nPos = 2;
10533 0 : nPos = osFilename.find(
10534 0 : pszSyntax[osPrefix.size() + strlen("{FILENAME}")],
10535 : nPos);
10536 0 : if (nPos != std::string::npos)
10537 : {
10538 0 : const CPLString osSuffix = osFilename.substr(nPos);
10539 0 : osFilename.resize(nPos);
10540 0 : osSrcDSName = osPrefix +
10541 0 : CPLProjectRelativeFilenameSafe(
10542 0 : pszReferencePath, osFilename) +
10543 0 : osSuffix;
10544 0 : bDone = true;
10545 : }
10546 : }
10547 2 : break;
10548 : }
10549 : }
10550 2588 : if (!bDone)
10551 : {
10552 2586 : std::string osReferencePath = pszReferencePath;
10553 2586 : if (!CPLIsFilenameRelative(pszReferencePath))
10554 : {
10555 : // Simplify path by replacing "foo/a/../b" with "foo/b"
10556 2274 : while (STARTS_WITH(pszFilename, "../"))
10557 : {
10558 : osReferencePath =
10559 5 : CPLGetPathSafe(osReferencePath.c_str());
10560 5 : pszFilename += strlen("../");
10561 : }
10562 : }
10563 :
10564 5172 : osSrcDSName = CPLProjectRelativeFilenameSafe(
10565 2586 : osReferencePath.c_str(), pszFilename);
10566 : }
10567 2592 : }
10568 : }
10569 : else
10570 : {
10571 2802 : osSrcDSName = pszFilename;
10572 : }
10573 5394 : return osSrcDSName;
10574 : }
|