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 <array>
19 : #include <climits>
20 : #include <cstdarg>
21 : #include <cstdio>
22 : #include <cstdlib>
23 : #include <cstring>
24 : #include <algorithm>
25 : #include <map>
26 : #include <mutex>
27 : #include <new>
28 : #include <set>
29 : #include <string>
30 : #include <utility>
31 :
32 : #include "cpl_conv.h"
33 : #include "cpl_error.h"
34 : #include "cpl_hash_set.h"
35 : #include "cpl_multiproc.h"
36 : #include "cpl_progress.h"
37 : #include "cpl_string.h"
38 : #include "cpl_vsi.h"
39 : #include "cpl_vsi_error.h"
40 : #include "gdal_alg.h"
41 : #include "ogr_api.h"
42 : #include "ogr_attrind.h"
43 : #include "ogr_core.h"
44 : #include "ogr_feature.h"
45 : #include "ogr_featurestyle.h"
46 : #include "ogr_gensql.h"
47 : #include "ogr_geometry.h"
48 : #include "ogr_p.h"
49 : #include "ogr_spatialref.h"
50 : #include "ogr_srs_api.h"
51 : #include "ograpispy.h"
52 : #include "ogrsf_frmts.h"
53 : #include "ogrunionlayer.h"
54 : #include "ogr_swq.h"
55 :
56 : #include "../frmts/derived/derivedlist.h"
57 :
58 : #ifdef SQLITE_ENABLED
59 : #include "../sqlite/ogrsqliteexecutesql.h"
60 : #endif
61 :
62 : extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
63 :
64 : CPL_C_START
65 : GDALAsyncReader *GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff,
66 : int nYOff, int nXSize, int nYSize,
67 : void *pBuf, int nBufXSize,
68 : int nBufYSize, GDALDataType eBufType,
69 : int nBandCount, int *panBandMap,
70 : int nPixelSpace, int nLineSpace,
71 : int nBandSpace, char **papszOptions);
72 : CPL_C_END
73 :
74 : enum class GDALAllowReadWriteMutexState
75 : {
76 : RW_MUTEX_STATE_UNKNOWN,
77 : RW_MUTEX_STATE_ALLOWED,
78 : RW_MUTEX_STATE_DISABLED
79 : };
80 :
81 : const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
82 : const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
83 :
84 : class GDALDataset::Private
85 : {
86 : CPL_DISALLOW_COPY_ASSIGN(Private)
87 :
88 : public:
89 : CPLMutex *hMutex = nullptr;
90 : std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
91 : #ifdef DEBUG_EXTRA
92 : std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
93 : #endif
94 : GDALAllowReadWriteMutexState eStateReadWriteMutex =
95 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
96 : int nCurrentLayerIdx = 0;
97 : int nLayerCount = -1;
98 : GIntBig nFeatureReadInLayer = 0;
99 : GIntBig nFeatureReadInDataset = 0;
100 : GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
101 : GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
102 : OGRLayer *poCurrentLayer = nullptr;
103 :
104 : std::mutex m_oMutexWKT{};
105 :
106 : char *m_pszWKTCached = nullptr;
107 : OGRSpatialReference *m_poSRSCached = nullptr;
108 : char *m_pszWKTGCPCached = nullptr;
109 : OGRSpatialReference *m_poSRSGCPCached = nullptr;
110 :
111 : GDALDataset *poParentDataset = nullptr;
112 :
113 : bool m_bOverviewsEnabled = true;
114 :
115 : std::vector<int>
116 : m_anBandMap{}; // used by RasterIO(). Values are 1, 2, etc.
117 :
118 150072 : Private() = default;
119 : };
120 :
121 : struct SharedDatasetCtxt
122 : {
123 : // PID of the thread that mark the dataset as shared
124 : // This may not be the actual PID, but the responsiblePID.
125 : GIntBig nPID;
126 : char *pszDescription;
127 : char *pszConcatenatedOpenOptions;
128 : int nOpenFlags;
129 :
130 : GDALDataset *poDS;
131 : };
132 :
133 : // Set of datasets opened as shared datasets (with GDALOpenShared)
134 : // The values in the set are of type SharedDatasetCtxt.
135 : static CPLHashSet *phSharedDatasetSet = nullptr;
136 :
137 : // Set of all datasets created in the constructor of GDALDataset.
138 : // In the case of a shared dataset, memorize the PID of the thread
139 : // that marked the dataset as shared, so that we can remove it from
140 : // the phSharedDatasetSet in the destructor of the dataset, even
141 : // if GDALClose is called from a different thread.
142 : static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
143 :
144 : static CPLMutex *hDLMutex = nullptr;
145 :
146 : // Static array of all datasets. Used by GDALGetOpenDatasets.
147 : // Not thread-safe. See GDALGetOpenDatasets.
148 : static GDALDataset **ppDatasets = nullptr;
149 :
150 8436 : static unsigned long GDALSharedDatasetHashFunc(const void *elt)
151 : {
152 8436 : const SharedDatasetCtxt *psStruct =
153 : static_cast<const SharedDatasetCtxt *>(elt);
154 : return static_cast<unsigned long>(
155 8436 : CPLHashSetHashStr(psStruct->pszDescription) ^
156 8436 : CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^
157 8436 : psStruct->nOpenFlags ^ psStruct->nPID);
158 : }
159 :
160 6940 : static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)
161 : {
162 6940 : const SharedDatasetCtxt *psStruct1 =
163 : static_cast<const SharedDatasetCtxt *>(elt1);
164 6940 : const SharedDatasetCtxt *psStruct2 =
165 : static_cast<const SharedDatasetCtxt *>(elt2);
166 13833 : return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
167 6893 : strcmp(psStruct1->pszConcatenatedOpenOptions,
168 6893 : psStruct2->pszConcatenatedOpenOptions) == 0 &&
169 20724 : psStruct1->nPID == psStruct2->nPID &&
170 13831 : psStruct1->nOpenFlags == psStruct2->nOpenFlags;
171 : }
172 :
173 393 : static void GDALSharedDatasetFreeFunc(void *elt)
174 : {
175 393 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
176 393 : CPLFree(psStruct->pszDescription);
177 393 : CPLFree(psStruct->pszConcatenatedOpenOptions);
178 393 : CPLFree(psStruct);
179 393 : }
180 :
181 : static std::string
182 7081 : GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)
183 : {
184 7081 : std::string osStr;
185 7094 : for (const char *pszOption : cpl::Iterate(papszOpenOptions))
186 13 : osStr += pszOption;
187 7081 : return osStr;
188 : }
189 :
190 : /************************************************************************/
191 : /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
192 : /************************************************************************/
193 :
194 : // The open-shared mutex must be used by the ProxyPool too.
195 482055 : CPLMutex **GDALGetphDLMutex()
196 : {
197 482055 : return &hDLMutex;
198 : }
199 :
200 : // The current thread will act in the behalf of the thread of PID
201 : // responsiblePID.
202 471730 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
203 : {
204 : GIntBig *pResponsiblePID =
205 471730 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
206 471729 : if (pResponsiblePID == nullptr)
207 : {
208 221 : pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
209 221 : CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
210 : }
211 471728 : *pResponsiblePID = responsiblePID;
212 471728 : }
213 :
214 : // Get the PID of the thread that the current thread will act in the behalf of
215 : // By default : the current thread acts in the behalf of itself.
216 597944 : GIntBig GDALGetResponsiblePIDForCurrentThread()
217 : {
218 : GIntBig *pResponsiblePID =
219 597944 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
220 597824 : if (pResponsiblePID == nullptr)
221 43490 : return CPLGetPID();
222 554334 : return *pResponsiblePID;
223 : }
224 :
225 : /************************************************************************/
226 : /* ==================================================================== */
227 : /* GDALDataset */
228 : /* ==================================================================== */
229 : /************************************************************************/
230 :
231 : /**
232 : * \class GDALDataset "gdal_priv.h"
233 : *
234 : * A dataset encapsulating one or more raster bands. Details are further
235 : * discussed in the <a href="https://gdal.org/user/raster_data_model.html">GDAL
236 : * Raster Data Model</a>.
237 : *
238 : * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
239 : * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
240 : * dataset.
241 : */
242 :
243 : /************************************************************************/
244 : /* GDALDataset() */
245 : /************************************************************************/
246 :
247 : //! @cond Doxygen_Suppress
248 130141 : GDALDataset::GDALDataset()
249 130141 : : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
250 : {
251 129914 : }
252 :
253 150112 : GDALDataset::GDALDataset(int bForceCachedIOIn)
254 149956 : : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
255 150112 : m_poPrivate(new(std::nothrow) GDALDataset::Private)
256 : {
257 149997 : }
258 :
259 : //! @endcond
260 :
261 : /************************************************************************/
262 : /* ~GDALDataset() */
263 : /************************************************************************/
264 :
265 : /**
266 : * \brief Destroy an open GDALDataset.
267 : *
268 : * This is the accepted method of closing a GDAL dataset and deallocating
269 : * all resources associated with it.
270 : *
271 : * Equivalent of the C callable GDALClose(). Except that GDALClose() first
272 : * decrements the reference count, and then closes only if it has dropped to
273 : * zero.
274 : *
275 : * For Windows users, it is not recommended to use the delete operator on the
276 : * dataset object because of known issues when allocating and freeing memory
277 : * across module boundaries. Calling GDALClose() is then a better option.
278 : */
279 :
280 149934 : GDALDataset::~GDALDataset()
281 :
282 : {
283 : // we don't want to report destruction of datasets that
284 : // were never really open or meant as internal
285 149819 : if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))
286 : {
287 70497 : if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
288 207 : CPLDebug("GDAL",
289 : "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
290 207 : GetDescription(), this, static_cast<int>(CPLGetPID()),
291 207 : static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
292 : else
293 70329 : CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
294 : }
295 :
296 149933 : GDALDataset::Close();
297 :
298 : /* -------------------------------------------------------------------- */
299 : /* Remove dataset from the "open" dataset list. */
300 : /* -------------------------------------------------------------------- */
301 149930 : if (!bIsInternal)
302 : {
303 143004 : CPLMutexHolderD(&hDLMutex);
304 71507 : if (poAllDatasetMap)
305 : {
306 : std::map<GDALDataset *, GIntBig>::iterator oIter =
307 71507 : poAllDatasetMap->find(this);
308 71507 : CPLAssert(oIter != poAllDatasetMap->end());
309 :
310 71507 : UnregisterFromSharedDataset();
311 :
312 71507 : poAllDatasetMap->erase(oIter);
313 :
314 71507 : if (poAllDatasetMap->empty())
315 : {
316 19816 : delete poAllDatasetMap;
317 19816 : poAllDatasetMap = nullptr;
318 19816 : if (phSharedDatasetSet)
319 : {
320 206 : CPLHashSetDestroy(phSharedDatasetSet);
321 : }
322 19816 : phSharedDatasetSet = nullptr;
323 19816 : CPLFree(ppDatasets);
324 19816 : ppDatasets = nullptr;
325 : }
326 : }
327 : }
328 :
329 : /* -------------------------------------------------------------------- */
330 : /* Destroy the raster bands if they exist. */
331 : /* -------------------------------------------------------------------- */
332 1680700 : for (int i = 0; i < nBands && papoBands != nullptr; ++i)
333 : {
334 1530750 : if (papoBands[i] != nullptr)
335 1530760 : delete papoBands[i];
336 1530760 : papoBands[i] = nullptr;
337 : }
338 :
339 149948 : CPLFree(papoBands);
340 :
341 149930 : if (m_poStyleTable)
342 : {
343 23 : delete m_poStyleTable;
344 23 : m_poStyleTable = nullptr;
345 : }
346 :
347 149930 : if (m_poPrivate != nullptr)
348 : {
349 149922 : if (m_poPrivate->hMutex != nullptr)
350 20293 : CPLDestroyMutex(m_poPrivate->hMutex);
351 :
352 : #if defined(__COVERITY__) || defined(DEBUG)
353 : // Not needed since at destruction there is no risk of concurrent use.
354 299853 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
355 : #endif
356 149934 : CPLFree(m_poPrivate->m_pszWKTCached);
357 149932 : if (m_poPrivate->m_poSRSCached)
358 : {
359 0 : m_poPrivate->m_poSRSCached->Release();
360 : }
361 149932 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
362 149931 : if (m_poPrivate->m_poSRSGCPCached)
363 : {
364 0 : m_poPrivate->m_poSRSGCPCached->Release();
365 : }
366 : }
367 :
368 149942 : delete m_poPrivate;
369 :
370 149940 : CSLDestroy(papszOpenOptions);
371 149933 : }
372 :
373 : /************************************************************************/
374 : /* Close() */
375 : /************************************************************************/
376 :
377 : /** Do final cleanup before a dataset is destroyed.
378 : *
379 : * This method is typically called by GDALClose() or the destructor of a
380 : * GDALDataset subclass. It might also be called by C++ users before
381 : * destroying a dataset. It should not be called on a shared dataset whose
382 : * reference count is greater than one.
383 : *
384 : * It gives a last chance to the closing process to return an error code if
385 : * something goes wrong, in particular in creation / update scenarios where
386 : * file write or network communication might occur when finalizing the dataset.
387 : *
388 : * Implementations should be robust to this method to be called several times
389 : * (on subsequent calls, it should do nothing and return CE_None).
390 : * Once it has been called, no other method than Close() or the dataset
391 : * destructor should be called. RasterBand or OGRLayer owned by the dataset
392 : * should be assumed as no longer being valid.
393 : *
394 : * If a driver implements this method, it must also call it from its
395 : * dataset destructor.
396 : *
397 : * This is the equivalent of C function GDALDatasetRunCloseWithoutDestroying().
398 : *
399 : * A typical implementation might look as the following
400 : * \code{.cpp}
401 : *
402 : * MyDataset::~MyDataset()
403 : * {
404 : * try
405 : * {
406 : * MyDataset::Close();
407 : * }
408 : * catch (const std::exception &exc)
409 : * {
410 : * // If Close() can throw exception
411 : * CPLError(CE_Failure, CPLE_AppDefined,
412 : * "Exception thrown in MyDataset::Close(): %s",
413 : * exc.what());
414 : * }
415 : * catch (...)
416 : * {
417 : * // If Close() can throw exception
418 : * CPLError(CE_Failure, CPLE_AppDefined,
419 : * "Exception thrown in MyDataset::Close()");
420 : * }
421 : * }
422 : *
423 : * CPLErr MyDataset::Close()
424 : * {
425 : * CPLErr eErr = CE_None;
426 : * if( nOpenFlags != OPEN_FLAGS_CLOSED )
427 : * {
428 : * if( MyDataset::FlushCache(true) != CE_None )
429 : * eErr = CE_Failure;
430 : *
431 : * // Do something driver specific
432 : * if (m_fpImage)
433 : * {
434 : * if( VSIFCloseL(m_fpImage) != 0 )
435 : * {
436 : * CPLError(CE_Failure, CPLE_FileIO, "VSIFCloseL() failed");
437 : * eErr = CE_Failure;
438 : * }
439 : * }
440 : *
441 : * // Call parent Close() implementation.
442 : * if( MyParentDatasetClass::Close() != CE_None )
443 : * eErr = CE_Failure;
444 : * }
445 : * return eErr;
446 : * }
447 : * \endcode
448 : *
449 : * @since GDAL 3.7
450 : */
451 256103 : CPLErr GDALDataset::Close()
452 : {
453 256103 : if (nOpenFlags != OPEN_FLAGS_CLOSED)
454 : {
455 : // Call UnregisterFromSharedDataset() before altering nOpenFlags
456 149960 : UnregisterFromSharedDataset();
457 :
458 149954 : nOpenFlags = OPEN_FLAGS_CLOSED;
459 : }
460 :
461 256097 : if (IsMarkedSuppressOnClose())
462 : {
463 3300 : if (poDriver == nullptr ||
464 : // Someone issuing Create("foo.tif") on a
465 : // memory driver doesn't expect files with those names to be deleted
466 : // on a file system...
467 : // This is somewhat messy. Ideally there should be a way for the
468 : // driver to overload the default behavior
469 1645 : (!EQUAL(poDriver->GetDescription(), "MEM") &&
470 1606 : !EQUAL(poDriver->GetDescription(), "Memory")))
471 : {
472 1616 : if (VSIUnlink(GetDescription()) == 0)
473 688 : UnMarkSuppressOnClose();
474 : }
475 : }
476 :
477 256095 : return CE_None;
478 : }
479 :
480 : /************************************************************************/
481 : /* GDALDatasetRunCloseWithoutDestroying() */
482 : /************************************************************************/
483 :
484 : /** Run the Close() method, without running destruction of the object.
485 : *
486 : * This ensures that content that should be written to file is written and
487 : * that all file descriptors are closed.
488 : *
489 : * Note that this is different from GDALClose() which also destroys
490 : * the underlying C++ object. GDALClose() or GDALReleaseDataset() are actually
491 : * the only functions that can be safely called on the dataset handle after
492 : * this function has been called.
493 : *
494 : * Most users want to use GDALClose() or GDALReleaseDataset() rather than
495 : * this function.
496 : *
497 : * This function is equivalent to the C++ method GDALDataset:Close()
498 : *
499 : * @param hDS dataset handle.
500 : * @return CE_None if no error
501 : *
502 : * @since GDAL 3.12
503 : * @see GDALClose()
504 : */
505 30 : CPLErr GDALDatasetRunCloseWithoutDestroying(GDALDatasetH hDS)
506 : {
507 30 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
508 30 : return GDALDataset::FromHandle(hDS)->Close();
509 : }
510 :
511 : /************************************************************************/
512 : /* UnregisterFromSharedDataset() */
513 : /************************************************************************/
514 :
515 221468 : void GDALDataset::UnregisterFromSharedDataset()
516 : {
517 221468 : if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))
518 221075 : return;
519 :
520 786 : CPLMutexHolderD(&hDLMutex);
521 :
522 : std::map<GDALDataset *, GIntBig>::iterator oIter =
523 393 : poAllDatasetMap->find(this);
524 393 : CPLAssert(oIter != poAllDatasetMap->end());
525 393 : const GIntBig nPIDCreatorForShared = oIter->second;
526 393 : bShared = false;
527 : SharedDatasetCtxt sStruct;
528 393 : sStruct.nPID = nPIDCreatorForShared;
529 393 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
530 393 : sStruct.pszDescription = const_cast<char *>(GetDescription());
531 : std::string osConcatenatedOpenOptions =
532 786 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
533 393 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
534 393 : sStruct.poDS = nullptr;
535 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
536 393 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
537 393 : if (psStruct && psStruct->poDS == this)
538 : {
539 392 : CPLHashSetRemove(phSharedDatasetSet, psStruct);
540 : }
541 : else
542 : {
543 1 : CPLDebug("GDAL",
544 : "Should not happen. Cannot find %s, "
545 : "this=%p in phSharedDatasetSet",
546 1 : GetDescription(), this);
547 : }
548 : }
549 :
550 : /************************************************************************/
551 : /* AddToDatasetOpenList() */
552 : /************************************************************************/
553 :
554 72973 : void GDALDataset::AddToDatasetOpenList()
555 : {
556 : /* -------------------------------------------------------------------- */
557 : /* Add this dataset to the open dataset list. */
558 : /* -------------------------------------------------------------------- */
559 72973 : bIsInternal = false;
560 :
561 72973 : CPLMutexHolderD(&hDLMutex);
562 :
563 72973 : if (poAllDatasetMap == nullptr)
564 19826 : poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
565 72973 : (*poAllDatasetMap)[this] = -1;
566 72973 : }
567 :
568 : /************************************************************************/
569 : /* FlushCache() */
570 : /************************************************************************/
571 :
572 : /**
573 : * \brief Flush all write cached data to disk.
574 : *
575 : * Any raster (or other GDAL) data written via GDAL calls, but buffered
576 : * internally will be written to disk.
577 : *
578 : * The default implementation of this method just calls the FlushCache() method
579 : * on each of the raster bands and the SyncToDisk() method
580 : * on each of the layers. Conceptually, calling FlushCache() on a dataset
581 : * should include any work that might be accomplished by calling SyncToDisk()
582 : * on layers in that dataset.
583 : *
584 : * Using this method does not prevent use from calling GDALClose()
585 : * to properly close a dataset and ensure that important data not addressed
586 : * by FlushCache() is written in the file.
587 : *
588 : * This method is the same as the C function GDALFlushCache().
589 : *
590 : * @param bAtClosing Whether this is called from a GDALDataset destructor
591 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
592 : */
593 :
594 117221 : CPLErr GDALDataset::FlushCache(bool bAtClosing)
595 :
596 : {
597 117221 : CPLErr eErr = CE_None;
598 : // This sometimes happens if a dataset is destroyed before completely
599 : // built.
600 :
601 117221 : if (papoBands)
602 : {
603 1998390 : for (int i = 0; i < nBands; ++i)
604 : {
605 1894060 : if (papoBands[i])
606 : {
607 1894060 : if (papoBands[i]->FlushCache(bAtClosing) != CE_None)
608 7 : eErr = CE_Failure;
609 : }
610 : }
611 : }
612 :
613 117221 : const int nLayers = GetLayerCount();
614 : // cppcheck-suppress knownConditionTrueFalse
615 117220 : if (nLayers > 0)
616 : {
617 15220 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
618 24557 : for (int i = 0; i < nLayers; ++i)
619 : {
620 16947 : OGRLayer *poLayer = GetLayer(i);
621 :
622 16947 : if (poLayer)
623 : {
624 16947 : if (poLayer->SyncToDisk() != OGRERR_NONE)
625 0 : eErr = CE_Failure;
626 : }
627 : }
628 : }
629 :
630 117220 : return eErr;
631 : }
632 :
633 : /************************************************************************/
634 : /* GDALFlushCache() */
635 : /************************************************************************/
636 :
637 : /**
638 : * \brief Flush all write cached data to disk.
639 : *
640 : * @see GDALDataset::FlushCache().
641 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
642 : */
643 :
644 4816 : CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)
645 :
646 : {
647 4816 : VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);
648 :
649 4816 : return GDALDataset::FromHandle(hDS)->FlushCache(false);
650 : }
651 :
652 : /************************************************************************/
653 : /* DropCache() */
654 : /************************************************************************/
655 :
656 : /**
657 : * \brief Drop all write cached data
658 : *
659 : * This method is the same as the C function GDALDropCache().
660 : *
661 : * @return CE_None in case of success
662 : * @since 3.9
663 : */
664 :
665 1 : CPLErr GDALDataset::DropCache()
666 :
667 : {
668 1 : CPLErr eErr = CE_None;
669 :
670 1 : if (papoBands)
671 : {
672 2 : for (int i = 0; i < nBands; ++i)
673 : {
674 1 : if (papoBands[i])
675 : {
676 1 : if (papoBands[i]->DropCache() != CE_None)
677 0 : eErr = CE_Failure;
678 : }
679 : }
680 : }
681 :
682 1 : return eErr;
683 : }
684 :
685 : /************************************************************************/
686 : /* GDALDropCache() */
687 : /************************************************************************/
688 :
689 : /**
690 : * \brief Drop all write cached data
691 : *
692 : * @see GDALDataset::DropCache().
693 : * @return CE_None in case of success
694 : * @since 3.9
695 : */
696 :
697 0 : CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS)
698 :
699 : {
700 0 : VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure);
701 :
702 0 : return GDALDataset::FromHandle(hDS)->DropCache();
703 : }
704 :
705 : /************************************************************************/
706 : /* GetEstimatedRAMUsage() */
707 : /************************************************************************/
708 :
709 : /**
710 : * \brief Return the intrinsic RAM usage of this dataset.
711 : *
712 : * The returned value should take into account caches in the underlying driver
713 : * and decoding library, but not the usage related to the GDAL block cache.
714 : *
715 : * At time of writing, this method is only implemented in the JP2OpenJPEG
716 : * driver. For single-tiled JPEG2000 images, the decoding of the image,
717 : * even partially, involves allocating at least
718 : * width * height * number_of_bands * sizeof(uint32_t) bytes inside the libopenjp2
719 : * library.
720 : *
721 : * This method is used by the GDALDatasetPool class, itself used by the GDAL VRT
722 : * driver, to determine how long a dataset in the pool must be kept open, given
723 : * the RAM usage of the dataset with respect to the usable total RAM.
724 : *
725 : * @since GDAL 3.7
726 : * @return RAM usage in bytes, or -1 if unknown (the default implementation
727 : * returns -1)
728 : */
729 :
730 3316 : GIntBig GDALDataset::GetEstimatedRAMUsage()
731 : {
732 3316 : return -1;
733 : }
734 :
735 : /************************************************************************/
736 : /* BlockBasedFlushCache() */
737 : /* */
738 : /* This helper method can be called by the */
739 : /* GDALDataset::FlushCache() for particular drivers to ensure */
740 : /* that buffers will be flushed in a manner suitable for pixel */
741 : /* interleaved (by block) IO. That is, if all the bands have */
742 : /* the same size blocks then a given block will be flushed for */
743 : /* all bands before proceeding to the next block. */
744 : /************************************************************************/
745 :
746 : //! @cond Doxygen_Suppress
747 350 : CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)
748 :
749 : {
750 350 : GDALRasterBand *poBand1 = GetRasterBand(1);
751 350 : if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))
752 : {
753 7 : return GDALDataset::FlushCache(bAtClosing);
754 : }
755 :
756 343 : int nBlockXSize = 0;
757 343 : int nBlockYSize = 0;
758 343 : poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
759 :
760 : /* -------------------------------------------------------------------- */
761 : /* Verify that all bands match. */
762 : /* -------------------------------------------------------------------- */
763 1108 : for (int iBand = 1; iBand < nBands; ++iBand)
764 : {
765 765 : GDALRasterBand *poBand = GetRasterBand(iBand + 1);
766 :
767 : int nThisBlockXSize, nThisBlockYSize;
768 765 : poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
769 765 : if (nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize)
770 : {
771 0 : return GDALDataset::FlushCache(bAtClosing);
772 : }
773 : }
774 :
775 : /* -------------------------------------------------------------------- */
776 : /* Now flush writable data. */
777 : /* -------------------------------------------------------------------- */
778 794 : for (int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY)
779 : {
780 991 : for (int iX = 0; iX < poBand1->nBlocksPerRow; ++iX)
781 : {
782 1690 : for (int iBand = 0; iBand < nBands; ++iBand)
783 : {
784 1150 : const CPLErr eErr = papoBands[iBand]->FlushBlock(iX, iY);
785 :
786 1150 : if (eErr != CE_None)
787 0 : return CE_Failure;
788 : }
789 : }
790 : }
791 343 : return CE_None;
792 : }
793 :
794 : /************************************************************************/
795 : /* RasterInitialize() */
796 : /* */
797 : /* Initialize raster size */
798 : /************************************************************************/
799 :
800 0 : void GDALDataset::RasterInitialize(int nXSize, int nYSize)
801 :
802 : {
803 0 : CPLAssert(nXSize > 0 && nYSize > 0);
804 :
805 0 : nRasterXSize = nXSize;
806 0 : nRasterYSize = nYSize;
807 0 : }
808 :
809 : //! @endcond
810 :
811 : /************************************************************************/
812 : /* AddBand() */
813 : /************************************************************************/
814 :
815 : /**
816 : * \fn GDALDataset::AddBand(GDALDataType, char**)
817 : * \brief Add a band to a dataset.
818 : *
819 : * This method will add a new band to the dataset if the underlying format
820 : * supports this action. Most formats do not.
821 : *
822 : * Note that the new GDALRasterBand is not returned. It may be fetched
823 : * after successful completion of the method by calling
824 : * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
825 : * band will always be the last band.
826 : *
827 : * @param eType the data type of the pixels in the new band.
828 : *
829 : * @param papszOptions a list of NAME=VALUE option strings. The supported
830 : * options are format specific. NULL may be passed by default.
831 : *
832 : * @return CE_None on success or CE_Failure on failure.
833 : */
834 :
835 0 : CPLErr GDALDataset::AddBand(CPL_UNUSED GDALDataType eType,
836 : CPL_UNUSED char **papszOptions)
837 :
838 : {
839 0 : ReportError(CE_Failure, CPLE_NotSupported,
840 : "Dataset does not support the AddBand() method.");
841 :
842 0 : return CE_Failure;
843 : }
844 :
845 : /************************************************************************/
846 : /* GDALAddBand() */
847 : /************************************************************************/
848 :
849 : /**
850 : * \brief Add a band to a dataset.
851 : *
852 : * @see GDALDataset::AddBand().
853 : */
854 :
855 30 : CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,
856 : CSLConstList papszOptions)
857 :
858 : {
859 30 : VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
860 :
861 60 : return GDALDataset::FromHandle(hDataset)->AddBand(
862 30 : eType, const_cast<char **>(papszOptions));
863 : }
864 :
865 : /************************************************************************/
866 : /* SetBand() */
867 : /************************************************************************/
868 :
869 : //! @cond Doxygen_Suppress
870 : /** Set a band in the band array, updating the band count, and array size
871 : * appropriately.
872 : *
873 : * @param nNewBand new band number (indexing starts at 1)
874 : * @param poBand band object.
875 : */
876 :
877 1746100 : void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)
878 :
879 : {
880 : /* -------------------------------------------------------------------- */
881 : /* Do we need to grow the bands list? */
882 : /* -------------------------------------------------------------------- */
883 1746100 : if (nBands < nNewBand || papoBands == nullptr)
884 : {
885 1011390 : GDALRasterBand **papoNewBands = nullptr;
886 :
887 1011390 : if (papoBands == nullptr)
888 95857 : papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
889 95753 : sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
890 : else
891 : papoNewBands = static_cast<GDALRasterBand **>(
892 915530 : VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
893 915641 : std::max(nNewBand, nBands)));
894 1011390 : if (papoNewBands == nullptr)
895 : {
896 0 : ReportError(CE_Failure, CPLE_OutOfMemory,
897 : "Cannot allocate band array");
898 0 : return;
899 : }
900 :
901 1011390 : papoBands = papoNewBands;
902 :
903 1972410 : for (int i = nBands; i < nNewBand; ++i)
904 961025 : papoBands[i] = nullptr;
905 :
906 1011390 : nBands = std::max(nBands, nNewBand);
907 :
908 1011420 : if (m_poPrivate)
909 : {
910 1011870 : for (int i = static_cast<int>(m_poPrivate->m_anBandMap.size());
911 2757570 : i < nBands; ++i)
912 : {
913 1745980 : m_poPrivate->m_anBandMap.push_back(i + 1);
914 : }
915 : }
916 : }
917 :
918 : /* -------------------------------------------------------------------- */
919 : /* Set the band. Resetting the band is currently not permitted. */
920 : /* -------------------------------------------------------------------- */
921 1745840 : if (papoBands[nNewBand - 1] != nullptr)
922 : {
923 0 : ReportError(CE_Failure, CPLE_NotSupported,
924 : "Cannot set band %d as it is already set", nNewBand);
925 0 : return;
926 : }
927 :
928 1745840 : papoBands[nNewBand - 1] = poBand;
929 :
930 : /* -------------------------------------------------------------------- */
931 : /* Set back reference information on the raster band. Note */
932 : /* that the GDALDataset is a friend of the GDALRasterBand */
933 : /* specifically to allow this. */
934 : /* -------------------------------------------------------------------- */
935 1745840 : poBand->nBand = nNewBand;
936 1745840 : poBand->poDS = this;
937 1745840 : poBand->nRasterXSize = nRasterXSize;
938 1745840 : poBand->nRasterYSize = nRasterYSize;
939 1745840 : poBand->eAccess = eAccess; // Default access to be same as dataset.
940 : }
941 :
942 : //! @endcond
943 :
944 : /************************************************************************/
945 : /* SetBand() */
946 : /************************************************************************/
947 :
948 : //! @cond Doxygen_Suppress
949 : /** Set a band in the band array, updating the band count, and array size
950 : * appropriately.
951 : *
952 : * @param nNewBand new band number (indexing starts at 1)
953 : * @param poBand band object.
954 : */
955 :
956 76495 : void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)
957 : {
958 76495 : SetBand(nNewBand, poBand.release());
959 76495 : }
960 :
961 : //! @endcond
962 :
963 : /************************************************************************/
964 : /* GetRasterXSize() */
965 : /************************************************************************/
966 :
967 : /**
968 :
969 : \brief Fetch raster width in pixels.
970 :
971 : Equivalent of the C function GDALGetRasterXSize().
972 :
973 : @return the width in pixels of raster bands in this GDALDataset.
974 :
975 : */
976 :
977 706300 : int GDALDataset::GetRasterXSize() const
978 : {
979 706300 : return nRasterXSize;
980 : }
981 :
982 : /************************************************************************/
983 : /* GDALGetRasterXSize() */
984 : /************************************************************************/
985 :
986 : /**
987 : * \brief Fetch raster width in pixels.
988 : *
989 : * @see GDALDataset::GetRasterXSize().
990 : */
991 :
992 37201 : int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)
993 :
994 : {
995 37201 : VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
996 :
997 37201 : return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
998 : }
999 :
1000 : /************************************************************************/
1001 : /* GetRasterYSize() */
1002 : /************************************************************************/
1003 :
1004 : /**
1005 :
1006 : \brief Fetch raster height in pixels.
1007 :
1008 : Equivalent of the C function GDALGetRasterYSize().
1009 :
1010 : @return the height in pixels of raster bands in this GDALDataset.
1011 :
1012 : */
1013 :
1014 586916 : int GDALDataset::GetRasterYSize() const
1015 : {
1016 586916 : return nRasterYSize;
1017 : }
1018 :
1019 : /************************************************************************/
1020 : /* GDALGetRasterYSize() */
1021 : /************************************************************************/
1022 :
1023 : /**
1024 : * \brief Fetch raster height in pixels.
1025 : *
1026 : * @see GDALDataset::GetRasterYSize().
1027 : */
1028 :
1029 36862 : int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)
1030 :
1031 : {
1032 36862 : VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
1033 :
1034 36862 : return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
1035 : }
1036 :
1037 : /************************************************************************/
1038 : /* GetRasterBand() */
1039 : /************************************************************************/
1040 :
1041 : /**
1042 :
1043 : \brief Fetch a band object for a dataset.
1044 :
1045 : See GetBands() for a C++ iterator version of this method.
1046 :
1047 : Equivalent of the C function GDALGetRasterBand().
1048 :
1049 : @param nBandId the index number of the band to fetch, from 1 to
1050 : GetRasterCount().
1051 :
1052 : @return the nBandId th band object
1053 :
1054 : */
1055 :
1056 11939100 : GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)
1057 :
1058 : {
1059 11939100 : if (papoBands)
1060 : {
1061 11934900 : if (nBandId < 1 || nBandId > nBands)
1062 : {
1063 56762 : ReportError(CE_Failure, CPLE_IllegalArg,
1064 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1065 : nBandId);
1066 12 : return nullptr;
1067 : }
1068 :
1069 11878200 : return papoBands[nBandId - 1];
1070 : }
1071 4192 : return nullptr;
1072 : }
1073 :
1074 : /************************************************************************/
1075 : /* GetRasterBand() */
1076 : /************************************************************************/
1077 :
1078 : /**
1079 :
1080 : \brief Fetch a band object for a dataset.
1081 :
1082 : See GetBands() for a C++ iterator version of this method.
1083 :
1084 : Equivalent of the C function GDALGetRasterBand().
1085 :
1086 : @param nBandId the index number of the band to fetch, from 1 to
1087 : GetRasterCount().
1088 :
1089 : @return the nBandId th band object
1090 :
1091 : */
1092 :
1093 587 : const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const
1094 :
1095 : {
1096 587 : if (papoBands)
1097 : {
1098 587 : if (nBandId < 1 || nBandId > nBands)
1099 : {
1100 0 : ReportError(CE_Failure, CPLE_IllegalArg,
1101 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1102 : nBandId);
1103 0 : return nullptr;
1104 : }
1105 :
1106 587 : return papoBands[nBandId - 1];
1107 : }
1108 0 : return nullptr;
1109 : }
1110 :
1111 : /************************************************************************/
1112 : /* GDALGetRasterBand() */
1113 : /************************************************************************/
1114 :
1115 : /**
1116 : * \brief Fetch a band object for a dataset.
1117 : * @see GDALDataset::GetRasterBand().
1118 : */
1119 :
1120 399792 : GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)
1121 :
1122 : {
1123 399792 : VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
1124 :
1125 399792 : return GDALRasterBand::ToHandle(
1126 399792 : GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
1127 : }
1128 :
1129 : /************************************************************************/
1130 : /* GetRasterCount() */
1131 : /************************************************************************/
1132 :
1133 : /**
1134 : * \brief Fetch the number of raster bands on this dataset.
1135 : *
1136 : * Same as the C function GDALGetRasterCount().
1137 : *
1138 : * @return the number of raster bands.
1139 : */
1140 :
1141 5826330 : int GDALDataset::GetRasterCount() const
1142 : {
1143 5826330 : return papoBands ? nBands : 0;
1144 : }
1145 :
1146 : /************************************************************************/
1147 : /* GDALGetRasterCount() */
1148 : /************************************************************************/
1149 :
1150 : /**
1151 : * \brief Fetch the number of raster bands on this dataset.
1152 : *
1153 : * @see GDALDataset::GetRasterCount().
1154 : */
1155 :
1156 382269 : int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)
1157 :
1158 : {
1159 382269 : VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
1160 :
1161 382269 : return GDALDataset::FromHandle(hDS)->GetRasterCount();
1162 : }
1163 :
1164 : /************************************************************************/
1165 : /* GetProjectionRef() */
1166 : /************************************************************************/
1167 :
1168 : /**
1169 : * \brief Fetch the projection definition string for this dataset.
1170 : *
1171 : * Same as the C function GDALGetProjectionRef().
1172 : *
1173 : * The returned string defines the projection coordinate system of the
1174 : * image in OpenGIS WKT format. It should be suitable for use with the
1175 : * OGRSpatialReference class.
1176 : *
1177 : * When a projection definition is not available an empty (but not NULL)
1178 : * string is returned.
1179 : *
1180 : * \note Starting with GDAL 3.0, this is a compatibility layer around
1181 : * GetSpatialRef()
1182 : *
1183 : * @return a pointer to an internal projection reference string. It should
1184 : * not be altered, freed or expected to last for long.
1185 : *
1186 : * @see https://gdal.org/tutorials/osr_api_tut.html
1187 : */
1188 :
1189 5364 : const char *GDALDataset::GetProjectionRef() const
1190 : {
1191 5364 : const auto poSRS = GetSpatialRef();
1192 5364 : if (!poSRS || !m_poPrivate)
1193 : {
1194 2424 : return "";
1195 : }
1196 2940 : char *pszWKT = nullptr;
1197 2940 : poSRS->exportToWkt(&pszWKT);
1198 2940 : if (!pszWKT)
1199 : {
1200 0 : return "";
1201 : }
1202 :
1203 : // If called on a thread-safe dataset, we might be called by several
1204 : // threads, so make sure our accesses to m_pszWKTCached are protected
1205 : // by a mutex.
1206 5880 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1207 2940 : if (m_poPrivate->m_pszWKTCached &&
1208 793 : strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)
1209 : {
1210 792 : CPLFree(pszWKT);
1211 792 : return m_poPrivate->m_pszWKTCached;
1212 : }
1213 2148 : CPLFree(m_poPrivate->m_pszWKTCached);
1214 2148 : m_poPrivate->m_pszWKTCached = pszWKT;
1215 2148 : return m_poPrivate->m_pszWKTCached;
1216 : }
1217 :
1218 : /************************************************************************/
1219 : /* GetSpatialRef() */
1220 : /************************************************************************/
1221 :
1222 : static thread_local int tlsEnableLayersInGetSpatialRefCounter = 0;
1223 :
1224 : /**
1225 : * \brief Fetch the spatial reference for this dataset.
1226 : *
1227 : * Same as the C function GDALGetSpatialRef().
1228 : *
1229 : * When a projection definition is not available, null is returned. If used on
1230 : * a dataset where there are GCPs and not a geotransform, this method returns
1231 : * null. Use GetGCPSpatialRef() instead.
1232 : *
1233 : * Since GDAL 3.12, the default implementation of this method will iterate over
1234 : * vector layers and return their SRS if all geometry columns of all layers use
1235 : * the same SRS, or nullptr otherwise.
1236 : *
1237 : * @since GDAL 3.0
1238 : *
1239 : * @return a pointer to an internal object. It should not be altered or freed.
1240 : * Its lifetime will be the one of the dataset object.
1241 : *
1242 : * @see https://gdal.org/tutorials/osr_api_tut.html
1243 : */
1244 :
1245 17130 : const OGRSpatialReference *GDALDataset::GetSpatialRef() const
1246 : {
1247 17130 : if (tlsEnableLayersInGetSpatialRefCounter == 0)
1248 17098 : return GetSpatialRefVectorOnly();
1249 32 : return nullptr;
1250 : }
1251 :
1252 : /************************************************************************/
1253 : /* GetSpatialRefVectorOnly() */
1254 : /************************************************************************/
1255 :
1256 : /**
1257 : * \brief Fetch the spatial reference for this dataset (only for vector layers)
1258 : *
1259 : * The default implementation of this method will iterate over
1260 : * vector layers and return their SRS if all geometry columns of all layers use
1261 : * the same SRS, or nullptr otherwise.
1262 : *
1263 : * @since GDAL 3.12
1264 : *
1265 : * @return a pointer to an internal object. It should not be altered or freed.
1266 : * Its lifetime will be the one of the dataset object.
1267 : */
1268 :
1269 17099 : const OGRSpatialReference *GDALDataset::GetSpatialRefVectorOnly() const
1270 : {
1271 17099 : bool bInit = false;
1272 17099 : const OGRSpatialReference *poGlobalSRS = nullptr;
1273 33262 : for (const OGRLayer *poLayer : GetLayers())
1274 : {
1275 16164 : for (const auto *poGeomFieldDefn :
1276 48494 : poLayer->GetLayerDefn()->GetGeomFields())
1277 : {
1278 16167 : const auto *poSRS = poGeomFieldDefn->GetSpatialRef();
1279 16167 : if (!bInit)
1280 : {
1281 207 : bInit = true;
1282 207 : poGlobalSRS = poSRS;
1283 : }
1284 31918 : else if ((poSRS && !poGlobalSRS) || (!poSRS && poGlobalSRS) ||
1285 15958 : (poSRS && poGlobalSRS && !poSRS->IsSame(poGlobalSRS)))
1286 : {
1287 3 : CPLDebug("GDAL",
1288 : "Not all geometry fields or layers have the same CRS");
1289 3 : return nullptr;
1290 : }
1291 : }
1292 : }
1293 17096 : return poGlobalSRS;
1294 : }
1295 :
1296 : /************************************************************************/
1297 : /* GetSpatialRefRasterOnly() */
1298 : /************************************************************************/
1299 :
1300 : /**
1301 : * \brief Fetch the spatial reference for this dataset (ignoring vector layers)
1302 : *
1303 : * @since GDAL 3.12
1304 : *
1305 : * @return a pointer to an internal object. It should not be altered or freed.
1306 : * Its lifetime will be the one of the dataset object.
1307 : */
1308 :
1309 781 : const OGRSpatialReference *GDALDataset::GetSpatialRefRasterOnly() const
1310 : {
1311 781 : ++tlsEnableLayersInGetSpatialRefCounter;
1312 781 : const auto poRet = GetSpatialRef();
1313 781 : --tlsEnableLayersInGetSpatialRefCounter;
1314 781 : return poRet;
1315 : }
1316 :
1317 : /************************************************************************/
1318 : /* GDALGetSpatialRef() */
1319 : /************************************************************************/
1320 :
1321 : /**
1322 : * \brief Fetch the spatial reference for this dataset.
1323 : *
1324 : * Same as the C++ method GDALDataset::GetSpatialRef()
1325 : *
1326 : * @since GDAL 3.0
1327 : *
1328 : * @see GDALDataset::GetSpatialRef()
1329 : */
1330 :
1331 6760 : OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)
1332 :
1333 : {
1334 6760 : VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
1335 :
1336 6760 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1337 6760 : GDALDataset::FromHandle(hDS)->GetSpatialRef()));
1338 : }
1339 :
1340 : /************************************************************************/
1341 : /* GDALGetProjectionRef() */
1342 : /************************************************************************/
1343 :
1344 : /**
1345 : * \brief Fetch the projection definition string for this dataset.
1346 : *
1347 : * @see GDALDataset::GetProjectionRef()
1348 : */
1349 :
1350 1483 : const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)
1351 :
1352 : {
1353 1483 : VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
1354 :
1355 1483 : return GDALDataset::FromHandle(hDS)->GetProjectionRef();
1356 : }
1357 :
1358 : /************************************************************************/
1359 : /* SetProjection() */
1360 : /************************************************************************/
1361 :
1362 : /**
1363 : * \brief Set the projection reference string for this dataset.
1364 : *
1365 : * The string should be in OGC WKT or PROJ.4 format. An error may occur
1366 : * because of incorrectly specified projection strings, because the dataset
1367 : * is not writable, or because the dataset does not support the indicated
1368 : * projection. Many formats do not support writing projections.
1369 : *
1370 : * This method is the same as the C GDALSetProjection() function.
1371 : *
1372 : * \note Startig with GDAL 3.0, this is a compatibility layer around
1373 : * SetSpatialRef()
1374 :
1375 : * @param pszProjection projection reference string.
1376 : *
1377 : * @return CE_Failure if an error occurs, otherwise CE_None.
1378 : */
1379 :
1380 2403 : CPLErr GDALDataset::SetProjection(const char *pszProjection)
1381 : {
1382 2403 : if (pszProjection && pszProjection[0] != '\0')
1383 : {
1384 4440 : OGRSpatialReference oSRS;
1385 2220 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1386 2220 : if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)
1387 : {
1388 2 : return CE_Failure;
1389 : }
1390 2218 : return SetSpatialRef(&oSRS);
1391 : }
1392 : else
1393 : {
1394 183 : return SetSpatialRef(nullptr);
1395 : }
1396 : }
1397 :
1398 : /************************************************************************/
1399 : /* SetSpatialRef() */
1400 : /************************************************************************/
1401 :
1402 : /**
1403 : * \brief Set the spatial reference system for this dataset.
1404 : *
1405 : * An error may occur because the dataset
1406 : * is not writable, or because the dataset does not support the indicated
1407 : * projection. Many formats do not support writing projections.
1408 : *
1409 : * This method is the same as the C GDALSetSpatialRef() function.
1410 : *
1411 : * @since GDAL 3.0
1412 :
1413 : * @param poSRS spatial reference system object. nullptr can potentially be
1414 : * passed for drivers that support unsetting the SRS.
1415 : *
1416 : * @return CE_Failure if an error occurs, otherwise CE_None.
1417 : */
1418 :
1419 0 : CPLErr GDALDataset::SetSpatialRef(CPL_UNUSED const OGRSpatialReference *poSRS)
1420 : {
1421 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1422 0 : ReportError(CE_Failure, CPLE_NotSupported,
1423 : "Dataset does not support the SetSpatialRef() method.");
1424 0 : return CE_Failure;
1425 : }
1426 :
1427 : /************************************************************************/
1428 : /* GDALSetSpatialRef() */
1429 : /************************************************************************/
1430 :
1431 : /**
1432 : * \brief Set the spatial reference system for this dataset.
1433 : *
1434 : * @since GDAL 3.0
1435 : *
1436 : * @see GDALDataset::SetSpatialRef()
1437 : */
1438 :
1439 1157 : CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)
1440 :
1441 : {
1442 1157 : VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1443 :
1444 2314 : return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1445 1157 : OGRSpatialReference::FromHandle(hSRS));
1446 : }
1447 :
1448 : /************************************************************************/
1449 : /* GDALSetProjection() */
1450 : /************************************************************************/
1451 :
1452 : /**
1453 : * \brief Set the projection reference string for this dataset.
1454 : *
1455 : * @see GDALDataset::SetProjection()
1456 : */
1457 :
1458 1784 : CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,
1459 : const char *pszProjection)
1460 :
1461 : {
1462 1784 : VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1463 :
1464 1784 : return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
1465 : }
1466 :
1467 : /************************************************************************/
1468 : /* GetGeoTransform() */
1469 : /************************************************************************/
1470 :
1471 : /**
1472 : * \brief Fetch the affine transformation coefficients.
1473 : *
1474 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
1475 : * space, and projection coordinates (Xp,Yp) space.
1476 : *
1477 : * \code
1478 : * Xp = gt[0] + P*gt[1] + L*gt[2];
1479 : * Yp = gt[3] + P*padfTransform[4] + L*gt[5];
1480 : * \endcode
1481 : *
1482 : * In a north up image, gt[1] is the pixel width, and
1483 : * gt[5] is the pixel height. The upper left corner of the
1484 : * upper left pixel is at position (gt[0],gt[3]).
1485 : *
1486 : * The default transform is (0,1,0,0,0,1) and should be returned even when
1487 : * a CE_Failure error is returned, such as for formats that don't support
1488 : * transformation to projection coordinates.
1489 : *
1490 : * This method does the same thing as the C GDALGetGeoTransform() function.
1491 : *
1492 : * @param gt an existing six double buffer into which the
1493 : * transformation will be placed.
1494 : *
1495 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
1496 : *
1497 : * @since 3.12
1498 : */
1499 :
1500 15617 : CPLErr GDALDataset::GetGeoTransform(GDALGeoTransform >) const
1501 :
1502 : {
1503 15617 : gt = GDALGeoTransform();
1504 :
1505 15618 : return CE_Failure;
1506 : }
1507 :
1508 : /************************************************************************/
1509 : /* GetGeoTransform() */
1510 : /************************************************************************/
1511 :
1512 : /**
1513 : * \brief Fetch the affine transformation coefficients.
1514 : *
1515 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
1516 : * space, and projection coordinates (Xp,Yp) space.
1517 : *
1518 : * \code
1519 : * Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
1520 : * Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
1521 : * \endcode
1522 : *
1523 : * In a north up image, padfTransform[1] is the pixel width, and
1524 : * padfTransform[5] is the pixel height. The upper left corner of the
1525 : * upper left pixel is at position (padfTransform[0],padfTransform[3]).
1526 : *
1527 : * The default transform is (0,1,0,0,0,1) and should be returned even when
1528 : * a CE_Failure error is returned, such as for formats that don't support
1529 : * transformation to projection coordinates.
1530 : *
1531 : * This method does the same thing as the C GDALGetGeoTransform() function.
1532 : *
1533 : * @param padfTransform an existing six double buffer into which the
1534 : * transformation will be placed.
1535 : *
1536 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
1537 : *
1538 : * @deprecated since 3.12. Use GetGeoTransform(GDALGeoTransform&) instead
1539 : */
1540 :
1541 2 : CPLErr GDALDataset::GetGeoTransform(double *padfTransform) const
1542 :
1543 : {
1544 2 : return GetGeoTransform(
1545 2 : *reinterpret_cast<GDALGeoTransform *>(padfTransform));
1546 : }
1547 :
1548 : /************************************************************************/
1549 : /* GDALGetGeoTransform() */
1550 : /************************************************************************/
1551 :
1552 : /**
1553 : * \brief Fetch the affine transformation coefficients.
1554 : *
1555 : * @see GDALDataset::GetGeoTransform()
1556 : */
1557 :
1558 8813 : CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1559 :
1560 : {
1561 8813 : VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1562 :
1563 17626 : return GDALDataset::FromHandle(hDS)->GetGeoTransform(
1564 8813 : *reinterpret_cast<GDALGeoTransform *>(padfTransform));
1565 : }
1566 :
1567 : /************************************************************************/
1568 : /* SetGeoTransform() */
1569 : /************************************************************************/
1570 :
1571 : /**
1572 : * \fn GDALDataset::SetGeoTransform(const GDALGeoTransform&)
1573 : * \brief Set the affine transformation coefficients.
1574 : *
1575 : * See GetGeoTransform() for details on the meaning of the padfTransform
1576 : * coefficients.
1577 : *
1578 : * This method does the same thing as the C GDALSetGeoTransform() function.
1579 : *
1580 : * @param gt the transformation coefficients to be written with the dataset.
1581 : *
1582 : * @return CE_None on success, or CE_Failure if this transform cannot be
1583 : * written.
1584 : *
1585 : * @since 3.12
1586 : */
1587 :
1588 0 : CPLErr GDALDataset::SetGeoTransform(CPL_UNUSED const GDALGeoTransform >)
1589 :
1590 : {
1591 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1592 0 : ReportError(CE_Failure, CPLE_NotSupported,
1593 : "SetGeoTransform() not supported for this dataset.");
1594 :
1595 0 : return CE_Failure;
1596 : }
1597 :
1598 : /************************************************************************/
1599 : /* SetGeoTransform() */
1600 : /************************************************************************/
1601 :
1602 : /**
1603 : * \brief Set the affine transformation coefficients.
1604 : *
1605 : * See GetGeoTransform() for details on the meaning of the padfTransform
1606 : * coefficients.
1607 : *
1608 : * This method does the same thing as the C GDALSetGeoTransform() function.
1609 : *
1610 : * @param padfTransform a six double buffer containing the transformation
1611 : * coefficients to be written with the dataset.
1612 : *
1613 : * @return CE_None on success, or CE_Failure if this transform cannot be
1614 : * written.
1615 : *
1616 : * @deprecated since 3.12. Use SetGeoTransform(const GDALGeoTransform&) instead
1617 : */
1618 30 : CPLErr GDALDataset::SetGeoTransform(const double *padfTransform)
1619 :
1620 : {
1621 30 : return SetGeoTransform(
1622 30 : *reinterpret_cast<const GDALGeoTransform *>(padfTransform));
1623 : }
1624 :
1625 : /************************************************************************/
1626 : /* GDALSetGeoTransform() */
1627 : /************************************************************************/
1628 :
1629 : /**
1630 : * \brief Set the affine transformation coefficients.
1631 : *
1632 : * @see GDALDataset::SetGeoTransform()
1633 : */
1634 :
1635 3934 : CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS,
1636 : const double *padfTransform)
1637 :
1638 : {
1639 3934 : VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1640 3934 : VALIDATE_POINTER1(padfTransform, "GDALSetGeoTransform", CE_Failure);
1641 :
1642 7868 : return GDALDataset::FromHandle(hDS)->SetGeoTransform(
1643 3934 : *reinterpret_cast<const GDALGeoTransform *>(padfTransform));
1644 : }
1645 :
1646 : /************************************************************************/
1647 : /* GetInternalHandle() */
1648 : /************************************************************************/
1649 :
1650 : /**
1651 : * \fn GDALDataset::GetInternalHandle(const char*)
1652 : * \brief Fetch a format specific internally meaningful handle.
1653 : *
1654 : * This method is the same as the C GDALGetInternalHandle() method.
1655 : *
1656 : * @param pszHandleName the handle name desired. The meaningful names
1657 : * will be specific to the file format.
1658 : *
1659 : * @return the desired handle value, or NULL if not recognized/supported.
1660 : */
1661 :
1662 185 : void *GDALDataset::GetInternalHandle(CPL_UNUSED const char *pszHandleName)
1663 :
1664 : {
1665 185 : return nullptr;
1666 : }
1667 :
1668 : /************************************************************************/
1669 : /* GDALGetInternalHandle() */
1670 : /************************************************************************/
1671 :
1672 : /**
1673 : * \brief Fetch a format specific internally meaningful handle.
1674 : *
1675 : * @see GDALDataset::GetInternalHandle()
1676 : */
1677 :
1678 60 : void *CPL_STDCALL GDALGetInternalHandle(GDALDatasetH hDS,
1679 : const char *pszRequest)
1680 :
1681 : {
1682 60 : VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
1683 :
1684 60 : return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
1685 : }
1686 :
1687 : /************************************************************************/
1688 : /* GetDriver() */
1689 : /************************************************************************/
1690 :
1691 : /**
1692 : * \brief Fetch the driver to which this dataset relates.
1693 : *
1694 : * This method is the same as the C GDALGetDatasetDriver() function.
1695 : *
1696 : * @return the driver on which the dataset was created with GDALOpen() or
1697 : * GDALCreate().
1698 : */
1699 :
1700 31023 : GDALDriver *GDALDataset::GetDriver()
1701 : {
1702 31023 : return poDriver;
1703 : }
1704 :
1705 : /************************************************************************/
1706 : /* GDALGetDatasetDriver() */
1707 : /************************************************************************/
1708 :
1709 : /**
1710 : * \brief Fetch the driver to which this dataset relates.
1711 : *
1712 : * @see GDALDataset::GetDriver()
1713 : */
1714 :
1715 2686 : GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)
1716 :
1717 : {
1718 2686 : VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1719 :
1720 : return static_cast<GDALDriverH>(
1721 2686 : GDALDataset::FromHandle(hDataset)->GetDriver());
1722 : }
1723 :
1724 : /************************************************************************/
1725 : /* Reference() */
1726 : /************************************************************************/
1727 :
1728 : /**
1729 : * \brief Add one to dataset reference count.
1730 : *
1731 : * The reference is one after instantiation.
1732 : *
1733 : * This method is the same as the C GDALReferenceDataset() function.
1734 : *
1735 : * @return the post-increment reference count.
1736 : */
1737 :
1738 257283 : int GDALDataset::Reference()
1739 : {
1740 257283 : return ++nRefCount;
1741 : }
1742 :
1743 : /************************************************************************/
1744 : /* GDALReferenceDataset() */
1745 : /************************************************************************/
1746 :
1747 : /**
1748 : * \brief Add one to dataset reference count.
1749 : *
1750 : * @see GDALDataset::Reference()
1751 : */
1752 :
1753 1255 : int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)
1754 :
1755 : {
1756 1255 : VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1757 :
1758 1255 : return GDALDataset::FromHandle(hDataset)->Reference();
1759 : }
1760 :
1761 : /************************************************************************/
1762 : /* Dereference() */
1763 : /************************************************************************/
1764 :
1765 : /**
1766 : * \brief Subtract one from dataset reference count.
1767 : *
1768 : * The reference is one after instantiation. Generally when the reference
1769 : * count has dropped to zero the dataset may be safely deleted (closed).
1770 : *
1771 : * This method is the same as the C GDALDereferenceDataset() function.
1772 : *
1773 : * @return the post-decrement reference count.
1774 : */
1775 :
1776 315758 : int GDALDataset::Dereference()
1777 : {
1778 315758 : return --nRefCount;
1779 : }
1780 :
1781 : /************************************************************************/
1782 : /* GDALDereferenceDataset() */
1783 : /************************************************************************/
1784 :
1785 : /**
1786 : * \brief Subtract one from dataset reference count.
1787 : *
1788 : * @see GDALDataset::Dereference()
1789 : */
1790 :
1791 57082 : int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)
1792 :
1793 : {
1794 57082 : VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1795 :
1796 57082 : return GDALDataset::FromHandle(hDataset)->Dereference();
1797 : }
1798 :
1799 : /************************************************************************/
1800 : /* ReleaseRef() */
1801 : /************************************************************************/
1802 :
1803 : /**
1804 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1805 : * @return TRUE if the object has been destroyed.
1806 : * @since GDAL 2.2
1807 : */
1808 :
1809 251060 : int GDALDataset::ReleaseRef()
1810 :
1811 : {
1812 251060 : if (Dereference() <= 0)
1813 : {
1814 7335 : nRefCount = 1;
1815 7335 : delete this;
1816 7335 : return TRUE;
1817 : }
1818 243725 : return FALSE;
1819 : }
1820 :
1821 : /************************************************************************/
1822 : /* GDALReleaseDataset() */
1823 : /************************************************************************/
1824 :
1825 : /**
1826 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1827 : *
1828 : * @see GDALDataset::ReleaseRef()
1829 : * @since GDAL 2.2
1830 : */
1831 :
1832 1492 : int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)
1833 :
1834 : {
1835 1492 : VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1836 :
1837 1492 : return GDALDataset::FromHandle(hDataset)->ReleaseRef();
1838 : }
1839 :
1840 : /************************************************************************/
1841 : /* GetShared() */
1842 : /************************************************************************/
1843 :
1844 : /**
1845 : * \brief Returns shared flag.
1846 : *
1847 : * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1848 : */
1849 :
1850 307610 : int GDALDataset::GetShared() const
1851 : {
1852 307610 : return bShared;
1853 : }
1854 :
1855 : /************************************************************************/
1856 : /* MarkAsShared() */
1857 : /************************************************************************/
1858 :
1859 : /**
1860 : * \brief Mark this dataset as available for sharing.
1861 : */
1862 :
1863 408 : void GDALDataset::MarkAsShared()
1864 :
1865 : {
1866 408 : CPLAssert(!bShared);
1867 :
1868 408 : bShared = true;
1869 408 : if (bIsInternal)
1870 14 : return;
1871 :
1872 394 : GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1873 :
1874 : // Insert the dataset in the set of shared opened datasets.
1875 788 : CPLMutexHolderD(&hDLMutex);
1876 394 : if (phSharedDatasetSet == nullptr)
1877 209 : phSharedDatasetSet =
1878 209 : CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1879 : GDALSharedDatasetFreeFunc);
1880 :
1881 : SharedDatasetCtxt *psStruct =
1882 394 : static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1883 394 : psStruct->poDS = this;
1884 394 : psStruct->nPID = nPID;
1885 394 : psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
1886 394 : psStruct->pszDescription = CPLStrdup(GetDescription());
1887 : std::string osConcatenatedOpenOptions =
1888 788 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
1889 394 : psStruct->pszConcatenatedOpenOptions =
1890 394 : CPLStrdup(osConcatenatedOpenOptions.c_str());
1891 394 : if (CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
1892 : {
1893 1 : GDALSharedDatasetFreeFunc(psStruct);
1894 1 : ReportError(CE_Failure, CPLE_AppDefined,
1895 : "An existing shared dataset already has this description. "
1896 : "This should not happen.");
1897 : }
1898 : else
1899 : {
1900 393 : CPLHashSetInsert(phSharedDatasetSet, psStruct);
1901 :
1902 393 : (*poAllDatasetMap)[this] = nPID;
1903 : }
1904 : }
1905 :
1906 : /************************************************************************/
1907 : /* MarkSuppressOnClose() */
1908 : /************************************************************************/
1909 :
1910 : /** Set that the dataset must be deleted on close.
1911 : *
1912 : * This is the same as C function GDALDatasetMarkSuppressOnClose()
1913 : */
1914 1200 : void GDALDataset::MarkSuppressOnClose()
1915 : {
1916 1200 : bSuppressOnClose = true;
1917 1200 : }
1918 :
1919 : /************************************************************************/
1920 : /* GDALDatasetMarkSuppressOnClose() */
1921 : /************************************************************************/
1922 :
1923 : /** Set that the dataset must be deleted on close.
1924 : *
1925 : * This is the same as C++ method GDALDataset::MarkSuppressOnClose()
1926 : *
1927 : * @since GDAL 3.12
1928 : */
1929 :
1930 4 : void GDALDatasetMarkSuppressOnClose(GDALDatasetH hDS)
1931 : {
1932 4 : VALIDATE_POINTER0(hDS, "GDALDatasetMarkSuppressOnClose");
1933 :
1934 4 : return GDALDataset::FromHandle(hDS)->MarkSuppressOnClose();
1935 : }
1936 :
1937 : /************************************************************************/
1938 : /* UnMarkSuppressOnClose() */
1939 : /************************************************************************/
1940 :
1941 : /** Remove the flag requesting the dataset to be deleted on close. */
1942 689 : void GDALDataset::UnMarkSuppressOnClose()
1943 : {
1944 689 : bSuppressOnClose = false;
1945 689 : }
1946 :
1947 : /************************************************************************/
1948 : /* CleanupPostFileClosing() */
1949 : /************************************************************************/
1950 :
1951 : /** This method should be called by driver implementations in their destructor,
1952 : * after having closed all files, but before having freed resources that
1953 : * are needed for their GetFileList() implementation.
1954 : * This is used to implement MarkSuppressOnClose behavior.
1955 : */
1956 259 : void GDALDataset::CleanupPostFileClosing()
1957 : {
1958 259 : if (IsMarkedSuppressOnClose())
1959 : {
1960 1 : char **papszFileList = GetFileList();
1961 3 : for (int i = 0; papszFileList && papszFileList[i]; ++i)
1962 2 : VSIUnlink(papszFileList[i]);
1963 1 : CSLDestroy(papszFileList);
1964 : }
1965 259 : }
1966 :
1967 : /************************************************************************/
1968 : /* GetGCPCount() */
1969 : /************************************************************************/
1970 :
1971 : /**
1972 : * \brief Get number of GCPs.
1973 : *
1974 : * This method is the same as the C function GDALGetGCPCount().
1975 : *
1976 : * @return number of GCPs for this dataset. Zero if there are none.
1977 : */
1978 :
1979 16165 : int GDALDataset::GetGCPCount()
1980 : {
1981 16165 : return 0;
1982 : }
1983 :
1984 : /************************************************************************/
1985 : /* GDALGetGCPCount() */
1986 : /************************************************************************/
1987 :
1988 : /**
1989 : * \brief Get number of GCPs.
1990 : *
1991 : * @see GDALDataset::GetGCPCount()
1992 : */
1993 :
1994 2121 : int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)
1995 :
1996 : {
1997 2121 : VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
1998 :
1999 2121 : return GDALDataset::FromHandle(hDS)->GetGCPCount();
2000 : }
2001 :
2002 : /************************************************************************/
2003 : /* GetGCPProjection() */
2004 : /************************************************************************/
2005 :
2006 : /**
2007 : * \brief Get output projection for GCPs.
2008 : *
2009 : * This method is the same as the C function GDALGetGCPProjection().
2010 : *
2011 : * The projection string follows the normal rules from GetProjectionRef().
2012 : *
2013 : * \note Starting with GDAL 3.0, this is a compatibility layer around
2014 : * GetGCPSpatialRef()
2015 : *
2016 : * @return internal projection string or "" if there are no GCPs.
2017 : * It should not be altered, freed or expected to last for long.
2018 : */
2019 :
2020 916 : const char *GDALDataset::GetGCPProjection()
2021 : {
2022 916 : const auto poSRS = GetGCPSpatialRef();
2023 916 : if (!poSRS || !m_poPrivate)
2024 : {
2025 580 : return "";
2026 : }
2027 336 : char *pszWKT = nullptr;
2028 336 : poSRS->exportToWkt(&pszWKT);
2029 336 : if (!pszWKT)
2030 : {
2031 0 : return "";
2032 : }
2033 :
2034 : // If called on a thread-safe dataset, we might be called by several
2035 : // threads, so make sure our accesses to m_pszWKTCached are protected
2036 : // by a mutex.
2037 672 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
2038 336 : if (m_poPrivate->m_pszWKTGCPCached &&
2039 256 : strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0)
2040 : {
2041 256 : CPLFree(pszWKT);
2042 256 : return m_poPrivate->m_pszWKTGCPCached;
2043 : }
2044 80 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
2045 80 : m_poPrivate->m_pszWKTGCPCached = pszWKT;
2046 80 : return m_poPrivate->m_pszWKTGCPCached;
2047 : }
2048 :
2049 : /************************************************************************/
2050 : /* GetGCPSpatialRef() */
2051 : /************************************************************************/
2052 :
2053 : /**
2054 : * \brief Get output spatial reference system for GCPs.
2055 : *
2056 : * Same as the C function GDALGetGCPSpatialRef().
2057 : *
2058 : * When a SRS is not available, null is returned. If used on
2059 : * a dataset where there is a geotransform, and not GCPs, this method returns
2060 : * null. Use GetSpatialRef() instead.
2061 : *
2062 : * @since GDAL 3.0
2063 : *
2064 : * @return a pointer to an internal object. It should not be altered or freed.
2065 : * Its lifetime will be the one of the dataset object, or until the next
2066 : * call to this method.
2067 : */
2068 :
2069 39 : const OGRSpatialReference *GDALDataset::GetGCPSpatialRef() const
2070 : {
2071 39 : return nullptr;
2072 : }
2073 :
2074 : /************************************************************************/
2075 : /* GDALGetGCPSpatialRef() */
2076 : /************************************************************************/
2077 :
2078 : /**
2079 : * \brief Get output spatial reference system for GCPs.
2080 : *
2081 : * @since GDAL 3.0
2082 : *
2083 : * @see GDALDataset::GetGCPSpatialRef()
2084 : */
2085 :
2086 468 : OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)
2087 :
2088 : {
2089 468 : VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
2090 :
2091 468 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
2092 468 : GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
2093 : }
2094 :
2095 : /************************************************************************/
2096 : /* GDALGetGCPProjection() */
2097 : /************************************************************************/
2098 :
2099 : /**
2100 : * \brief Get output projection for GCPs.
2101 : *
2102 : * @see GDALDataset::GetGCPProjection()
2103 : */
2104 :
2105 846 : const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)
2106 :
2107 : {
2108 846 : VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
2109 :
2110 846 : return GDALDataset::FromHandle(hDS)->GetGCPProjection();
2111 : }
2112 :
2113 : /************************************************************************/
2114 : /* GetGCPs() */
2115 : /************************************************************************/
2116 :
2117 : /**
2118 : * \brief Fetch GCPs.
2119 : *
2120 : * This method is the same as the C function GDALGetGCPs().
2121 : *
2122 : * @return pointer to internal GCP structure list. It should not be modified,
2123 : * and may change on the next GDAL call.
2124 : */
2125 :
2126 10 : const GDAL_GCP *GDALDataset::GetGCPs()
2127 : {
2128 10 : return nullptr;
2129 : }
2130 :
2131 : /************************************************************************/
2132 : /* GDALGetGCPs() */
2133 : /************************************************************************/
2134 :
2135 : /**
2136 : * \brief Fetch GCPs.
2137 : *
2138 : * @see GDALDataset::GetGCPs()
2139 : */
2140 :
2141 578 : const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)
2142 :
2143 : {
2144 578 : VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
2145 :
2146 578 : return GDALDataset::FromHandle(hDS)->GetGCPs();
2147 : }
2148 :
2149 : /************************************************************************/
2150 : /* SetGCPs() */
2151 : /************************************************************************/
2152 :
2153 : /**
2154 : * \brief Assign GCPs.
2155 : *
2156 : * This method is the same as the C function GDALSetGCPs().
2157 : *
2158 : * This method assigns the passed set of GCPs to this dataset, as well as
2159 : * setting their coordinate system. Internally copies are made of the
2160 : * coordinate system and list of points, so the caller remains responsible for
2161 : * deallocating these arguments if appropriate.
2162 : *
2163 : * Most formats do not support setting of GCPs, even formats that can
2164 : * handle GCPs. These formats will return CE_Failure.
2165 : *
2166 : * \note Startig with GDAL 3.0, this is a compatibility layer around
2167 : * SetGCPs(int, const GDAL_GCP*, const char*)
2168 : *
2169 : * @param nGCPCount number of GCPs being assigned.
2170 : *
2171 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2172 : *
2173 : * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
2174 : * GCP output coordinates. This parameter should be "" if no output coordinate
2175 : * system is known.
2176 : *
2177 : * @return CE_None on success, CE_Failure on failure (including if action is
2178 : * not supported for this format).
2179 : */
2180 :
2181 52 : CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,
2182 : const char *pszGCPProjection)
2183 :
2184 : {
2185 52 : if (pszGCPProjection && pszGCPProjection[0] != '\0')
2186 : {
2187 66 : OGRSpatialReference oSRS;
2188 33 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
2189 33 : if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)
2190 : {
2191 0 : return CE_Failure;
2192 : }
2193 33 : return SetGCPs(nGCPCount, pasGCPList, &oSRS);
2194 : }
2195 : else
2196 : {
2197 19 : return SetGCPs(nGCPCount, pasGCPList,
2198 19 : static_cast<const OGRSpatialReference *>(nullptr));
2199 : }
2200 : }
2201 :
2202 : /************************************************************************/
2203 : /* SetGCPs() */
2204 : /************************************************************************/
2205 :
2206 : /**
2207 : * \brief Assign GCPs.
2208 : *
2209 : * This method is the same as the C function GDALSetGCPs().
2210 : *
2211 : * This method assigns the passed set of GCPs to this dataset, as well as
2212 : * setting their coordinate system. Internally copies are made of the
2213 : * coordinate system and list of points, so the caller remains responsible for
2214 : * deallocating these arguments if appropriate.
2215 : *
2216 : * Most formats do not support setting of GCPs, even formats that can
2217 : * handle GCPs. These formats will return CE_Failure.
2218 : *
2219 : * @since GDAL 3.0
2220 : *
2221 : * @param nGCPCount number of GCPs being assigned.
2222 : *
2223 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2224 : *
2225 : * @param poGCP_SRS the new coordinate reference system to assign for the
2226 : * GCP output coordinates. This parameter should be null if no output
2227 : * coordinate system is known.
2228 : *
2229 : * @return CE_None on success, CE_Failure on failure (including if action is
2230 : * not supported for this format).
2231 : */
2232 :
2233 1 : CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,
2234 : CPL_UNUSED const GDAL_GCP *pasGCPList,
2235 : CPL_UNUSED const OGRSpatialReference *poGCP_SRS)
2236 :
2237 : {
2238 1 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
2239 1 : ReportError(CE_Failure, CPLE_NotSupported,
2240 : "Dataset does not support the SetGCPs() method.");
2241 :
2242 1 : return CE_Failure;
2243 : }
2244 :
2245 : /************************************************************************/
2246 : /* GDALSetGCPs() */
2247 : /************************************************************************/
2248 :
2249 : /**
2250 : * \brief Assign GCPs.
2251 : *
2252 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
2253 : */
2254 :
2255 29 : CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,
2256 : const GDAL_GCP *pasGCPList,
2257 : const char *pszGCPProjection)
2258 :
2259 : {
2260 29 : VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
2261 :
2262 29 : return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,
2263 29 : pszGCPProjection);
2264 : }
2265 :
2266 : /************************************************************************/
2267 : /* GDALSetGCPs2() */
2268 : /************************************************************************/
2269 :
2270 : /**
2271 : * \brief Assign GCPs.
2272 : *
2273 : * @since GDAL 3.0
2274 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
2275 : */
2276 :
2277 9 : CPLErr GDALSetGCPs2(GDALDatasetH hDS, int nGCPCount, const GDAL_GCP *pasGCPList,
2278 : OGRSpatialReferenceH hSRS)
2279 :
2280 : {
2281 9 : VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
2282 :
2283 18 : return GDALDataset::FromHandle(hDS)->SetGCPs(
2284 9 : nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
2285 : }
2286 :
2287 : /************************************************************************/
2288 : /* BuildOverviews() */
2289 : /************************************************************************/
2290 :
2291 : /**
2292 : * \brief Build raster overview(s)
2293 : *
2294 : * If the operation is not supported for the indicated dataset, then
2295 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
2296 : * CPLE_NotSupported.
2297 : *
2298 : * Depending on the actual file format, all overviews level can be also
2299 : * deleted by specifying nOverviews == 0. This works at least for external
2300 : * overviews (.ovr), TIFF internal overviews, etc.
2301 : *
2302 : * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
2303 : * to "ALL_CPUS" or a integer value to specify the number of threads to use for
2304 : * overview computation.
2305 : *
2306 : * This method is the same as the C function GDALBuildOverviewsEx().
2307 : *
2308 : * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
2309 : * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
2310 : * or "NONE" controlling the downsampling method applied.
2311 : * @param nOverviews number of overviews to build, or 0 to clean overviews.
2312 : * @param panOverviewList the list of overview decimation factors (positive
2313 : * integers, normally larger or equal to 2) to build, or
2314 : * NULL if nOverviews == 0.
2315 : * @param nListBands number of bands to build overviews for in panBandList.
2316 : * Build for all bands if this is 0.
2317 : * @param panBandList list of band numbers.
2318 : * @param pfnProgress a function to call to report progress, or NULL.
2319 : * @param pProgressData application data to pass to the progress function.
2320 : * @param papszOptions (GDAL >= 3.6) NULL terminated list of options as
2321 : * key=value pairs, or NULL.
2322 : * Possible keys are the ones returned by
2323 : * GetDriver()->GetMetadataItem(GDAL_DMD_OVERVIEW_CREATIONOPTIONLIST)
2324 : *
2325 : * @return CE_None on success or CE_Failure if the operation doesn't work.
2326 : *
2327 : * For example, to build overview level 2, 4 and 8 on all bands the following
2328 : * call could be made:
2329 : * \code{.cpp}
2330 : * int anOverviewList[3] = { 2, 4, 8 };
2331 : *
2332 : * poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
2333 : * GDALDummyProgress, nullptr );
2334 : * \endcode
2335 : *
2336 : * @see GDALRegenerateOverviewsEx()
2337 : */
2338 :
2339 743 : CPLErr GDALDataset::BuildOverviews(const char *pszResampling, int nOverviews,
2340 : const int *panOverviewList, int nListBands,
2341 : const int *panBandList,
2342 : GDALProgressFunc pfnProgress,
2343 : void *pProgressData,
2344 : CSLConstList papszOptions)
2345 : {
2346 743 : int *panAllBandList = nullptr;
2347 :
2348 1486 : CPLStringList aosOptions(papszOptions);
2349 743 : if (poDriver && !aosOptions.empty())
2350 : {
2351 : const char *pszOptionList =
2352 28 : poDriver->GetMetadataItem(GDAL_DMD_OVERVIEW_CREATIONOPTIONLIST);
2353 28 : if (pszOptionList)
2354 : {
2355 : // For backwards compatibility
2356 28 : if (const char *opt = aosOptions.FetchNameValue("USE_RRD"))
2357 : {
2358 4 : if (strstr(pszOptionList, "<Value>RRD</Value>") &&
2359 2 : aosOptions.FetchNameValue("LOCATION") == nullptr)
2360 : {
2361 2 : if (CPLTestBool(opt))
2362 2 : aosOptions.SetNameValue("LOCATION", "RRD");
2363 2 : aosOptions.SetNameValue("USE_RRD", nullptr);
2364 : }
2365 : }
2366 28 : if (const char *opt =
2367 28 : aosOptions.FetchNameValue("VRT_VIRTUAL_OVERVIEWS"))
2368 : {
2369 3 : if (strstr(pszOptionList, "VIRTUAL"))
2370 : {
2371 3 : aosOptions.SetNameValue("VIRTUAL", opt);
2372 3 : aosOptions.SetNameValue("VRT_VIRTUAL_OVERVIEWS", nullptr);
2373 : }
2374 : }
2375 :
2376 76 : for (const auto &[pszKey, pszValue] :
2377 104 : cpl::IterateNameValue(papszOptions))
2378 : {
2379 38 : if (cpl::ends_with(std::string_view(pszKey), "_OVERVIEW"))
2380 : {
2381 : aosOptions.SetNameValue(
2382 16 : std::string(pszKey)
2383 16 : .substr(0, strlen(pszKey) - strlen("_OVERVIEW"))
2384 : .c_str(),
2385 16 : pszValue);
2386 8 : aosOptions.SetNameValue(pszKey, nullptr);
2387 : }
2388 : }
2389 :
2390 56 : CPLString osDriver;
2391 28 : osDriver.Printf("driver %s", poDriver->GetDescription());
2392 28 : GDALValidateOptions(pszOptionList, aosOptions.List(),
2393 : "overview creation option", osDriver);
2394 : }
2395 : }
2396 :
2397 743 : if (nListBands == 0)
2398 : {
2399 731 : nListBands = GetRasterCount();
2400 : panAllBandList =
2401 731 : static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
2402 67454 : for (int i = 0; i < nListBands; ++i)
2403 66723 : panAllBandList[i] = i + 1;
2404 :
2405 731 : panBandList = panAllBandList;
2406 : }
2407 :
2408 743 : if (pfnProgress == nullptr)
2409 708 : pfnProgress = GDALDummyProgress;
2410 :
2411 1817 : for (int i = 0; i < nOverviews; ++i)
2412 : {
2413 1075 : if (panOverviewList[i] <= 0)
2414 : {
2415 1 : CPLError(CE_Failure, CPLE_IllegalArg,
2416 : "panOverviewList[%d] = %d is invalid. It must be a "
2417 : "positive value",
2418 1 : i, panOverviewList[i]);
2419 1 : CPLFree(panAllBandList);
2420 1 : return CE_Failure;
2421 : }
2422 : }
2423 :
2424 742 : const CPLErr eErr = IBuildOverviews(
2425 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2426 742 : pfnProgress, pProgressData, aosOptions.List());
2427 :
2428 742 : if (panAllBandList != nullptr)
2429 729 : CPLFree(panAllBandList);
2430 :
2431 742 : return eErr;
2432 : }
2433 :
2434 : /************************************************************************/
2435 : /* GDALBuildOverviews() */
2436 : /************************************************************************/
2437 :
2438 : /**
2439 : * \brief Build raster overview(s)
2440 : *
2441 : * @see GDALDataset::BuildOverviews() and GDALBuildOverviews()
2442 : */
2443 :
2444 27 : CPLErr CPL_STDCALL GDALBuildOverviews(GDALDatasetH hDataset,
2445 : const char *pszResampling, int nOverviews,
2446 : const int *panOverviewList,
2447 : int nListBands, const int *panBandList,
2448 : GDALProgressFunc pfnProgress,
2449 : void *pProgressData)
2450 :
2451 : {
2452 27 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2453 :
2454 27 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2455 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2456 27 : pfnProgress, pProgressData, nullptr);
2457 : }
2458 :
2459 : /************************************************************************/
2460 : /* GDALBuildOverviews() */
2461 : /************************************************************************/
2462 :
2463 : /**
2464 : * \brief Build raster overview(s)
2465 : *
2466 : * @see GDALDataset::BuildOverviews()
2467 : * @since GDAL 3.6
2468 : */
2469 :
2470 : CPLErr CPL_STDCALL
2471 695 : GDALBuildOverviewsEx(GDALDatasetH hDataset, const char *pszResampling,
2472 : int nOverviews, const int *panOverviewList, int nListBands,
2473 : const int *panBandList, GDALProgressFunc pfnProgress,
2474 : void *pProgressData, CSLConstList papszOptions)
2475 :
2476 : {
2477 695 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2478 :
2479 695 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2480 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2481 695 : pfnProgress, pProgressData, papszOptions);
2482 : }
2483 :
2484 : /************************************************************************/
2485 : /* IBuildOverviews() */
2486 : /* */
2487 : /* Default implementation. */
2488 : /************************************************************************/
2489 :
2490 : //! @cond Doxygen_Suppress
2491 196 : CPLErr GDALDataset::IBuildOverviews(const char *pszResampling, int nOverviews,
2492 : const int *panOverviewList, int nListBands,
2493 : const int *panBandList,
2494 : GDALProgressFunc pfnProgress,
2495 : void *pProgressData,
2496 : CSLConstList papszOptions)
2497 :
2498 : {
2499 196 : if (oOvManager.IsInitialized())
2500 195 : return oOvManager.BuildOverviews(
2501 : nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2502 195 : panBandList, pfnProgress, pProgressData, papszOptions);
2503 : else
2504 : {
2505 1 : ReportError(CE_Failure, CPLE_NotSupported,
2506 : "BuildOverviews() not supported for this dataset.");
2507 :
2508 1 : return CE_Failure;
2509 : }
2510 : }
2511 :
2512 : //! @endcond
2513 :
2514 : /************************************************************************/
2515 : /* AddOverviews() */
2516 : /* */
2517 : /* Default implementation. */
2518 : /************************************************************************/
2519 :
2520 : /**
2521 : * \brief Add overview from existing dataset(s)
2522 : *
2523 : * This function creates new overview levels or refresh existing one from
2524 : * the list of provided overview datasets.
2525 : * Source overviews may come from any GDAL supported format, provided they
2526 : * have the same number of bands and geospatial extent than the target
2527 : * dataset.
2528 : *
2529 : * If the operation is not supported for the indicated dataset, then
2530 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
2531 : * CPLE_NotSupported.
2532 : *
2533 : * At time of writing, this method is only implemented for internal overviews
2534 : * of GeoTIFF datasets and external overviews in GeoTIFF format.
2535 : *
2536 : * @param apoSrcOvrDS Vector of source overviews.
2537 : * @param pfnProgress a function to call to report progress, or NULL.
2538 : * @param pProgressData application data to pass to the progress function.
2539 : * @param papszOptions NULL terminated list of options as
2540 : * key=value pairs, or NULL. Possible keys are the
2541 : * ones returned by
2542 : * GetDriver()->GetMetadataItem(GDAL_DMD_OVERVIEW_CREATIONOPTIONLIST)
2543 : *
2544 : * @return CE_None on success or CE_Failure if the operation doesn't work.
2545 : * @since 3.12
2546 : */
2547 5 : CPLErr GDALDataset::AddOverviews(const std::vector<GDALDataset *> &apoSrcOvrDS,
2548 : GDALProgressFunc pfnProgress,
2549 : void *pProgressData, CSLConstList papszOptions)
2550 : {
2551 5 : if (oOvManager.IsInitialized())
2552 : {
2553 4 : return oOvManager.AddOverviews(nullptr, apoSrcOvrDS, pfnProgress,
2554 4 : pProgressData, papszOptions);
2555 : }
2556 : else
2557 : {
2558 1 : ReportError(CE_Failure, CPLE_NotSupported,
2559 : "AddOverviews() not supported for this dataset.");
2560 1 : return CE_Failure;
2561 : }
2562 : }
2563 :
2564 : /************************************************************************/
2565 : /* IRasterIO() */
2566 : /* */
2567 : /* The default implementation of IRasterIO() is, in the general */
2568 : /* case to pass the request off to each band objects rasterio */
2569 : /* methods with appropriate arguments. In some cases, it might */
2570 : /* choose instead the BlockBasedRasterIO() implementation. */
2571 : /************************************************************************/
2572 :
2573 : //! @cond Doxygen_Suppress
2574 443563 : CPLErr GDALDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2575 : int nXSize, int nYSize, void *pData,
2576 : int nBufXSize, int nBufYSize,
2577 : GDALDataType eBufType, int nBandCount,
2578 : BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,
2579 : GSpacing nLineSpace, GSpacing nBandSpace,
2580 : GDALRasterIOExtraArg *psExtraArg)
2581 :
2582 : {
2583 443563 : const char *pszInterleave = nullptr;
2584 :
2585 443563 : CPLAssert(nullptr != pData);
2586 :
2587 443563 : const bool bHasSubpixelShift =
2588 445787 : psExtraArg->bFloatingPointWindowValidity &&
2589 444333 : psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2590 770 : (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2591 :
2592 443449 : if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&
2593 70260 : nBandCount > 1 &&
2594 70259 : (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2595 887013 : nullptr &&
2596 67189 : EQUAL(pszInterleave, "PIXEL"))
2597 : {
2598 63970 : return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2599 : nBufXSize, nBufYSize, eBufType, nBandCount,
2600 : panBandMap, nPixelSpace, nLineSpace,
2601 63967 : nBandSpace, psExtraArg);
2602 : }
2603 :
2604 379597 : if (eRWFlag == GF_Read &&
2605 200131 : (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2606 199368 : psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2607 199366 : psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2608 200131 : psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2609 927 : !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)
2610 : {
2611 904 : if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())
2612 : {
2613 698 : int bTried = FALSE;
2614 698 : const CPLErr eErr = TryOverviewRasterIO(
2615 : eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
2616 : nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
2617 : nLineSpace, nBandSpace, psExtraArg, &bTried);
2618 698 : if (bTried)
2619 1 : return eErr;
2620 : }
2621 :
2622 903 : GDALDataType eFirstBandDT = GDT_Unknown;
2623 903 : int nFirstMaskFlags = 0;
2624 903 : GDALRasterBand *poFirstMaskBand = nullptr;
2625 903 : int nOKBands = 0;
2626 :
2627 : // Check if bands share the same mask band
2628 2824 : for (int i = 0; i < nBandCount; ++i)
2629 : {
2630 2558 : GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2631 4449 : if ((nBufXSize < nXSize || nBufYSize < nYSize) &&
2632 1894 : poBand->GetOverviewCount())
2633 : {
2634 : // Could be improved to select the appropriate overview.
2635 3 : break;
2636 : }
2637 2552 : if (poBand->GetColorTable() != nullptr)
2638 : {
2639 0 : break;
2640 : }
2641 2554 : const GDALDataType eDT = poBand->GetRasterDataType();
2642 2551 : if (GDALDataTypeIsComplex(eDT))
2643 : {
2644 30 : break;
2645 : }
2646 2521 : if (i == 0)
2647 : {
2648 870 : eFirstBandDT = eDT;
2649 870 : nFirstMaskFlags = poBand->GetMaskFlags();
2650 873 : if (nFirstMaskFlags == GMF_NODATA)
2651 : {
2652 : // The dataset-level resampling code is not ready for nodata
2653 : // Fallback to band-level resampling
2654 10 : break;
2655 : }
2656 863 : poFirstMaskBand = poBand->GetMaskBand();
2657 : }
2658 : else
2659 : {
2660 1651 : if (eDT != eFirstBandDT)
2661 : {
2662 0 : break;
2663 : }
2664 1651 : int nMaskFlags = poBand->GetMaskFlags();
2665 1655 : if (nMaskFlags == GMF_NODATA)
2666 : {
2667 : // The dataset-level resampling code is not ready for nodata
2668 : // Fallback to band-level resampling
2669 0 : break;
2670 : }
2671 1655 : GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2672 1656 : if (nFirstMaskFlags == GMF_ALL_VALID &&
2673 : nMaskFlags == GMF_ALL_VALID)
2674 : {
2675 : // Ok.
2676 : }
2677 1015 : else if (poFirstMaskBand == poMaskBand)
2678 : {
2679 : // Ok.
2680 : }
2681 : else
2682 : {
2683 596 : break;
2684 : }
2685 : }
2686 :
2687 1921 : ++nOKBands;
2688 : }
2689 :
2690 905 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2691 905 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2692 :
2693 905 : CPLErr eErr = CE_None;
2694 905 : if (nOKBands > 0)
2695 : {
2696 864 : if (nOKBands < nBandCount)
2697 : {
2698 596 : psExtraArg->pfnProgress = GDALScaledProgress;
2699 1192 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2700 596 : 0.0, static_cast<double>(nOKBands) / nBandCount,
2701 : pfnProgressGlobal, pProgressDataGlobal);
2702 596 : if (psExtraArg->pProgressData == nullptr)
2703 207 : psExtraArg->pfnProgress = nullptr;
2704 : }
2705 :
2706 864 : eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2707 : pData, nBufXSize, nBufYSize, eBufType,
2708 : nOKBands, panBandMap, nPixelSpace,
2709 : nLineSpace, nBandSpace, psExtraArg);
2710 :
2711 865 : if (nOKBands < nBandCount)
2712 : {
2713 596 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2714 : }
2715 : }
2716 906 : if (eErr == CE_None && nOKBands < nBandCount)
2717 : {
2718 636 : if (nOKBands > 0)
2719 : {
2720 593 : psExtraArg->pfnProgress = GDALScaledProgress;
2721 1186 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2722 593 : static_cast<double>(nOKBands) / nBandCount, 1.0,
2723 : pfnProgressGlobal, pProgressDataGlobal);
2724 593 : if (psExtraArg->pProgressData == nullptr)
2725 204 : psExtraArg->pfnProgress = nullptr;
2726 : }
2727 1272 : eErr = BandBasedRasterIO(
2728 : eRWFlag, nXOff, nYOff, nXSize, nYSize,
2729 636 : static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,
2730 : nBufYSize, eBufType, nBandCount - nOKBands,
2731 636 : panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,
2732 : psExtraArg);
2733 636 : if (nOKBands > 0)
2734 : {
2735 593 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2736 : }
2737 : }
2738 :
2739 908 : psExtraArg->pfnProgress = pfnProgressGlobal;
2740 908 : psExtraArg->pProgressData = pProgressDataGlobal;
2741 :
2742 908 : return eErr;
2743 : }
2744 :
2745 378693 : return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2746 : nBufXSize, nBufYSize, eBufType, nBandCount,
2747 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2748 378690 : psExtraArg);
2749 : }
2750 :
2751 : //! @endcond
2752 :
2753 : /************************************************************************/
2754 : /* BandBasedRasterIO() */
2755 : /* */
2756 : /* Pass the request off to each band objects rasterio methods with */
2757 : /* appropriate arguments. */
2758 : /************************************************************************/
2759 :
2760 : //! @cond Doxygen_Suppress
2761 645477 : CPLErr GDALDataset::BandBasedRasterIO(
2762 : GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
2763 : void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
2764 : int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
2765 : GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
2766 :
2767 : {
2768 : int iBandIndex;
2769 645477 : CPLErr eErr = CE_None;
2770 :
2771 645477 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2772 645477 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2773 :
2774 1664700 : for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
2775 : ++iBandIndex)
2776 : {
2777 1019210 : GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2778 :
2779 1019210 : if (poBand == nullptr)
2780 : {
2781 0 : eErr = CE_Failure;
2782 0 : break;
2783 : }
2784 :
2785 1019210 : GByte *pabyBandData =
2786 1019210 : static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2787 :
2788 1019210 : if (nBandCount > 1)
2789 : {
2790 551230 : psExtraArg->pfnProgress = GDALScaledProgress;
2791 1102460 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2792 : 1.0 * iBandIndex / nBandCount,
2793 551230 : 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2794 : pProgressDataGlobal);
2795 551232 : if (psExtraArg->pProgressData == nullptr)
2796 548268 : psExtraArg->pfnProgress = nullptr;
2797 : }
2798 :
2799 2038440 : eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2800 : pabyBandData, nBufXSize, nBufYSize, eBufType,
2801 1019220 : nPixelSpace, nLineSpace, psExtraArg);
2802 :
2803 1019220 : if (nBandCount > 1)
2804 551244 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2805 : }
2806 :
2807 645488 : psExtraArg->pfnProgress = pfnProgressGlobal;
2808 645488 : psExtraArg->pProgressData = pProgressDataGlobal;
2809 :
2810 645488 : return eErr;
2811 : }
2812 :
2813 : //! @endcond
2814 :
2815 : /************************************************************************/
2816 : /* ValidateRasterIOOrAdviseReadParameters() */
2817 : /************************************************************************/
2818 :
2819 : //! @cond Doxygen_Suppress
2820 743025 : CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
2821 : const char *pszCallingFunc, int *pbStopProcessingOnCENone, int nXOff,
2822 : int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize,
2823 : int nBandCount, const int *panBandMap)
2824 : {
2825 :
2826 : /* -------------------------------------------------------------------- */
2827 : /* Some size values are "noop". Lets just return to avoid */
2828 : /* stressing lower level functions. */
2829 : /* -------------------------------------------------------------------- */
2830 743025 : if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)
2831 : {
2832 25 : CPLDebug("GDAL",
2833 : "%s skipped for odd window or buffer size.\n"
2834 : " Window = (%d,%d)x%dx%d\n"
2835 : " Buffer = %dx%d",
2836 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2837 : nBufYSize);
2838 :
2839 24 : *pbStopProcessingOnCENone = TRUE;
2840 24 : return CE_None;
2841 : }
2842 :
2843 743000 : CPLErr eErr = CE_None;
2844 743000 : *pbStopProcessingOnCENone = FALSE;
2845 :
2846 743000 : if (nXOff < 0 || nXOff > INT_MAX - nXSize ||
2847 742992 : nXOff + nXSize > nRasterXSize || nYOff < 0 ||
2848 742992 : nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)
2849 : {
2850 10 : ReportError(CE_Failure, CPLE_IllegalArg,
2851 : "Access window out of range in %s. Requested "
2852 : "(%d,%d) of size %dx%d on raster of %dx%d.",
2853 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
2854 : nRasterYSize);
2855 2 : eErr = CE_Failure;
2856 : }
2857 :
2858 742992 : if (panBandMap == nullptr && nBandCount > GetRasterCount())
2859 : {
2860 0 : ReportError(CE_Failure, CPLE_IllegalArg,
2861 : "%s: nBandCount cannot be greater than %d", pszCallingFunc,
2862 : GetRasterCount());
2863 1 : eErr = CE_Failure;
2864 : }
2865 :
2866 2221500 : for (int i = 0; i < nBandCount && eErr == CE_None; ++i)
2867 : {
2868 1478500 : int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2869 1478500 : if (iBand < 1 || iBand > GetRasterCount())
2870 : {
2871 3 : ReportError(
2872 : CE_Failure, CPLE_IllegalArg,
2873 : "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
2874 : pszCallingFunc, i, iBand);
2875 3 : eErr = CE_Failure;
2876 : }
2877 :
2878 1478500 : if (eErr == CE_None && GetRasterBand(iBand) == nullptr)
2879 : {
2880 0 : ReportError(
2881 : CE_Failure, CPLE_IllegalArg,
2882 : "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
2883 : pszCallingFunc, i, iBand);
2884 0 : eErr = CE_Failure;
2885 : }
2886 : }
2887 :
2888 743002 : return eErr;
2889 : }
2890 :
2891 : //! @endcond
2892 :
2893 : /************************************************************************/
2894 : /* RasterIO() */
2895 : /************************************************************************/
2896 :
2897 : /**
2898 : * \brief Read/write a region of image data from multiple bands.
2899 : *
2900 : * This method allows reading a region of one or more GDALRasterBands from
2901 : * this dataset into a buffer, or writing data from a buffer into a region
2902 : * of the GDALRasterBands. It automatically takes care of data type
2903 : * translation if the data type (eBufType) of the buffer is different than
2904 : * that of the GDALRasterBand.
2905 : * The method also takes care of image decimation / replication if the
2906 : * buffer size (nBufXSize x nBufYSize) is different than the size of the
2907 : * region being accessed (nXSize x nYSize).
2908 : *
2909 : * The window of interest expressed by (nXOff, nYOff, nXSize, nYSize) should be
2910 : * fully within the raster space, that is nXOff >= 0, nYOff >= 0,
2911 : * nXOff + nXSize <= GetRasterXSize() and nYOff + nYSize <= GetRasterYSize().
2912 : * If reads larger than the raster space are wished, GDALTranslate() might be used.
2913 : * Or use nLineSpace and a possibly shifted pData value.
2914 : *
2915 : * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
2916 : * writing from various organization of buffers.
2917 : *
2918 : * Some formats may efficiently implement decimation into a buffer by
2919 : * reading from lower resolution overview images. The logic of the default
2920 : * implementation in the base class GDALRasterBand is the following one. It
2921 : * computes a target_downscaling_factor from the window of interest and buffer
2922 : * size which is min(nXSize/nBufXSize, nYSize/nBufYSize).
2923 : * It then walks through overviews and will select the first one whose
2924 : * downscaling factor is greater than target_downscaling_factor / 1.2.
2925 : *
2926 : * Let's assume we have overviews at downscaling factors 2, 4 and 8.
2927 : * The relationship between target_downscaling_factor and the select overview
2928 : * level is the following one:
2929 : *
2930 : * target_downscaling_factor | selected_overview
2931 : * ------------------------- | -----------------
2932 : * ]0, 2 / 1.2] | full resolution band
2933 : * ]2 / 1.2, 4 / 1.2] | 2x downsampled band
2934 : * ]4 / 1.2, 8 / 1.2] | 4x downsampled band
2935 : * ]8 / 1.2, infinity[ | 8x downsampled band
2936 : *
2937 : * Note that starting with GDAL 3.9, this 1.2 oversampling factor can be
2938 : * modified by setting the GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD configuration
2939 : * option. Also note that starting with GDAL 3.9, when the resampling algorithm
2940 : * specified in psExtraArg->eResampleAlg is different from GRIORA_NearestNeighbour,
2941 : * this oversampling threshold defaults to 1. Consequently if there are overviews
2942 : * of downscaling factor 2, 4 and 8, and the desired downscaling factor is
2943 : * 7.99, the overview of factor 4 will be selected for a non nearest resampling.
2944 : *
2945 : * For highest performance full resolution data access, read and write
2946 : * on "block boundaries" as returned by GetBlockSize(), or use the
2947 : * ReadBlock() and WriteBlock() methods.
2948 : *
2949 : * This method is the same as the C GDALDatasetRasterIO() or
2950 : * GDALDatasetRasterIOEx() functions.
2951 : *
2952 : * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
2953 : * write a region of data.
2954 : *
2955 : * @param nXOff The pixel offset to the top left corner of the region
2956 : * of the band to be accessed. This would be zero to start from the left side.
2957 : *
2958 : * @param nYOff The line offset to the top left corner of the region
2959 : * of the band to be accessed. This would be zero to start from the top.
2960 : *
2961 : * @param nXSize The width of the region of the band to be accessed in pixels.
2962 : *
2963 : * @param nYSize The height of the region of the band to be accessed in lines.
2964 : *
2965 : * @param pData The buffer into which the data should be read, or from which
2966 : * it should be written. This buffer must contain at least
2967 : * nBufXSize * nBufYSize * nBandCount words of type eBufType. It is organized
2968 : * in left to right,top to bottom pixel order. Spacing is controlled by the
2969 : * nPixelSpace, and nLineSpace parameters.
2970 : * Note that even with eRWFlag==GF_Write, the content of the buffer might be
2971 : * temporarily modified during the execution of this method (and eventually
2972 : * restored back to its original content), so it is not safe to use a buffer
2973 : * stored in a read-only section of the calling program.
2974 : *
2975 : * @param nBufXSize the width of the buffer image into which the desired region
2976 : * is to be read, or from which it is to be written.
2977 : *
2978 : * @param nBufYSize the height of the buffer image into which the desired
2979 : * region is to be read, or from which it is to be written.
2980 : *
2981 : * @param eBufType the type of the pixel values in the pData data buffer. The
2982 : * pixel values will automatically be translated to/from the GDALRasterBand
2983 : * data type as needed. Most driver implementations will use GDALCopyWords64()
2984 : * to perform data type translation.
2985 : *
2986 : * @param nBandCount the number of bands being read or written.
2987 : *
2988 : * @param panBandMap the list of nBandCount band numbers being read/written.
2989 : * Note band numbers are 1 based. This may be NULL to select the first
2990 : * nBandCount bands. (Note: before GDAL 3.10, argument type was "int*", and
2991 : * not "const int*")
2992 : *
2993 : * @param nPixelSpace The byte offset from the start of one pixel value in
2994 : * pData to the start of the next pixel value within a scanline. If defaulted
2995 : * (0) the size of the datatype eBufType is used.
2996 : *
2997 : * @param nLineSpace The byte offset from the start of one scanline in
2998 : * pData to the start of the next. If defaulted (0) the size of the datatype
2999 : * eBufType * nBufXSize is used.
3000 : *
3001 : * @param nBandSpace the byte offset from the start of one bands data to the
3002 : * start of the next. If defaulted (0) the value will be
3003 : * nLineSpace * nBufYSize implying band sequential organization
3004 : * of the data buffer.
3005 : *
3006 : * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
3007 : * structure with additional arguments to specify resampling and progress
3008 : * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
3009 : * configuration option can also be defined to override the default resampling
3010 : * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
3011 : *
3012 : * @return CE_Failure if the access fails, otherwise CE_None.
3013 : */
3014 :
3015 728141 : CPLErr GDALDataset::RasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
3016 : int nXSize, int nYSize, void *pData, int nBufXSize,
3017 : int nBufYSize, GDALDataType eBufType,
3018 : int nBandCount, const int *panBandMap,
3019 : GSpacing nPixelSpace, GSpacing nLineSpace,
3020 : GSpacing nBandSpace,
3021 : GDALRasterIOExtraArg *psExtraArg)
3022 :
3023 : {
3024 : GDALRasterIOExtraArg sExtraArg;
3025 728141 : if (psExtraArg == nullptr)
3026 : {
3027 535766 : INIT_RASTERIO_EXTRA_ARG(sExtraArg);
3028 :
3029 : // 4 below inits are not strictly needed but make Coverity Scan
3030 : // happy
3031 535766 : sExtraArg.dfXOff = nXOff;
3032 535766 : sExtraArg.dfYOff = nYOff;
3033 535766 : sExtraArg.dfXSize = nXSize;
3034 535766 : sExtraArg.dfYSize = nYSize;
3035 :
3036 535766 : psExtraArg = &sExtraArg;
3037 : }
3038 192375 : else if (CPL_UNLIKELY(psExtraArg->nVersion >
3039 : RASTERIO_EXTRA_ARG_CURRENT_VERSION))
3040 : {
3041 0 : ReportError(CE_Failure, CPLE_AppDefined,
3042 : "Unhandled version of GDALRasterIOExtraArg");
3043 0 : return CE_Failure;
3044 : }
3045 :
3046 728141 : GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
3047 : nBufYSize);
3048 :
3049 728136 : if (CPL_UNLIKELY(nullptr == pData))
3050 : {
3051 0 : ReportError(CE_Failure, CPLE_AppDefined,
3052 : "The buffer into which the data should be read is null");
3053 0 : return CE_Failure;
3054 : }
3055 :
3056 : /* -------------------------------------------------------------------- */
3057 : /* Do some validation of parameters. */
3058 : /* -------------------------------------------------------------------- */
3059 :
3060 728136 : if (CPL_UNLIKELY(eRWFlag != GF_Read && eRWFlag != GF_Write))
3061 : {
3062 0 : ReportError(
3063 : CE_Failure, CPLE_IllegalArg,
3064 : "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
3065 : eRWFlag);
3066 0 : return CE_Failure;
3067 : }
3068 :
3069 728136 : if (eRWFlag == GF_Write)
3070 : {
3071 216336 : if (CPL_UNLIKELY(eAccess != GA_Update))
3072 : {
3073 2 : ReportError(CE_Failure, CPLE_AppDefined,
3074 : "Write operation not permitted on dataset opened "
3075 : "in read-only mode");
3076 2 : return CE_Failure;
3077 : }
3078 : }
3079 :
3080 728134 : int bStopProcessing = FALSE;
3081 728134 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3082 : "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
3083 : nBufYSize, nBandCount, panBandMap);
3084 728137 : if (eErr != CE_None || bStopProcessing)
3085 16 : return eErr;
3086 728121 : if (CPL_UNLIKELY(eBufType == GDT_Unknown || eBufType == GDT_TypeCount))
3087 : {
3088 2 : ReportError(CE_Failure, CPLE_AppDefined,
3089 : "Illegal GDT_Unknown/GDT_TypeCount argument");
3090 2 : return CE_Failure;
3091 : }
3092 :
3093 : /* -------------------------------------------------------------------- */
3094 : /* If pixel and line spacing are defaulted assign reasonable */
3095 : /* value assuming a packed buffer. */
3096 : /* -------------------------------------------------------------------- */
3097 728119 : if (nPixelSpace == 0)
3098 423691 : nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
3099 :
3100 728113 : if (nLineSpace == 0)
3101 : {
3102 480506 : nLineSpace = nPixelSpace * nBufXSize;
3103 : }
3104 :
3105 728113 : if (nBandSpace == 0 && nBandCount > 1)
3106 : {
3107 66776 : nBandSpace = nLineSpace * nBufYSize;
3108 : }
3109 :
3110 728113 : if (panBandMap == nullptr)
3111 : {
3112 352834 : if (!m_poPrivate)
3113 0 : return CE_Failure;
3114 352834 : CPLAssert(static_cast<int>(m_poPrivate->m_anBandMap.size()) == nBands);
3115 352833 : panBandMap = m_poPrivate->m_anBandMap.data();
3116 : }
3117 :
3118 728111 : int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
3119 :
3120 : /* -------------------------------------------------------------------- */
3121 : /* We are being forced to use cached IO instead of a driver */
3122 : /* specific implementation. */
3123 : /* -------------------------------------------------------------------- */
3124 728127 : if (bForceCachedIO)
3125 : {
3126 18 : eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3127 : nBufXSize, nBufYSize, eBufType, nBandCount,
3128 : panBandMap, nPixelSpace, nLineSpace,
3129 18 : nBandSpace, psExtraArg);
3130 : }
3131 :
3132 : /* -------------------------------------------------------------------- */
3133 : /* Call the format specific function. */
3134 : /* -------------------------------------------------------------------- */
3135 : else
3136 : {
3137 728106 : eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3138 : nBufXSize, nBufYSize, eBufType, nBandCount,
3139 : // TODO: remove this const_cast once IRasterIO()
3140 : // takes a const int*
3141 : const_cast<int *>(panBandMap), nPixelSpace, nLineSpace,
3142 728109 : nBandSpace, psExtraArg);
3143 : }
3144 :
3145 728124 : if (bCallLeaveReadWrite)
3146 407503 : LeaveReadWrite();
3147 :
3148 728127 : return eErr;
3149 : }
3150 :
3151 : /************************************************************************/
3152 : /* GDALDatasetRasterIO() */
3153 : /************************************************************************/
3154 :
3155 : /**
3156 : * \brief Read/write a region of image data from multiple bands.
3157 : *
3158 : * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
3159 : * resolution, progress callback, etc. are needed)
3160 : *
3161 : * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
3162 : *
3163 : * @see GDALDataset::RasterIO()
3164 : */
3165 :
3166 4762 : CPLErr CPL_STDCALL GDALDatasetRasterIO(GDALDatasetH hDS, GDALRWFlag eRWFlag,
3167 : int nXOff, int nYOff, int nXSize,
3168 : int nYSize, void *pData, int nBufXSize,
3169 : int nBufYSize, GDALDataType eBufType,
3170 : int nBandCount, const int *panBandMap,
3171 : int nPixelSpace, int nLineSpace,
3172 : int nBandSpace)
3173 :
3174 : {
3175 4762 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
3176 :
3177 4762 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
3178 :
3179 4762 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3180 : nBufXSize, nBufYSize, eBufType, nBandCount,
3181 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
3182 4762 : nullptr);
3183 : }
3184 :
3185 : /************************************************************************/
3186 : /* GDALDatasetRasterIOEx() */
3187 : /************************************************************************/
3188 :
3189 : /**
3190 : * \brief Read/write a region of image data from multiple bands.
3191 : *
3192 : * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
3193 : *
3194 : * @see GDALDataset::RasterIO()
3195 : * @since GDAL 2.0
3196 : */
3197 :
3198 353121 : CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
3199 : GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
3200 : int nYSize, void *pData, int nBufXSize, int nBufYSize,
3201 : GDALDataType eBufType, int nBandCount, const int *panBandMap,
3202 : GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
3203 : GDALRasterIOExtraArg *psExtraArg)
3204 :
3205 : {
3206 353121 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
3207 :
3208 353121 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
3209 :
3210 353121 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3211 : nBufXSize, nBufYSize, eBufType, nBandCount,
3212 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
3213 353121 : psExtraArg);
3214 : }
3215 :
3216 : /************************************************************************/
3217 : /* GetOpenDatasets() */
3218 : /************************************************************************/
3219 :
3220 : /**
3221 : * \brief Fetch all open GDAL dataset handles.
3222 : *
3223 : * This method is the same as the C function GDALGetOpenDatasets().
3224 : *
3225 : * NOTE: This method is not thread safe. The returned list may change
3226 : * at any time and it should not be freed.
3227 : *
3228 : * @param pnCount integer into which to place the count of dataset pointers
3229 : * being returned.
3230 : *
3231 : * @return a pointer to an array of dataset handles.
3232 : */
3233 :
3234 2257 : GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)
3235 :
3236 : {
3237 4514 : CPLMutexHolderD(&hDLMutex);
3238 :
3239 2257 : if (poAllDatasetMap == nullptr)
3240 : {
3241 2236 : *pnCount = 0;
3242 2236 : return nullptr;
3243 : }
3244 :
3245 21 : *pnCount = static_cast<int>(poAllDatasetMap->size());
3246 21 : ppDatasets = static_cast<GDALDataset **>(
3247 21 : CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
3248 21 : std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();
3249 562 : for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)
3250 541 : ppDatasets[i] = oIter->first;
3251 21 : return ppDatasets;
3252 : }
3253 :
3254 : /************************************************************************/
3255 : /* GDALGetOpenDatasets() */
3256 : /************************************************************************/
3257 :
3258 : /**
3259 : * \brief Fetch all open GDAL dataset handles.
3260 : *
3261 : * @see GDALDataset::GetOpenDatasets()
3262 : */
3263 :
3264 0 : void CPL_STDCALL GDALGetOpenDatasets(GDALDatasetH **ppahDSList, int *pnCount)
3265 :
3266 : {
3267 0 : VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
3268 0 : VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
3269 :
3270 0 : *ppahDSList =
3271 0 : reinterpret_cast<GDALDatasetH *>(GDALDataset::GetOpenDatasets(pnCount));
3272 : }
3273 :
3274 : /************************************************************************/
3275 : /* GDALCleanOpenDatasetsList() */
3276 : /************************************************************************/
3277 :
3278 : // Useful when called from the child of a fork(), to avoid closing
3279 : // the datasets of the parent at the child termination.
3280 0 : void GDALNullifyOpenDatasetsList()
3281 : {
3282 0 : poAllDatasetMap = nullptr;
3283 0 : phSharedDatasetSet = nullptr;
3284 0 : ppDatasets = nullptr;
3285 0 : hDLMutex = nullptr;
3286 0 : }
3287 :
3288 : /************************************************************************/
3289 : /* GDALGetAccess() */
3290 : /************************************************************************/
3291 :
3292 : /**
3293 : * \brief Return access flag
3294 : *
3295 : * @see GDALDataset::GetAccess()
3296 : */
3297 :
3298 0 : int CPL_STDCALL GDALGetAccess(GDALDatasetH hDS)
3299 : {
3300 0 : VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
3301 :
3302 0 : return GDALDataset::FromHandle(hDS)->GetAccess();
3303 : }
3304 :
3305 : /************************************************************************/
3306 : /* AdviseRead() */
3307 : /************************************************************************/
3308 :
3309 : /**
3310 : * \brief Advise driver of upcoming read requests.
3311 : *
3312 : * Some GDAL drivers operate more efficiently if they know in advance what
3313 : * set of upcoming read requests will be made. The AdviseRead() method allows
3314 : * an application to notify the driver of the region and bands of interest,
3315 : * and at what resolution the region will be read.
3316 : *
3317 : * Many drivers just ignore the AdviseRead() call, but it can dramatically
3318 : * accelerate access via some drivers.
3319 : *
3320 : * Depending on call paths, drivers might receive several calls to
3321 : * AdviseRead() with the same parameters.
3322 : *
3323 : * @param nXOff The pixel offset to the top left corner of the region
3324 : * of the band to be accessed. This would be zero to start from the left side.
3325 : *
3326 : * @param nYOff The line offset to the top left corner of the region
3327 : * of the band to be accessed. This would be zero to start from the top.
3328 : *
3329 : * @param nXSize The width of the region of the band to be accessed in pixels.
3330 : *
3331 : * @param nYSize The height of the region of the band to be accessed in lines.
3332 : *
3333 : * @param nBufXSize the width of the buffer image into which the desired region
3334 : * is to be read, or from which it is to be written.
3335 : *
3336 : * @param nBufYSize the height of the buffer image into which the desired
3337 : * region is to be read, or from which it is to be written.
3338 : *
3339 : * @param eBufType the type of the pixel values in the pData data buffer. The
3340 : * pixel values will automatically be translated to/from the GDALRasterBand
3341 : * data type as needed.
3342 : *
3343 : * @param nBandCount the number of bands being read or written.
3344 : *
3345 : * @param panBandMap the list of nBandCount band numbers being read/written.
3346 : * Note band numbers are 1 based. This may be NULL to select the first
3347 : * nBandCount bands.
3348 : *
3349 : * @param papszOptions a list of name=value strings with special control
3350 : * options. Normally this is NULL.
3351 : *
3352 : * @return CE_Failure if the request is invalid and CE_None if it works or
3353 : * is ignored.
3354 : */
3355 :
3356 14637 : CPLErr GDALDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
3357 : int nBufXSize, int nBufYSize,
3358 : GDALDataType eBufType, int nBandCount,
3359 : int *panBandMap, char **papszOptions)
3360 :
3361 : {
3362 : /* -------------------------------------------------------------------- */
3363 : /* Do some validation of parameters. */
3364 : /* -------------------------------------------------------------------- */
3365 14637 : int bStopProcessing = FALSE;
3366 14637 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3367 : "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
3368 : nBufXSize, nBufYSize, nBandCount, panBandMap);
3369 14637 : if (eErr != CE_None || bStopProcessing)
3370 20 : return eErr;
3371 :
3372 128240 : for (int iBand = 0; iBand < nBandCount; ++iBand)
3373 : {
3374 113623 : GDALRasterBand *poBand = nullptr;
3375 :
3376 113623 : if (panBandMap == nullptr)
3377 112276 : poBand = GetRasterBand(iBand + 1);
3378 : else
3379 1347 : poBand = GetRasterBand(panBandMap[iBand]);
3380 :
3381 113623 : if (poBand == nullptr)
3382 0 : return CE_Failure;
3383 :
3384 227246 : eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
3385 113623 : nBufYSize, eBufType, papszOptions);
3386 :
3387 113623 : if (eErr != CE_None)
3388 0 : return eErr;
3389 : }
3390 :
3391 14617 : return CE_None;
3392 : }
3393 :
3394 : /************************************************************************/
3395 : /* GDALDatasetAdviseRead() */
3396 : /************************************************************************/
3397 :
3398 : /**
3399 : * \brief Advise driver of upcoming read requests.
3400 : *
3401 : * @see GDALDataset::AdviseRead()
3402 : */
3403 1 : CPLErr CPL_STDCALL GDALDatasetAdviseRead(GDALDatasetH hDS, int nXOff, int nYOff,
3404 : int nXSize, int nYSize, int nBufXSize,
3405 : int nBufYSize, GDALDataType eDT,
3406 : int nBandCount, int *panBandMap,
3407 : CSLConstList papszOptions)
3408 :
3409 : {
3410 1 : VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
3411 :
3412 2 : return GDALDataset::FromHandle(hDS)->AdviseRead(
3413 : nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount,
3414 1 : panBandMap, const_cast<char **>(papszOptions));
3415 : }
3416 :
3417 : /************************************************************************/
3418 : /* GDALAntiRecursionStruct */
3419 : /************************************************************************/
3420 :
3421 : // Prevent infinite recursion.
3422 : struct GDALAntiRecursionStruct
3423 : {
3424 : struct DatasetContext
3425 : {
3426 : std::string osFilename;
3427 : int nOpenFlags;
3428 : std::string osAllowedDrivers;
3429 :
3430 80731 : DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,
3431 : const std::string &osAllowedDriversIn)
3432 80731 : : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),
3433 80731 : osAllowedDrivers(osAllowedDriversIn)
3434 : {
3435 80723 : }
3436 : };
3437 :
3438 : struct DatasetContextCompare
3439 : {
3440 947772 : bool operator()(const DatasetContext &lhs,
3441 : const DatasetContext &rhs) const
3442 : {
3443 2767230 : return lhs.osFilename < rhs.osFilename ||
3444 916404 : (lhs.osFilename == rhs.osFilename &&
3445 903130 : (lhs.nOpenFlags < rhs.nOpenFlags ||
3446 1805390 : (lhs.nOpenFlags == rhs.nOpenFlags &&
3447 1850510 : lhs.osAllowedDrivers < rhs.osAllowedDrivers)));
3448 : }
3449 : };
3450 :
3451 1322 : ~GDALAntiRecursionStruct()
3452 1322 : {
3453 1322 : CPLAssert(aosDatasetNamesWithFlags.empty());
3454 1322 : CPLAssert(nRecLevel == 0);
3455 1322 : CPLAssert(m_oMapDepth.empty());
3456 1322 : }
3457 :
3458 : std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
3459 : int nRecLevel = 0;
3460 : std::map<std::string, int> m_oMapDepth{};
3461 : };
3462 :
3463 : #ifdef _WIN32
3464 : // Currently thread_local and C++ objects don't work well with DLL on Windows
3465 : static void FreeAntiRecursionOpen(void *pData)
3466 : {
3467 : delete static_cast<GDALAntiRecursionStruct *>(pData);
3468 : }
3469 :
3470 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3471 : {
3472 : static GDALAntiRecursionStruct dummy;
3473 : int bMemoryErrorOccurred = false;
3474 : void *pData =
3475 : CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
3476 : if (bMemoryErrorOccurred)
3477 : {
3478 : return dummy;
3479 : }
3480 : if (pData == nullptr)
3481 : {
3482 : auto pAntiRecursion = new GDALAntiRecursionStruct();
3483 : CPLSetTLSWithFreeFuncEx(CTLS_GDALOPEN_ANTIRECURSION, pAntiRecursion,
3484 : FreeAntiRecursionOpen, &bMemoryErrorOccurred);
3485 : if (bMemoryErrorOccurred)
3486 : {
3487 : delete pAntiRecursion;
3488 : return dummy;
3489 : }
3490 : return *pAntiRecursion;
3491 : }
3492 : return *static_cast<GDALAntiRecursionStruct *>(pData);
3493 : }
3494 : #else
3495 : static thread_local GDALAntiRecursionStruct g_tls_antiRecursion;
3496 :
3497 340800 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3498 : {
3499 340800 : return g_tls_antiRecursion;
3500 : }
3501 : #endif
3502 :
3503 : //! @cond Doxygen_Suppress
3504 260068 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)
3505 260068 : : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),
3506 : m_osIdentifier(osIdentifier),
3507 260068 : m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3508 : {
3509 260068 : CPLAssert(!osIdentifier.empty());
3510 260068 : }
3511 :
3512 260068 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(
3513 260068 : const GDALAntiRecursionGuard &other, const std::string &osIdentifier)
3514 260068 : : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),
3515 260068 : m_osIdentifier(osIdentifier.empty()
3516 : ? osIdentifier
3517 26852 : : other.m_osIdentifier + osIdentifier),
3518 260068 : m_nDepth(m_osIdentifier.empty()
3519 260068 : ? 0
3520 286920 : : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3521 : {
3522 260068 : }
3523 :
3524 520136 : GDALAntiRecursionGuard::~GDALAntiRecursionGuard()
3525 : {
3526 520136 : if (!m_osIdentifier.empty())
3527 : {
3528 286920 : auto oIter = m_psAntiRecursionStruct->m_oMapDepth.find(m_osIdentifier);
3529 286920 : CPLAssert(oIter != m_psAntiRecursionStruct->m_oMapDepth.end());
3530 286920 : if (--(oIter->second) == 0)
3531 286649 : m_psAntiRecursionStruct->m_oMapDepth.erase(oIter);
3532 : }
3533 520136 : }
3534 :
3535 : //! @endcond
3536 :
3537 : /************************************************************************/
3538 : /* GetFileList() */
3539 : /************************************************************************/
3540 :
3541 : /**
3542 : * \brief Fetch files forming dataset.
3543 : *
3544 : * Returns a list of files believed to be part of this dataset. If it returns
3545 : * an empty list of files it means there is believed to be no local file
3546 : * system files associated with the dataset (for instance a virtual dataset).
3547 : * The returned file list is owned by the caller and should be deallocated
3548 : * with CSLDestroy().
3549 : *
3550 : * The returned filenames will normally be relative or absolute paths
3551 : * depending on the path used to originally open the dataset. The strings
3552 : * will be UTF-8 encoded.
3553 : *
3554 : * This method is the same as the C GDALGetFileList() function.
3555 : *
3556 : * @return NULL or a NULL terminated array of file names.
3557 : */
3558 :
3559 4741 : char **GDALDataset::GetFileList()
3560 :
3561 : {
3562 9482 : CPLString osMainFilename = GetDescription();
3563 : VSIStatBufL sStat;
3564 :
3565 4741 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3566 : GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,
3567 9481 : std::string());
3568 4741 : auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
3569 4741 : if (cpl::contains(aosDatasetList, datasetCtxt))
3570 0 : return nullptr;
3571 :
3572 : /* -------------------------------------------------------------------- */
3573 : /* Is the main filename even a real filesystem object? */
3574 : /* -------------------------------------------------------------------- */
3575 : int bMainFileReal =
3576 4741 : VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
3577 :
3578 : /* -------------------------------------------------------------------- */
3579 : /* Form new list. */
3580 : /* -------------------------------------------------------------------- */
3581 4741 : char **papszList = nullptr;
3582 :
3583 4741 : if (bMainFileReal)
3584 4674 : papszList = CSLAddString(papszList, osMainFilename);
3585 :
3586 4741 : if (sAntiRecursion.nRecLevel == 100)
3587 : {
3588 0 : CPLError(CE_Failure, CPLE_AppDefined,
3589 : "GetFileList() called with too many recursion levels");
3590 0 : return papszList;
3591 : }
3592 4741 : ++sAntiRecursion.nRecLevel;
3593 :
3594 : /* -------------------------------------------------------------------- */
3595 : /* Do we have a known overview file? */
3596 : /* -------------------------------------------------------------------- */
3597 4741 : if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
3598 : {
3599 60 : auto iter = aosDatasetList.insert(datasetCtxt).first;
3600 60 : char **papszOvrList = oOvManager.poODS->GetFileList();
3601 60 : papszList = CSLInsertStrings(papszList, -1, papszOvrList);
3602 60 : CSLDestroy(papszOvrList);
3603 60 : aosDatasetList.erase(iter);
3604 : }
3605 :
3606 : /* -------------------------------------------------------------------- */
3607 : /* Do we have a known mask file? */
3608 : /* -------------------------------------------------------------------- */
3609 4741 : if (oOvManager.HaveMaskFile())
3610 : {
3611 9 : auto iter = aosDatasetList.insert(std::move(datasetCtxt)).first;
3612 9 : for (const char *pszFile :
3613 18 : CPLStringList(oOvManager.poMaskDS->GetFileList()))
3614 : {
3615 9 : if (CSLFindString(papszList, pszFile) < 0)
3616 9 : papszList = CSLAddString(papszList, pszFile);
3617 : }
3618 9 : aosDatasetList.erase(iter);
3619 : }
3620 :
3621 4740 : --sAntiRecursion.nRecLevel;
3622 :
3623 4740 : return papszList;
3624 : }
3625 :
3626 : /************************************************************************/
3627 : /* GDALGetFileList() */
3628 : /************************************************************************/
3629 :
3630 : /**
3631 : * \brief Fetch files forming dataset.
3632 : *
3633 : * @see GDALDataset::GetFileList()
3634 : */
3635 :
3636 3942 : char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)
3637 :
3638 : {
3639 3942 : VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3640 :
3641 3942 : return GDALDataset::FromHandle(hDS)->GetFileList();
3642 : }
3643 :
3644 : /************************************************************************/
3645 : /* CreateMaskBand() */
3646 : /************************************************************************/
3647 :
3648 : /**
3649 : * \brief Adds a mask band to the dataset
3650 : *
3651 : * The default implementation of the CreateMaskBand() method is implemented
3652 : * based on similar rules to the .ovr handling implemented using the
3653 : * GDALDefaultOverviews object. A TIFF file with the extension .msk will
3654 : * be created with the same basename as the original file, and it will have
3655 : * one band.
3656 : * The mask images will be deflate compressed tiled images with the same
3657 : * block size as the original image if possible.
3658 : * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
3659 : * level, where xx matches the band number of a band of the main dataset. The
3660 : * value of those items will be the one of the nFlagsIn parameter.
3661 : *
3662 : * Note that if you got a mask band with a previous call to GetMaskBand(), it
3663 : * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
3664 : * again.
3665 : *
3666 : * @since GDAL 1.5.0
3667 : *
3668 : * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
3669 : * GMF_PER_DATASET will be always set, even if not explicitly
3670 : * specified.
3671 : * @return CE_None on success or CE_Failure on an error.
3672 : *
3673 : * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
3674 : * @see GDALRasterBand::CreateMaskBand()
3675 : *
3676 : */
3677 17 : CPLErr GDALDataset::CreateMaskBand(int nFlagsIn)
3678 :
3679 : {
3680 17 : if (oOvManager.IsInitialized())
3681 : {
3682 17 : CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
3683 17 : if (eErr != CE_None)
3684 0 : return eErr;
3685 :
3686 : // Invalidate existing raster band masks.
3687 45 : for (int i = 0; i < nBands; ++i)
3688 : {
3689 28 : GDALRasterBand *poBand = papoBands[i];
3690 28 : poBand->poMask.reset();
3691 : }
3692 :
3693 17 : return CE_None;
3694 : }
3695 :
3696 0 : ReportError(CE_Failure, CPLE_NotSupported,
3697 : "CreateMaskBand() not supported for this dataset.");
3698 :
3699 0 : return CE_Failure;
3700 : }
3701 :
3702 : /************************************************************************/
3703 : /* GDALCreateDatasetMaskBand() */
3704 : /************************************************************************/
3705 :
3706 : /**
3707 : * \brief Adds a mask band to the dataset
3708 : * @see GDALDataset::CreateMaskBand()
3709 : */
3710 92 : CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)
3711 :
3712 : {
3713 92 : VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3714 :
3715 92 : return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
3716 : }
3717 :
3718 : /************************************************************************/
3719 : /* GDALOpen() */
3720 : /************************************************************************/
3721 :
3722 : /**
3723 : * \brief Open a raster file as a GDALDataset.
3724 : *
3725 : * This function will try to open the passed file, or virtual dataset
3726 : * name by invoking the Open method of each registered GDALDriver in turn.
3727 : * The first successful open will result in a returned dataset. If all
3728 : * drivers fail then NULL is returned and an error is issued.
3729 : *
3730 : * Several recommendations :
3731 : * <ul>
3732 : * <li>If you open a dataset object with GA_Update access, it is not recommended
3733 : * to open a new dataset on the same underlying file.</li>
3734 : * <li>The returned dataset should only be accessed by one thread at a time. If
3735 : * you want to use it from different threads, you must add all necessary code
3736 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3737 : * as GeoTIFF, maintain internal state variables that are updated each time a
3738 : * new block is read, thus preventing concurrent use.) </li>
3739 : * </ul>
3740 : *
3741 : * For drivers supporting the VSI virtual file API, it is possible to open a
3742 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3743 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3744 : * server (see VSIInstallCurlFileHandler())
3745 : *
3746 : * \sa GDALOpenShared()
3747 : * \sa GDALOpenEx()
3748 : *
3749 : * @param pszFilename the name of the file to access. In the case of
3750 : * exotic drivers this may not refer to a physical file, but instead contain
3751 : * information for the driver on how to access a dataset. It should be in UTF-8
3752 : * encoding.
3753 : *
3754 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
3755 : * drivers support only read only access.
3756 : *
3757 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3758 : * this handle can be cast to a GDALDataset *.
3759 : */
3760 :
3761 25270 : GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)
3762 :
3763 : {
3764 25270 : const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3765 25270 : const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3766 : GDALDatasetH hDataset =
3767 25270 : GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3768 25261 : return hDataset;
3769 : }
3770 :
3771 : /************************************************************************/
3772 : /* GetSharedDS() */
3773 : /************************************************************************/
3774 :
3775 6485 : static GDALDataset *GetSharedDS(const char *pszFilename,
3776 : unsigned int nOpenFlags,
3777 : const char *const *papszOpenOptions)
3778 : {
3779 12970 : CPLMutexHolderD(&hDLMutex);
3780 :
3781 6485 : if (phSharedDatasetSet != nullptr)
3782 : {
3783 6294 : const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3784 : SharedDatasetCtxt sStruct;
3785 :
3786 6294 : sStruct.nPID = nThisPID;
3787 6294 : sStruct.pszDescription = const_cast<char *>(pszFilename);
3788 6294 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
3789 : std::string osConcatenatedOpenOptions =
3790 6294 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
3791 6294 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
3792 6294 : sStruct.poDS = nullptr;
3793 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3794 6294 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3795 6294 : if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3796 : {
3797 177 : sStruct.nOpenFlags |= GDAL_OF_UPDATE;
3798 : psStruct = static_cast<SharedDatasetCtxt *>(
3799 177 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3800 : }
3801 6294 : if (psStruct)
3802 : {
3803 6106 : return psStruct->poDS;
3804 : }
3805 : }
3806 379 : return nullptr;
3807 : }
3808 :
3809 : /************************************************************************/
3810 : /* GDALOpenEx() */
3811 : /************************************************************************/
3812 :
3813 : /**
3814 : * \brief Open a raster or vector file as a GDALDataset.
3815 : *
3816 : * This function will try to open the passed file, or virtual dataset
3817 : * name by invoking the Open method of each registered GDALDriver in turn.
3818 : * The first successful open will result in a returned dataset. If all
3819 : * drivers fail then NULL is returned and an error is issued.
3820 : *
3821 : * Several recommendations :
3822 : * <ul>
3823 : * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
3824 : * recommended to open a new dataset on the same underlying file.</li>
3825 : * <li>The returned dataset should only be accessed by one thread at a time. If
3826 : * you want to use it from different threads, you must add all necessary code
3827 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3828 : * as GeoTIFF, maintain internal state variables that are updated each time a
3829 : * new block is read, thus preventing concurrent use.) </li>
3830 : * </ul>
3831 : *
3832 : * For drivers supporting the VSI virtual file API, it is possible to open a
3833 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3834 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3835 : * server (see VSIInstallCurlFileHandler())
3836 : *
3837 : * In order to reduce the need for searches through the operating system
3838 : * file system machinery, it is possible to give an optional list of files with
3839 : * the papszSiblingFiles parameter.
3840 : * This is the list of all files at the same level in the file system as the
3841 : * target file, including the target file. The filenames must not include any
3842 : * path components, are essentially just the output of VSIReadDir() on the
3843 : * parent directory. If the target object does not have filesystem semantics
3844 : * then the file list should be NULL.
3845 : *
3846 : * @param pszFilename the name of the file to access. In the case of
3847 : * exotic drivers this may not refer to a physical file, but instead contain
3848 : * information for the driver on how to access a dataset. It should be in UTF-8
3849 : * encoding.
3850 : *
3851 : * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
3852 : * through logical or operator.
3853 : * <ul>
3854 : * <li>Driver kind:
3855 : * <ul>
3856 : * <li>GDAL_OF_RASTER for raster drivers,</li>
3857 : * <li>GDAL_OF_MULTIDIM_RASTER for multidimensional raster drivers,</li>
3858 : * <li>GDAL_OF_VECTOR for vector drivers,</li>
3859 : * <li>GDAL_OF_GNM for Geographic Network Model drivers.</li>
3860 : * </ul>
3861 : * GDAL_OF_RASTER and GDAL_OF_MULTIDIM_RASTER are generally mutually
3862 : * exclusive. If none of the value is specified, GDAL_OF_RASTER | GDAL_OF_VECTOR
3863 : * | GDAL_OF_GNM is implied.
3864 : * </li>
3865 : * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.
3866 : * </li>
3867 : * <li>Shared mode: GDAL_OF_SHARED. If set,
3868 : * it allows the sharing of GDALDataset handles for a dataset with other callers
3869 : * that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will first consult
3870 : * its list of currently open and shared GDALDataset's, and if the
3871 : * GetDescription() name for one exactly matches the pszFilename passed to
3872 : * GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called
3873 : * from the same thread.
3874 : * </li>
3875 : * <li>Thread safe mode: GDAL_OF_THREAD_SAFE (added in 3.10).
3876 : * This must be use in combination with GDAL_OF_RASTER, and is mutually
3877 : * exclusive with GDAL_OF_UPDATE, GDAL_OF_VECTOR, GDAL_OF_MULTIDIM_RASTER or
3878 : * GDAL_OF_GNM.
3879 : * </li>
3880 : * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set,
3881 : * a failed attempt to open the file will lead to an error message to be
3882 : * reported.
3883 : * </li>
3884 : * </ul>
3885 : *
3886 : * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
3887 : * terminated list of strings with the driver short names that must be
3888 : * considered.
3889 : *
3890 : * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
3891 : * options passed to candidate drivers. An option exists for all drivers,
3892 : * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
3893 : * The level index starts at 0. The level number can be suffixed by "only" to
3894 : * specify that only this overview level must be visible, and not sub-levels.
3895 : * Open options are validated by default, and a warning is emitted in case the
3896 : * option is not recognized. In some scenarios, it might be not desirable (e.g.
3897 : * when not knowing which driver will open the file), so the special open option
3898 : * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
3899 : * since GDAL 2.1, an option name can be preceded by the @ character to indicate
3900 : * that it may not cause a warning if the driver doesn't declare this option.
3901 : * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
3902 : * no overviews should be exposed.
3903 : *
3904 : * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
3905 : * filenames that are auxiliary to the main filename. If NULL is passed, a
3906 : * probing of the file system will be done.
3907 : *
3908 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3909 : * this handle can be cast to a GDALDataset *.
3910 : *
3911 : * @since GDAL 2.0
3912 : */
3913 :
3914 82102 : GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
3915 : unsigned int nOpenFlags,
3916 : const char *const *papszAllowedDrivers,
3917 : const char *const *papszOpenOptions,
3918 : const char *const *papszSiblingFiles)
3919 : {
3920 82102 : VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
3921 :
3922 : // Hack for the ZARR driver. We translate the CACHE_KERCHUNK_JSON
3923 : // into VSIKERCHUNK_USE_CACHE config option
3924 82059 : std::unique_ptr<CPLConfigOptionSetter> poVSIKERCHUNK_USE_CACHESetter;
3925 82102 : if (CPLFetchBool(papszOpenOptions, "CACHE_KERCHUNK_JSON", false))
3926 : {
3927 13 : poVSIKERCHUNK_USE_CACHESetter = std::make_unique<CPLConfigOptionSetter>(
3928 26 : "VSIKERCHUNK_USE_CACHE", "YES", false);
3929 : }
3930 :
3931 : // Do some sanity checks on incompatible flags with thread-safe mode.
3932 82100 : if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3933 : {
3934 : const struct
3935 : {
3936 : int nFlag;
3937 : const char *pszFlagName;
3938 128 : } asFlags[] = {
3939 : {GDAL_OF_UPDATE, "GDAL_OF_UPDATE"},
3940 : {GDAL_OF_VECTOR, "GDAL_OF_VECTOR"},
3941 : {GDAL_OF_MULTIDIM_RASTER, "GDAL_OF_MULTIDIM_RASTER"},
3942 : {GDAL_OF_GNM, "GDAL_OF_GNM"},
3943 : };
3944 :
3945 630 : for (const auto &asFlag : asFlags)
3946 : {
3947 506 : if ((nOpenFlags & asFlag.nFlag) != 0)
3948 : {
3949 4 : CPLError(CE_Failure, CPLE_IllegalArg,
3950 : "GDAL_OF_THREAD_SAFE and %s are mutually "
3951 : "exclusive",
3952 4 : asFlag.pszFlagName);
3953 4 : return nullptr;
3954 : }
3955 : }
3956 : }
3957 :
3958 : // If no driver kind is specified, assume all are to be probed.
3959 82096 : if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)
3960 7592 : nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
3961 :
3962 : /* -------------------------------------------------------------------- */
3963 : /* In case of shared dataset, first scan the existing list to see */
3964 : /* if it could already contain the requested dataset. */
3965 : /* -------------------------------------------------------------------- */
3966 82096 : if (nOpenFlags & GDAL_OF_SHARED)
3967 : {
3968 6485 : if (nOpenFlags & GDAL_OF_INTERNAL)
3969 : {
3970 0 : CPLError(CE_Failure, CPLE_IllegalArg,
3971 : "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
3972 0 : return nullptr;
3973 : }
3974 :
3975 : auto poSharedDS =
3976 6485 : GetSharedDS(pszFilename, nOpenFlags, papszOpenOptions);
3977 6485 : if (poSharedDS)
3978 : {
3979 6106 : poSharedDS->Reference();
3980 6106 : return poSharedDS;
3981 : }
3982 : }
3983 :
3984 75990 : GDALDriverManager *poDM = GetGDALDriverManager();
3985 : // CPLLocaleC oLocaleForcer;
3986 :
3987 75988 : CPLErrorReset();
3988 75977 : VSIErrorReset();
3989 75985 : CPLAssert(nullptr != poDM);
3990 :
3991 : // Build GDALOpenInfo just now to avoid useless file stat'ing if a
3992 : // shared dataset was asked before.
3993 : GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
3994 151914 : const_cast<char **>(papszSiblingFiles));
3995 75992 : oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3996 :
3997 75992 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3998 75992 : if (sAntiRecursion.nRecLevel == 100)
3999 : {
4000 0 : CPLError(CE_Failure, CPLE_AppDefined,
4001 : "GDALOpen() called with too many recursion levels");
4002 0 : return nullptr;
4003 : }
4004 :
4005 151938 : std::string osAllowedDrivers;
4006 166924 : for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
4007 90934 : osAllowedDrivers += pszDriverName;
4008 : auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(
4009 227933 : std::string(pszFilename), nOpenFlags, osAllowedDrivers);
4010 75981 : if (cpl::contains(sAntiRecursion.aosDatasetNamesWithFlags, dsCtxt))
4011 : {
4012 0 : CPLError(CE_Failure, CPLE_AppDefined,
4013 : "GDALOpen() called on %s recursively", pszFilename);
4014 0 : return nullptr;
4015 : }
4016 :
4017 : // Remove leading @ if present.
4018 : char **papszOpenOptionsCleaned =
4019 75975 : CSLDuplicate(const_cast<char **>(papszOpenOptions));
4020 81578 : for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
4021 : ++papszIter)
4022 : {
4023 5604 : char *pszOption = *papszIter;
4024 5604 : if (pszOption[0] == '@')
4025 203 : memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
4026 : }
4027 :
4028 75974 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4029 75974 : oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;
4030 :
4031 : #ifdef OGRAPISPY_ENABLED
4032 75974 : const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
4033 : const int iSnapshot =
4034 18982 : (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0
4035 94956 : ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)
4036 75974 : : INT_MIN;
4037 : #endif
4038 :
4039 75974 : const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);
4040 75969 : GDALDriver *poMissingPluginDriver = nullptr;
4041 151945 : std::vector<GDALDriver *> apoSecondPassDrivers;
4042 :
4043 : // Lookup of matching driver for dataset can involve up to 2 passes:
4044 : // - in the first pass, all drivers that are compabile of the request mode
4045 : // (raster/vector/etc.) are probed using their Identify() method if it
4046 : // exists. If the Identify() method returns FALSE, the driver is skipped.
4047 : // If the Identify() methods returns GDAL_IDENTIFY_UNKNOWN and that the
4048 : // driver is a deferred-loading plugin, it is added to the
4049 : // apoSecondPassDrivers list for potential later probing, and execution
4050 : // continues to the next driver in the list.
4051 : // Otherwise if Identify() returns non-FALSE, the Open() method is used.
4052 : // If Open() returns a non-NULL dataset, the loop stops and it is
4053 : // returned. Otherwise looping over remaining drivers continues.
4054 : // - the second pass is optional, only if at least one driver was added
4055 : // into apoSecondPassDrivers during the first pass. It is similar
4056 : // to the first pass except it runs only on apoSecondPassDrivers drivers.
4057 : // And the Open() method of such drivers is used, causing them to be
4058 : // loaded for real.
4059 75957 : int iPass = 1;
4060 75972 : retry:
4061 7808220 : for (int iDriver = 0;
4062 7808250 : iDriver < (iPass == 1 ? nDriverCount
4063 30 : : static_cast<int>(apoSecondPassDrivers.size()));
4064 : ++iDriver)
4065 : {
4066 : GDALDriver *poDriver =
4067 7789560 : iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
4068 624 : : apoSecondPassDrivers[iDriver];
4069 11372400 : if (papszAllowedDrivers != nullptr &&
4070 3582100 : CSLFindString(papszAllowedDrivers,
4071 : GDALGetDriverShortName(poDriver)) == -1)
4072 : {
4073 7333660 : continue;
4074 : }
4075 :
4076 4297400 : if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)
4077 42146 : continue;
4078 :
4079 11279300 : if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&
4080 6143550 : (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
4081 1906060 : poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
4082 456214 : continue;
4083 11094200 : if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&
4084 5549040 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
4085 1767760 : poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
4086 1335820 : continue;
4087 5177970 : if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
4088 2591740 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
4089 146278 : poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)
4090 137658 : continue;
4091 :
4092 : // Remove general OVERVIEW_LEVEL open options from list before passing
4093 : // it to the driver, if it isn't a driver specific option already.
4094 2307800 : char **papszTmpOpenOptions = nullptr;
4095 2307800 : char **papszTmpOpenOptionsToValidate = nullptr;
4096 2307800 : char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
4097 2307800 : if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
4098 2318980 : nullptr &&
4099 152 : !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
4100 : {
4101 152 : papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
4102 : papszTmpOpenOptions =
4103 152 : CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
4104 152 : oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
4105 :
4106 152 : papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
4107 152 : papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate,
4108 : "OVERVIEW_LEVEL", nullptr);
4109 152 : papszTmpOpenOptionsToValidate = papszOptionsToValidate;
4110 : }
4111 :
4112 : const int nIdentifyRes =
4113 2318830 : poDriver->pfnIdentifyEx
4114 4638450 : ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)
4115 2318820 : : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)
4116 2319630 : : GDAL_IDENTIFY_UNKNOWN;
4117 2319630 : if (nIdentifyRes == FALSE)
4118 : {
4119 1870290 : CSLDestroy(papszTmpOpenOptions);
4120 1869930 : CSLDestroy(papszTmpOpenOptionsToValidate);
4121 1868820 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4122 1868820 : continue;
4123 : }
4124 451773 : else if (iPass == 1 && nIdentifyRes < 0 &&
4125 901221 : poDriver->pfnOpen == nullptr &&
4126 106 : poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN"))
4127 : {
4128 : // Not loaded plugin
4129 101 : apoSecondPassDrivers.push_back(poDriver);
4130 101 : CSLDestroy(papszTmpOpenOptions);
4131 101 : CSLDestroy(papszTmpOpenOptionsToValidate);
4132 101 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4133 101 : continue;
4134 : }
4135 :
4136 449241 : const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;
4137 449241 : if (bIdentifyRes)
4138 : {
4139 56463 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
4140 : }
4141 :
4142 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
4143 : const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
4144 : CPLErrorReset();
4145 : #endif
4146 :
4147 449228 : sAntiRecursion.nRecLevel++;
4148 449228 : sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
4149 :
4150 451180 : GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
4151 :
4152 451639 : sAntiRecursion.nRecLevel--;
4153 451639 : sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
4154 :
4155 451194 : if (poDriver->pfnOpen != nullptr)
4156 : {
4157 : // If we couldn't determine for sure with Identify() (it returned
4158 : // -1), but Open() managed to open the file, post validate options.
4159 451303 : if (poDS != nullptr &&
4160 56411 : (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&
4161 55849 : !bIdentifyRes)
4162 : {
4163 804 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
4164 : }
4165 : }
4166 0 : else if (poDriver->pfnOpenWithDriverArg != nullptr)
4167 : {
4168 : // do nothing
4169 : }
4170 0 : else if (bIdentifyRes &&
4171 0 : poDriver->GetMetadataItem("MISSING_PLUGIN_FILENAME"))
4172 : {
4173 0 : if (!poMissingPluginDriver)
4174 : {
4175 0 : poMissingPluginDriver = poDriver;
4176 : }
4177 : }
4178 : else
4179 : {
4180 : // should not happen given the GDAL_DCAP_OPEN check
4181 0 : CSLDestroy(papszTmpOpenOptions);
4182 0 : CSLDestroy(papszTmpOpenOptionsToValidate);
4183 0 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4184 0 : continue;
4185 : }
4186 :
4187 451194 : CSLDestroy(papszTmpOpenOptions);
4188 451010 : CSLDestroy(papszTmpOpenOptionsToValidate);
4189 450608 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4190 :
4191 450608 : if (poDS != nullptr)
4192 : {
4193 56389 : if (poDS->papszOpenOptions == nullptr)
4194 : {
4195 56153 : poDS->papszOpenOptions = papszOpenOptionsCleaned;
4196 56153 : papszOpenOptionsCleaned = nullptr;
4197 : }
4198 :
4199 : // Deal with generic OVERVIEW_LEVEL open option, unless it is
4200 : // driver specific.
4201 56389 : if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
4202 56448 : nullptr &&
4203 39 : !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
4204 : {
4205 : CPLString osVal(
4206 78 : CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
4207 39 : const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
4208 : const bool bThisLevelOnly =
4209 39 : nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
4210 : GDALDataset *poOvrDS =
4211 39 : GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly);
4212 39 : if (poOvrDS && (nOpenFlags & GDAL_OF_SHARED) != 0)
4213 : {
4214 4 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
4215 : {
4216 0 : CPLError(
4217 : CE_Warning, CPLE_NotSupported,
4218 : "A dataset opened by GDALOpenShared should have "
4219 : "the same filename (%s) "
4220 : "and description (%s)",
4221 0 : pszFilename, poDS->GetDescription());
4222 : }
4223 : else
4224 : {
4225 4 : CSLDestroy(poDS->papszOpenOptions);
4226 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
4227 4 : poDS->papszOpenOptions = CSLSetNameValue(
4228 : poDS->papszOpenOptions, "OVERVIEW_LEVEL", nullptr);
4229 : }
4230 : }
4231 39 : poDS->ReleaseRef();
4232 39 : poDS = poOvrDS;
4233 39 : if (poDS == nullptr)
4234 : {
4235 1 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4236 : {
4237 1 : CPLError(CE_Failure, CPLE_OpenFailed,
4238 : "Cannot open overview level %d of %s",
4239 : nOvrLevel, pszFilename);
4240 : }
4241 : }
4242 : else
4243 : {
4244 : // For thread-safe opening, currently poDS is what will be
4245 : // the "master" dataset owned by the thread-safe dataset
4246 : // returned to the user, hence we do not register it as a
4247 : // visible one in the open dataset list, or mark it as shared.
4248 38 : if (!(nOpenFlags & GDAL_OF_INTERNAL) &&
4249 36 : !(nOpenFlags & GDAL_OF_THREAD_SAFE))
4250 : {
4251 35 : poDS->AddToDatasetOpenList();
4252 : }
4253 38 : if (nOpenFlags & GDAL_OF_SHARED)
4254 : {
4255 4 : CSLDestroy(poDS->papszOpenOptions);
4256 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
4257 4 : poDS->nOpenFlags = nOpenFlags;
4258 4 : if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
4259 4 : poDS->MarkAsShared();
4260 : }
4261 : }
4262 : }
4263 56370 : else if (nOpenFlags & GDAL_OF_SHARED)
4264 : {
4265 369 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
4266 : {
4267 2 : CPLError(CE_Warning, CPLE_NotSupported,
4268 : "A dataset opened by GDALOpenShared should have "
4269 : "the same filename (%s) "
4270 : "and description (%s)",
4271 2 : pszFilename, poDS->GetDescription());
4272 : }
4273 367 : else if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
4274 : {
4275 : // For thread-safe opening, currently poDS is what will be
4276 : // the "master" dataset owned by the thread-safe dataset
4277 : // returned to the user, hence we do not or mark it as shared.
4278 367 : poDS->MarkAsShared();
4279 : }
4280 : }
4281 :
4282 56409 : VSIErrorReset();
4283 :
4284 56379 : CSLDestroy(papszOpenOptionsCleaned);
4285 :
4286 : #ifdef OGRAPISPY_ENABLED
4287 56383 : if (iSnapshot != INT_MIN)
4288 : {
4289 11201 : GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
4290 11201 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4291 11201 : poDS = GDALDataset::FromHandle(hDS);
4292 : }
4293 : #endif
4294 :
4295 56383 : if (poDS)
4296 : {
4297 56380 : poDS->m_bCanBeReopened = true;
4298 :
4299 56380 : if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
4300 : {
4301 : poDS =
4302 248 : GDALGetThreadSafeDataset(
4303 248 : std::unique_ptr<GDALDataset>(poDS), GDAL_OF_RASTER)
4304 124 : .release();
4305 124 : if (poDS)
4306 : {
4307 124 : poDS->m_bCanBeReopened = true;
4308 124 : poDS->poDriver = poDriver;
4309 124 : poDS->nOpenFlags = nOpenFlags;
4310 124 : if (!(nOpenFlags & GDAL_OF_INTERNAL))
4311 124 : poDS->AddToDatasetOpenList();
4312 124 : if (nOpenFlags & GDAL_OF_SHARED)
4313 0 : poDS->MarkAsShared();
4314 : }
4315 : }
4316 : }
4317 :
4318 57434 : return poDS;
4319 : }
4320 :
4321 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
4322 : if (bFpAvailableBefore && oOpenInfo.fpL == nullptr)
4323 : {
4324 : // In case the file descriptor was "consumed" by a driver
4325 : // that ultimately failed, re-open it for next drivers.
4326 : oOpenInfo.fpL = VSIFOpenL(
4327 : pszFilename, (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
4328 : }
4329 : #else
4330 394219 : if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
4331 : {
4332 0 : CSLDestroy(papszOpenOptionsCleaned);
4333 :
4334 : #ifdef OGRAPISPY_ENABLED
4335 1014 : if (iSnapshot != INT_MIN)
4336 : {
4337 189 : GDALDatasetH hDS = nullptr;
4338 189 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4339 : }
4340 : #endif
4341 1014 : return nullptr;
4342 : }
4343 : #endif
4344 : }
4345 :
4346 : // cppcheck-suppress knownConditionTrueFalse
4347 18682 : if (iPass == 1 && !apoSecondPassDrivers.empty())
4348 : {
4349 11 : CPLDebugOnly("GDAL", "GDALOpen(): Second pass");
4350 15 : iPass = 2;
4351 15 : goto retry;
4352 : }
4353 :
4354 18670 : CSLDestroy(papszOpenOptionsCleaned);
4355 :
4356 : #ifdef OGRAPISPY_ENABLED
4357 18543 : if (iSnapshot != INT_MIN)
4358 : {
4359 653 : GDALDatasetH hDS = nullptr;
4360 653 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4361 : }
4362 : #endif
4363 :
4364 18543 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4365 : {
4366 5630 : if (nDriverCount == 0)
4367 : {
4368 0 : CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");
4369 : }
4370 5630 : else if (poMissingPluginDriver)
4371 : {
4372 0 : std::string osMsg("`");
4373 0 : osMsg += pszFilename;
4374 : osMsg += "' not recognized as being in a supported file format. "
4375 0 : "It could have been recognized by driver ";
4376 0 : osMsg += poMissingPluginDriver->GetDescription();
4377 0 : osMsg += ", but plugin ";
4378 : osMsg +=
4379 0 : GDALGetMessageAboutMissingPluginDriver(poMissingPluginDriver);
4380 :
4381 0 : CPLError(CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str());
4382 : }
4383 : // Check to see if there was a filesystem error, and report it if so.
4384 : // If not, return a more generic error.
4385 5630 : else if (!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
4386 : {
4387 355 : if (oOpenInfo.bStatOK)
4388 : {
4389 352 : CPLError(CE_Failure, CPLE_OpenFailed,
4390 : "`%s' not recognized as being in a supported file "
4391 : "format.",
4392 : pszFilename);
4393 : }
4394 : else
4395 : {
4396 : // If Stat failed and no VSI error was set, assume it is because
4397 : // the file did not exist on the filesystem.
4398 3 : CPLError(CE_Failure, CPLE_OpenFailed,
4399 : "`%s' does not exist in the file system, "
4400 : "and is not recognized as a supported dataset name.",
4401 : pszFilename);
4402 : }
4403 : }
4404 : }
4405 :
4406 18542 : return nullptr;
4407 : }
4408 :
4409 : /************************************************************************/
4410 : /* GDALOpenShared() */
4411 : /************************************************************************/
4412 :
4413 : /**
4414 : * \brief Open a raster file as a GDALDataset.
4415 : *
4416 : * This function works the same as GDALOpen(), but allows the sharing of
4417 : * GDALDataset handles for a dataset with other callers to GDALOpenShared().
4418 : *
4419 : * In particular, GDALOpenShared() will first consult its list of currently
4420 : * open and shared GDALDataset's, and if the GetDescription() name for one
4421 : * exactly matches the pszFilename passed to GDALOpenShared() it will be
4422 : * referenced and returned.
4423 : *
4424 : * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
4425 : * pszFilename from two different threads, a different GDALDataset object will
4426 : * be returned as it is not safe to use the same dataset from different threads,
4427 : * unless the user does explicitly use mutexes in its code.
4428 : *
4429 : * For drivers supporting the VSI virtual file API, it is possible to open a
4430 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
4431 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
4432 : * server (see VSIInstallCurlFileHandler())
4433 : *
4434 : * \sa GDALOpen()
4435 : * \sa GDALOpenEx()
4436 : *
4437 : * @param pszFilename the name of the file to access. In the case of
4438 : * exotic drivers this may not refer to a physical file, but instead contain
4439 : * information for the driver on how to access a dataset. It should be in
4440 : * UTF-8 encoding.
4441 : *
4442 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
4443 : * drivers support only read only access.
4444 : *
4445 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
4446 : * this handle can be cast to a GDALDataset *.
4447 : */
4448 :
4449 5224 : GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,
4450 : GDALAccess eAccess)
4451 : {
4452 5224 : VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
4453 5224 : return GDALOpenEx(pszFilename,
4454 : GDAL_OF_RASTER |
4455 : (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
4456 : GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
4457 5224 : nullptr, nullptr, nullptr);
4458 : }
4459 :
4460 : /************************************************************************/
4461 : /* GDALClose() */
4462 : /************************************************************************/
4463 :
4464 : /**
4465 : * \brief Close GDAL dataset.
4466 : *
4467 : * For non-shared datasets (opened with GDALOpen()) the dataset is closed
4468 : * using the C++ "delete" operator, recovering all dataset related resources.
4469 : * For shared datasets (opened with GDALOpenShared()) the dataset is
4470 : * dereferenced, and closed only if the referenced count has dropped below 1.
4471 : *
4472 : * @param hDS The dataset to close. May be cast from a "GDALDataset *".
4473 : * @return CE_None in case of success (return value since GDAL 3.7). On a
4474 : * shared dataset whose reference count is not dropped below 1, CE_None will
4475 : * be returned.
4476 : */
4477 :
4478 75887 : CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)
4479 :
4480 : {
4481 75887 : if (!hDS)
4482 398 : return CE_None;
4483 :
4484 : #ifdef OGRAPISPY_ENABLED
4485 75489 : if (bOGRAPISpyEnabled)
4486 11 : OGRAPISpyPreClose(hDS);
4487 : #endif
4488 :
4489 75489 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
4490 :
4491 75489 : if (poDS->GetShared())
4492 : {
4493 : /* --------------------------------------------------------------------
4494 : */
4495 : /* If this file is in the shared dataset list then dereference */
4496 : /* it, and only delete/remote it if the reference count has */
4497 : /* dropped to zero. */
4498 : /* --------------------------------------------------------------------
4499 : */
4500 231 : if (poDS->Dereference() > 0)
4501 15 : return CE_None;
4502 :
4503 216 : CPLErr eErr = poDS->Close();
4504 216 : delete poDS;
4505 :
4506 : #ifdef OGRAPISPY_ENABLED
4507 216 : if (bOGRAPISpyEnabled)
4508 0 : OGRAPISpyPostClose();
4509 : #endif
4510 :
4511 216 : return eErr;
4512 : }
4513 :
4514 : /* -------------------------------------------------------------------- */
4515 : /* This is not shared dataset, so directly delete it. */
4516 : /* -------------------------------------------------------------------- */
4517 75258 : CPLErr eErr = poDS->Close();
4518 75254 : delete poDS;
4519 :
4520 : #ifdef OGRAPISPY_ENABLED
4521 75257 : if (bOGRAPISpyEnabled)
4522 11 : OGRAPISpyPostClose();
4523 : #endif
4524 75251 : return eErr;
4525 : }
4526 :
4527 : /************************************************************************/
4528 : /* GDALDumpOpenDataset() */
4529 : /************************************************************************/
4530 :
4531 0 : static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
4532 : {
4533 0 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
4534 0 : FILE *fp = static_cast<FILE *>(user_data);
4535 0 : GDALDataset *poDS = psStruct->poDS;
4536 :
4537 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4538 0 : ? "DriverIsNULL"
4539 0 : : poDS->GetDriver()->GetDescription();
4540 :
4541 0 : poDS->Reference();
4542 0 : CPL_IGNORE_RET_VAL(
4543 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4544 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName,
4545 0 : static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
4546 : poDS->GetRasterYSize(), poDS->GetRasterCount(),
4547 0 : poDS->GetDescription()));
4548 :
4549 0 : return TRUE;
4550 : }
4551 :
4552 0 : static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
4553 : {
4554 :
4555 : // Don't list shared datasets. They have already been listed by
4556 : // GDALDumpOpenSharedDatasetsForeach.
4557 0 : if (poDS->GetShared())
4558 0 : return TRUE;
4559 :
4560 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4561 0 : ? "DriverIsNULL"
4562 0 : : poDS->GetDriver()->GetDescription();
4563 :
4564 0 : poDS->Reference();
4565 0 : CPL_IGNORE_RET_VAL(
4566 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4567 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
4568 : poDS->GetRasterXSize(), poDS->GetRasterYSize(),
4569 0 : poDS->GetRasterCount(), poDS->GetDescription()));
4570 :
4571 0 : return TRUE;
4572 : }
4573 :
4574 : /**
4575 : * \brief List open datasets.
4576 : *
4577 : * Dumps a list of all open datasets (shared or not) to the indicated
4578 : * text file (may be stdout or stderr). This function is primarily intended
4579 : * to assist in debugging "dataset leaks" and reference counting issues.
4580 : * The information reported includes the dataset name, referenced count,
4581 : * shared status, driver name, size, and band count.
4582 : */
4583 :
4584 272 : int CPL_STDCALL GDALDumpOpenDatasets(FILE *fp)
4585 :
4586 : {
4587 272 : VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
4588 :
4589 544 : CPLMutexHolderD(&hDLMutex);
4590 :
4591 272 : if (poAllDatasetMap == nullptr)
4592 272 : return 0;
4593 :
4594 0 : CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
4595 :
4596 0 : for (const auto &oIter : *poAllDatasetMap)
4597 : {
4598 0 : GDALDumpOpenDatasetsForeach(oIter.first, fp);
4599 : }
4600 :
4601 0 : if (phSharedDatasetSet != nullptr)
4602 : {
4603 0 : CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach,
4604 : fp);
4605 : }
4606 0 : return static_cast<int>(poAllDatasetMap->size());
4607 : }
4608 :
4609 : /************************************************************************/
4610 : /* BeginAsyncReader() */
4611 : /************************************************************************/
4612 :
4613 : /**
4614 : * \brief Sets up an asynchronous data request
4615 : *
4616 : * This method establish an asynchronous raster read request for the
4617 : * indicated window on the dataset into the indicated buffer. The parameters
4618 : * for windowing, buffer size, buffer type and buffer organization are similar
4619 : * to those for GDALDataset::RasterIO(); however, this call only launches
4620 : * the request and filling the buffer is accomplished via calls to
4621 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4622 : *
4623 : * Once all processing for the created session is complete, or if no further
4624 : * refinement of the request is required, the GDALAsyncReader object should
4625 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4626 : *
4627 : * Note that the data buffer (pData) will potentially continue to be
4628 : * updated as long as the session lives, but it is not deallocated when
4629 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4630 : * should be deallocated by the application at that point.
4631 : *
4632 : * Additional information on asynchronous IO in GDAL may be found at:
4633 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4634 : *
4635 : * This method is the same as the C GDALBeginAsyncReader() function.
4636 : *
4637 : * @param nXOff The pixel offset to the top left corner of the region
4638 : * of the band to be accessed. This would be zero to start from the left side.
4639 : *
4640 : * @param nYOff The line offset to the top left corner of the region
4641 : * of the band to be accessed. This would be zero to start from the top.
4642 : *
4643 : * @param nXSize The width of the region of the band to be accessed in pixels.
4644 : *
4645 : * @param nYSize The height of the region of the band to be accessed in lines.
4646 : *
4647 : * @param pBuf The buffer into which the data should be read. This buffer must
4648 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4649 : * It is organized in left to right,top to bottom pixel order. Spacing is
4650 : * controlled by the nPixelSpace, and nLineSpace parameters.
4651 : *
4652 : * @param nBufXSize the width of the buffer image into which the desired region
4653 : * is to be read, or from which it is to be written.
4654 : *
4655 : * @param nBufYSize the height of the buffer image into which the desired
4656 : * region is to be read, or from which it is to be written.
4657 : *
4658 : * @param eBufType the type of the pixel values in the pData data buffer. The
4659 : * pixel values will automatically be translated to/from the GDALRasterBand
4660 : * data type as needed.
4661 : *
4662 : * @param nBandCount the number of bands being read or written.
4663 : *
4664 : * @param panBandMap the list of nBandCount band numbers being read/written.
4665 : * Note band numbers are 1 based. This may be NULL to select the first
4666 : * nBandCount bands.
4667 : *
4668 : * @param nPixelSpace The byte offset from the start of one pixel value in
4669 : * pData to the start of the next pixel value within a scanline. If defaulted
4670 : * (0) the size of the datatype eBufType is used.
4671 : *
4672 : * @param nLineSpace The byte offset from the start of one scanline in
4673 : * pData to the start of the next. If defaulted the size of the datatype
4674 : * eBufType * nBufXSize is used.
4675 : *
4676 : * @param nBandSpace the byte offset from the start of one bands data to the
4677 : * start of the next. If defaulted (zero) the value will be
4678 : * nLineSpace * nBufYSize implying band sequential organization
4679 : * of the data buffer.
4680 : *
4681 : * @param papszOptions Driver specific control options in a string list or NULL.
4682 : * Consult driver documentation for options supported.
4683 : *
4684 : * @return The GDALAsyncReader object representing the request.
4685 : */
4686 :
4687 1 : GDALAsyncReader *GDALDataset::BeginAsyncReader(
4688 : int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
4689 : int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
4690 : int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions)
4691 : {
4692 : // See gdaldefaultasync.cpp
4693 :
4694 1 : return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
4695 : nBufXSize, nBufYSize, eBufType, nBandCount,
4696 : panBandMap, nPixelSpace, nLineSpace,
4697 1 : nBandSpace, papszOptions);
4698 : }
4699 :
4700 : /************************************************************************/
4701 : /* GDALBeginAsyncReader() */
4702 : /************************************************************************/
4703 :
4704 : /**
4705 : * \brief Sets up an asynchronous data request
4706 : *
4707 : * This method establish an asynchronous raster read request for the
4708 : * indicated window on the dataset into the indicated buffer. The parameters
4709 : * for windowing, buffer size, buffer type and buffer organization are similar
4710 : * to those for GDALDataset::RasterIO(); however, this call only launches
4711 : * the request and filling the buffer is accomplished via calls to
4712 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4713 : *
4714 : * Once all processing for the created session is complete, or if no further
4715 : * refinement of the request is required, the GDALAsyncReader object should
4716 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4717 : *
4718 : * Note that the data buffer (pData) will potentially continue to be
4719 : * updated as long as the session lives, but it is not deallocated when
4720 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4721 : * should be deallocated by the application at that point.
4722 : *
4723 : * Additional information on asynchronous IO in GDAL may be found at:
4724 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4725 : *
4726 : * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
4727 : *
4728 : * @param hDS handle to the dataset object.
4729 : *
4730 : * @param nXOff The pixel offset to the top left corner of the region
4731 : * of the band to be accessed. This would be zero to start from the left side.
4732 : *
4733 : * @param nYOff The line offset to the top left corner of the region
4734 : * of the band to be accessed. This would be zero to start from the top.
4735 : *
4736 : * @param nXSize The width of the region of the band to be accessed in pixels.
4737 : *
4738 : * @param nYSize The height of the region of the band to be accessed in lines.
4739 : *
4740 : * @param pBuf The buffer into which the data should be read. This buffer must
4741 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4742 : * It is organized in left to right,top to bottom pixel order. Spacing is
4743 : * controlled by the nPixelSpace, and nLineSpace parameters.
4744 : *
4745 : * @param nBufXSize the width of the buffer image into which the desired region
4746 : * is to be read, or from which it is to be written.
4747 : *
4748 : * @param nBufYSize the height of the buffer image into which the desired
4749 : * region is to be read, or from which it is to be written.
4750 : *
4751 : * @param eBufType the type of the pixel values in the pData data buffer. The
4752 : * pixel values will automatically be translated to/from the GDALRasterBand
4753 : * data type as needed.
4754 : *
4755 : * @param nBandCount the number of bands being read or written.
4756 : *
4757 : * @param panBandMap the list of nBandCount band numbers being read/written.
4758 : * Note band numbers are 1 based. This may be NULL to select the first
4759 : * nBandCount bands.
4760 : *
4761 : * @param nPixelSpace The byte offset from the start of one pixel value in
4762 : * pData to the start of the next pixel value within a scanline. If defaulted
4763 : * (0) the size of the datatype eBufType is used.
4764 : *
4765 : * @param nLineSpace The byte offset from the start of one scanline in
4766 : * pData to the start of the next. If defaulted the size of the datatype
4767 : * eBufType * nBufXSize is used.
4768 : *
4769 : * @param nBandSpace the byte offset from the start of one bands data to the
4770 : * start of the next. If defaulted (zero) the value will be
4771 : * nLineSpace * nBufYSize implying band sequential organization
4772 : * of the data buffer.
4773 : *
4774 : * @param papszOptions Driver specific control options in a string list or NULL.
4775 : * Consult driver documentation for options supported.
4776 : *
4777 : * @return handle representing the request.
4778 : */
4779 :
4780 2 : GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(
4781 : GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf,
4782 : int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount,
4783 : int *panBandMap, int nPixelSpace, int nLineSpace, int nBandSpace,
4784 : CSLConstList papszOptions)
4785 :
4786 : {
4787 2 : VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
4788 : return static_cast<GDALAsyncReaderH>(
4789 2 : GDALDataset::FromHandle(hDS)->BeginAsyncReader(
4790 : nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
4791 : nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
4792 2 : const_cast<char **>(papszOptions)));
4793 : }
4794 :
4795 : /************************************************************************/
4796 : /* EndAsyncReader() */
4797 : /************************************************************************/
4798 :
4799 : /**
4800 : * End asynchronous request.
4801 : *
4802 : * This method destroys an asynchronous io request and recovers all
4803 : * resources associated with it.
4804 : *
4805 : * This method is the same as the C function GDALEndAsyncReader().
4806 : *
4807 : * @param poARIO pointer to a GDALAsyncReader
4808 : */
4809 :
4810 1 : void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO)
4811 : {
4812 1 : delete poARIO;
4813 1 : }
4814 :
4815 : /************************************************************************/
4816 : /* GDALEndAsyncReader() */
4817 : /************************************************************************/
4818 :
4819 : /**
4820 : * End asynchronous request.
4821 : *
4822 : * This method destroys an asynchronous io request and recovers all
4823 : * resources associated with it.
4824 : *
4825 : * This method is the same as the C++ method GDALDataset::EndAsyncReader().
4826 : *
4827 : * @param hDS handle to the dataset object.
4828 : * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
4829 : */
4830 :
4831 1 : void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS,
4832 : GDALAsyncReaderH hAsyncReaderH)
4833 : {
4834 1 : VALIDATE_POINTER0(hDS, "GDALDataset");
4835 1 : VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
4836 1 : GDALDataset::FromHandle(hDS)->EndAsyncReader(
4837 1 : static_cast<GDALAsyncReader *>(hAsyncReaderH));
4838 : }
4839 :
4840 : /************************************************************************/
4841 : /* CloseDependentDatasets() */
4842 : /************************************************************************/
4843 :
4844 : /**
4845 : * Drop references to any other datasets referenced by this dataset.
4846 : *
4847 : * This method should release any reference to other datasets (e.g. a VRT
4848 : * dataset to its sources), but not close the current dataset itself.
4849 : *
4850 : * If at least, one reference to a dependent dataset has been dropped,
4851 : * this method should return TRUE. Otherwise it *should* return FALSE.
4852 : * (Failure to return the proper value might result in infinite loop)
4853 : *
4854 : * This method can be called several times on a given dataset. After
4855 : * the first time, it should not do anything and return FALSE.
4856 : *
4857 : * The driver implementation may choose to destroy its raster bands,
4858 : * so be careful not to call any method on the raster bands afterwards.
4859 : *
4860 : * Basically the only safe action you can do after calling
4861 : * CloseDependentDatasets() is to call the destructor.
4862 : *
4863 : * Note: the only legitimate caller of CloseDependentDatasets() is
4864 : * GDALDriverManager::~GDALDriverManager()
4865 : *
4866 : * @return TRUE if at least one reference to another dataset has been dropped.
4867 : */
4868 18913 : int GDALDataset::CloseDependentDatasets()
4869 : {
4870 18913 : return oOvManager.CloseDependentDatasets();
4871 : }
4872 :
4873 : /************************************************************************/
4874 : /* ReportError() */
4875 : /************************************************************************/
4876 :
4877 : #ifndef DOXYGEN_XML
4878 : /**
4879 : * \brief Emits an error related to a dataset.
4880 : *
4881 : * This function is a wrapper for regular CPLError(). The only difference
4882 : * with CPLError() is that it prepends the error message with the dataset
4883 : * name.
4884 : *
4885 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4886 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4887 : * @param fmt a printf() style format string. Any additional arguments
4888 : * will be treated as arguments to fill in this format in a manner
4889 : * similar to printf().
4890 : *
4891 : * @since GDAL 1.9.0
4892 : */
4893 :
4894 98 : void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4895 : const char *fmt, ...) const
4896 : {
4897 : va_list args;
4898 98 : va_start(args, fmt);
4899 98 : ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4900 98 : va_end(args);
4901 98 : }
4902 :
4903 : /**
4904 : * \brief Emits an error related to a dataset (static method)
4905 : *
4906 : * This function is a wrapper for regular CPLError(). The only difference
4907 : * with CPLError() is that it prepends the error message with the dataset
4908 : * name.
4909 : *
4910 : * @param pszDSName dataset name.
4911 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4912 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4913 : * @param fmt a printf() style format string. Any additional arguments
4914 : * will be treated as arguments to fill in this format in a manner
4915 : * similar to printf().
4916 : *
4917 : * @since GDAL 3.2.0
4918 : */
4919 :
4920 124 : void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,
4921 : CPLErrorNum err_no, const char *fmt, ...)
4922 : {
4923 : va_list args;
4924 124 : va_start(args, fmt);
4925 124 : ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4926 124 : va_end(args);
4927 124 : }
4928 :
4929 222 : void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,
4930 : CPLErrorNum err_no, const char *fmt,
4931 : va_list args)
4932 : {
4933 222 : pszDSName = CPLGetFilename(pszDSName);
4934 222 : if (pszDSName[0] != '\0')
4935 : {
4936 209 : CPLError(eErrClass, err_no, "%s",
4937 418 : std::string(pszDSName)
4938 209 : .append(": ")
4939 418 : .append(CPLString().vPrintf(fmt, args))
4940 : .c_str());
4941 : }
4942 : else
4943 : {
4944 13 : CPLErrorV(eErrClass, err_no, fmt, args);
4945 : }
4946 222 : }
4947 : #endif
4948 :
4949 : /************************************************************************/
4950 : /* GetMetadata() */
4951 : /************************************************************************/
4952 70261 : char **GDALDataset::GetMetadata(const char *pszDomain)
4953 : {
4954 : #ifndef WITHOUT_DERIVED
4955 70261 : if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
4956 : {
4957 10 : oDerivedMetadataList.Clear();
4958 :
4959 : // First condition: at least one raster band.
4960 10 : if (GetRasterCount() > 0)
4961 : {
4962 : // Check if there is at least one complex band.
4963 10 : bool hasAComplexBand = false;
4964 :
4965 19 : for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4966 : {
4967 11 : if (GDALDataTypeIsComplex(
4968 11 : GetRasterBand(rasterId)->GetRasterDataType()))
4969 : {
4970 2 : hasAComplexBand = true;
4971 2 : break;
4972 : }
4973 : }
4974 :
4975 10 : unsigned int nbSupportedDerivedDS = 0;
4976 : const DerivedDatasetDescription *poDDSDesc =
4977 10 : GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4978 :
4979 10 : int nNumDataset = 1;
4980 80 : for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4981 : ++derivedId)
4982 : {
4983 126 : if (hasAComplexBand ||
4984 126 : CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4985 : "complex")
4986 : {
4987 : oDerivedMetadataList.SetNameValue(
4988 : CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4989 : CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4990 22 : poDDSDesc[derivedId].pszDatasetName,
4991 22 : GetDescription()));
4992 :
4993 : CPLString osDesc(
4994 : CPLSPrintf("%s from %s",
4995 22 : poDDSDesc[derivedId].pszDatasetDescription,
4996 22 : GetDescription()));
4997 : oDerivedMetadataList.SetNameValue(
4998 : CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4999 22 : osDesc.c_str());
5000 :
5001 22 : nNumDataset++;
5002 : }
5003 : }
5004 : }
5005 10 : return oDerivedMetadataList.List();
5006 : }
5007 : #endif
5008 :
5009 70251 : return GDALMajorObject::GetMetadata(pszDomain);
5010 : }
5011 :
5012 : // clang-format off
5013 :
5014 : /**
5015 : * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
5016 : * \brief Set metadata.
5017 : *
5018 : * CAUTION: depending on the format, older values of the updated information
5019 : * might still be found in the file in a "ghost" state, even if no longer
5020 : * accessible through the GDAL API. This is for example the case of the GTiff
5021 : * format (this is not a exhaustive list)
5022 : *
5023 : * The C function GDALSetMetadata() does the same thing as this method.
5024 : *
5025 : * @param papszMetadata the metadata in name=value string list format to
5026 : * apply.
5027 : * @param pszDomain the domain of interest. Use "" or NULL for the default
5028 : * domain.
5029 : * @return CE_None on success, CE_Failure on failure and CE_Warning if the
5030 : * metadata has been accepted, but is likely not maintained persistently
5031 : * by the underlying object between sessions.
5032 : */
5033 :
5034 : /**
5035 : * \fn GDALDataset::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
5036 : * \brief Set single metadata item.
5037 : *
5038 : * CAUTION: depending on the format, older values of the updated information
5039 : * might still be found in the file in a "ghost" state, even if no longer
5040 : * accessible through the GDAL API. This is for example the case of the GTiff
5041 : * format (this is not a exhaustive list)
5042 : *
5043 : * The C function GDALSetMetadataItem() does the same thing as this method.
5044 : *
5045 : * @param pszName the key for the metadata item to fetch.
5046 : * @param pszValue the value to assign to the key.
5047 : * @param pszDomain the domain to set within, use NULL for the default domain.
5048 : *
5049 : * @return CE_None on success, or an error code on failure.
5050 : */
5051 :
5052 : // clang-format on
5053 :
5054 : /************************************************************************/
5055 : /* GetMetadataDomainList() */
5056 : /************************************************************************/
5057 :
5058 964 : char **GDALDataset::GetMetadataDomainList()
5059 : {
5060 964 : char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
5061 :
5062 : // Ensure that we do not duplicate DERIVED domain.
5063 1107 : if (GetRasterCount() > 0 &&
5064 143 : CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
5065 : {
5066 : currentDomainList =
5067 143 : CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
5068 : }
5069 964 : return currentDomainList;
5070 : }
5071 :
5072 : /************************************************************************/
5073 : /* GetDriverName() */
5074 : /************************************************************************/
5075 :
5076 : /** Return driver name.
5077 : * @return driver name.
5078 : */
5079 2056 : const char *GDALDataset::GetDriverName()
5080 : {
5081 2056 : if (poDriver)
5082 2044 : return poDriver->GetDescription();
5083 12 : return "";
5084 : }
5085 :
5086 : /************************************************************************/
5087 : /* GDALDatasetReleaseResultSet() */
5088 : /************************************************************************/
5089 :
5090 : /**
5091 : \brief Release results of ExecuteSQL().
5092 :
5093 : This function should only be used to deallocate OGRLayers resulting from
5094 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
5095 : results set before destroying the GDALDataset may cause errors.
5096 :
5097 : This function is the same as the C++ method GDALDataset::ReleaseResultSet()
5098 :
5099 : @since GDAL 2.0
5100 :
5101 : @param hDS the dataset handle.
5102 : @param hLayer the result of a previous ExecuteSQL() call.
5103 :
5104 : */
5105 3413 : void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)
5106 :
5107 : {
5108 3413 : VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
5109 :
5110 : #ifdef OGRAPISPY_ENABLED
5111 3413 : if (bOGRAPISpyEnabled)
5112 6 : OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
5113 : #endif
5114 :
5115 6826 : GDALDataset::FromHandle(hDS)->ReleaseResultSet(
5116 3413 : OGRLayer::FromHandle(hLayer));
5117 : }
5118 :
5119 : /************************************************************************/
5120 : /* GDALDatasetGetLayerCount() */
5121 : /************************************************************************/
5122 :
5123 : /**
5124 : \brief Get the number of layers in this dataset.
5125 :
5126 : This function is the same as the C++ method GDALDataset::GetLayerCount()
5127 :
5128 : @since GDAL 2.0
5129 :
5130 : @param hDS the dataset handle.
5131 : @return layer count.
5132 : */
5133 :
5134 1467 : int GDALDatasetGetLayerCount(GDALDatasetH hDS)
5135 :
5136 : {
5137 1467 : VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
5138 :
5139 : #ifdef OGRAPISPY_ENABLED
5140 1467 : if (bOGRAPISpyEnabled)
5141 2 : OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
5142 : #endif
5143 :
5144 1467 : return GDALDataset::FromHandle(hDS)->GetLayerCount();
5145 : }
5146 :
5147 : /************************************************************************/
5148 : /* GDALDatasetGetLayer() */
5149 : /************************************************************************/
5150 :
5151 : /**
5152 : \brief Fetch a layer by index.
5153 :
5154 : The returned layer remains owned by the
5155 : GDALDataset and should not be deleted by the application.
5156 :
5157 : This function is the same as the C++ method GDALDataset::GetLayer()
5158 :
5159 : @since GDAL 2.0
5160 :
5161 : @param hDS the dataset handle.
5162 : @param iLayer a layer number between 0 and GetLayerCount()-1.
5163 :
5164 : @return the layer, or NULL if iLayer is out of range or an error occurs.
5165 : */
5166 :
5167 9338 : OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)
5168 :
5169 : {
5170 9338 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
5171 :
5172 : OGRLayerH hLayer =
5173 9338 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
5174 :
5175 : #ifdef OGRAPISPY_ENABLED
5176 9338 : if (bOGRAPISpyEnabled)
5177 3 : OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
5178 : #endif
5179 :
5180 9338 : return hLayer;
5181 : }
5182 :
5183 : /************************************************************************/
5184 : /* GDALDatasetGetLayerByName() */
5185 : /************************************************************************/
5186 :
5187 : /**
5188 : \brief Fetch a layer by name.
5189 :
5190 : The returned layer remains owned by the
5191 : GDALDataset and should not be deleted by the application.
5192 :
5193 : This function is the same as the C++ method GDALDataset::GetLayerByName()
5194 :
5195 : @since GDAL 2.0
5196 :
5197 : @param hDS the dataset handle.
5198 : @param pszName the layer name of the layer to fetch.
5199 :
5200 : @return the layer, or NULL if Layer is not found or an error occurs.
5201 : */
5202 :
5203 3399 : OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)
5204 :
5205 : {
5206 3399 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
5207 :
5208 3399 : OGRLayerH hLayer = OGRLayer::ToHandle(
5209 3399 : GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
5210 :
5211 : #ifdef OGRAPISPY_ENABLED
5212 3399 : if (bOGRAPISpyEnabled)
5213 4 : OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
5214 : #endif
5215 :
5216 3399 : return hLayer;
5217 : }
5218 :
5219 : /************************************************************************/
5220 : /* GDALDatasetIsLayerPrivate() */
5221 : /************************************************************************/
5222 :
5223 : /**
5224 : \brief Returns true if the layer at the specified index is deemed a private or
5225 : system table, or an internal detail only.
5226 :
5227 : This function is the same as the C++ method GDALDataset::IsLayerPrivate()
5228 :
5229 : @since GDAL 3.4
5230 :
5231 : @param hDS the dataset handle.
5232 : @param iLayer a layer number between 0 and GetLayerCount()-1.
5233 :
5234 : @return true if the layer is a private or system table.
5235 : */
5236 :
5237 91 : int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)
5238 :
5239 : {
5240 91 : VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);
5241 :
5242 91 : const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);
5243 :
5244 91 : return res ? 1 : 0;
5245 : }
5246 :
5247 : /************************************************************************/
5248 : /* GetLayerIndex() */
5249 : /************************************************************************/
5250 :
5251 : /**
5252 : \brief Returns the index of the layer specified by name.
5253 :
5254 : @since GDAL 3.12
5255 :
5256 : @param pszName layer name (not NULL)
5257 :
5258 : @return an index >= 0, or -1 if not found.
5259 : */
5260 :
5261 3 : int GDALDataset::GetLayerIndex(const char *pszName) const
5262 : {
5263 3 : const int nLayerCount = GetLayerCount();
5264 3 : int iMatch = -1;
5265 6 : for (int i = 0; i < nLayerCount; ++i)
5266 : {
5267 5 : if (const auto poLayer = GetLayer(i))
5268 : {
5269 5 : const char *pszLayerName = poLayer->GetDescription();
5270 5 : if (strcmp(pszName, pszLayerName) == 0)
5271 : {
5272 2 : iMatch = i;
5273 2 : break;
5274 : }
5275 3 : else if (EQUAL(pszName, pszLayerName))
5276 : {
5277 0 : iMatch = i;
5278 : }
5279 : }
5280 : }
5281 3 : return iMatch;
5282 : }
5283 :
5284 : /************************************************************************/
5285 : /* GDALDatasetDeleteLayer() */
5286 : /************************************************************************/
5287 :
5288 : /**
5289 : \brief Delete the indicated layer from the datasource.
5290 :
5291 : If this function is supported
5292 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
5293 :
5294 : This method is the same as the C++ method GDALDataset::DeleteLayer().
5295 :
5296 : @since GDAL 2.0
5297 :
5298 : @param hDS the dataset handle.
5299 : @param iLayer the index of the layer to delete.
5300 :
5301 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
5302 : layers is not supported for this datasource.
5303 :
5304 : */
5305 41 : OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)
5306 :
5307 : {
5308 41 : VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
5309 :
5310 : #ifdef OGRAPISPY_ENABLED
5311 41 : if (bOGRAPISpyEnabled)
5312 2 : OGRAPISpy_DS_DeleteLayer(hDS, iLayer);
5313 : #endif
5314 :
5315 41 : return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
5316 : }
5317 :
5318 : /************************************************************************/
5319 : /* CreateLayer() */
5320 : /************************************************************************/
5321 :
5322 : /**
5323 : \brief This method attempts to create a new layer on the dataset with the
5324 : indicated name, coordinate system, geometry type.
5325 :
5326 : The papszOptions argument
5327 : can be used to control driver specific creation options. These options are
5328 : normally documented in the format specific documentation.
5329 : That function will try to validate the creation option list passed to the
5330 : driver with the GDALValidateCreationOptions() method. This check can be
5331 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5332 : to NO.
5333 :
5334 : Drivers should extend the ICreateLayer() method and not
5335 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5336 : delegating the actual work to ICreateLayer().
5337 :
5338 : This method is the same as the C function GDALDatasetCreateLayer() and the
5339 : deprecated OGR_DS_CreateLayer().
5340 :
5341 : Example:
5342 :
5343 : \code{.cpp}
5344 : #include "gdal.h"
5345 : #include "cpl_string.h"
5346 :
5347 : ...
5348 :
5349 : OGRLayer *poLayer;
5350 : char **papszOptions;
5351 :
5352 : if( !poDS->TestCapability( ODsCCreateLayer ) )
5353 : {
5354 : ...
5355 : }
5356 :
5357 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5358 : poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
5359 : papszOptions );
5360 : CSLDestroy( papszOptions );
5361 :
5362 : if( poLayer == NULL )
5363 : {
5364 : ...
5365 : }
5366 : \endcode
5367 :
5368 : @param pszName the name for the new layer. This should ideally not
5369 : match any existing layer on the datasource.
5370 : @param poSpatialRef the coordinate system to use for the new layer, or NULL if
5371 : no coordinate system is available.
5372 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5373 : are no constraints on the types geometry to be written.
5374 : @param papszOptions a StringList of name=value options. Options are driver
5375 : specific.
5376 :
5377 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5378 :
5379 : */
5380 :
5381 7907 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5382 : const OGRSpatialReference *poSpatialRef,
5383 : OGRwkbGeometryType eGType,
5384 : CSLConstList papszOptions)
5385 :
5386 : {
5387 7907 : if (eGType == wkbNone)
5388 : {
5389 496 : return CreateLayer(pszName, nullptr, papszOptions);
5390 : }
5391 : else
5392 : {
5393 14822 : OGRGeomFieldDefn oGeomFieldDefn("", eGType);
5394 7411 : oGeomFieldDefn.SetSpatialRef(poSpatialRef);
5395 7411 : return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5396 : }
5397 : }
5398 :
5399 : /**
5400 : \brief This method attempts to create a new layer on the dataset with the
5401 : indicated name and geometry field definition.
5402 :
5403 : When poGeomFieldDefn is not null, most drivers should honor
5404 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5405 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5406 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5407 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5408 : very few currently.
5409 :
5410 : Note that even if a geometry coordinate precision is set and a driver honors the
5411 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5412 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5413 : with the coordinate precision. That is they are assumed to be valid once their
5414 : coordinates are rounded to it. If it might not be the case, the user may set
5415 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5416 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5417 : the passed geometries.
5418 :
5419 : The papszOptions argument
5420 : can be used to control driver specific creation options. These options are
5421 : normally documented in the format specific documentation.
5422 : This function will try to validate the creation option list passed to the
5423 : driver with the GDALValidateCreationOptions() method. This check can be
5424 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5425 : to NO.
5426 :
5427 : Drivers should extend the ICreateLayer() method and not
5428 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5429 : delegating the actual work to ICreateLayer().
5430 :
5431 : This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().
5432 :
5433 : @param pszName the name for the new layer. This should ideally not
5434 : match any existing layer on the datasource.
5435 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5436 : or NULL if there is no geometry field.
5437 : @param papszOptions a StringList of name=value options. Options are driver
5438 : specific.
5439 :
5440 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5441 : @since 3.9
5442 :
5443 : */
5444 :
5445 9060 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5446 : const OGRGeomFieldDefn *poGeomFieldDefn,
5447 : CSLConstList papszOptions)
5448 :
5449 : {
5450 9060 : if (CPLTestBool(
5451 : CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
5452 : {
5453 9060 : ValidateLayerCreationOptions(papszOptions);
5454 : }
5455 :
5456 : OGRLayer *poLayer;
5457 9060 : if (poGeomFieldDefn)
5458 : {
5459 8311 : OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);
5460 8404 : if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&
5461 93 : !TestCapability(ODsCCurveGeometries))
5462 : {
5463 23 : oGeomFieldDefn.SetType(
5464 : OGR_GT_GetLinear(poGeomFieldDefn->GetType()));
5465 : }
5466 :
5467 8311 : poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5468 : }
5469 : else
5470 : {
5471 749 : poLayer = ICreateLayer(pszName, nullptr, papszOptions);
5472 : }
5473 : #ifdef DEBUG
5474 9130 : if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
5475 70 : !poLayer->TestCapability(OLCCurveGeometries))
5476 : {
5477 0 : CPLError(CE_Warning, CPLE_AppDefined,
5478 : "Inconsistent driver: Layer geometry type is non-linear, but "
5479 : "TestCapability(OLCCurveGeometries) returns FALSE.");
5480 : }
5481 : #endif
5482 :
5483 9060 : return poLayer;
5484 : }
5485 :
5486 : //! @cond Doxygen_Suppress
5487 :
5488 : // Technical override to avoid ambiguous choice between the old and new
5489 : // new CreateLayer() signatures.
5490 11 : OGRLayer *GDALDataset::CreateLayer(const char *pszName)
5491 : {
5492 22 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5493 22 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5494 : }
5495 :
5496 : // Technical override to avoid ambiguous choice between the old and new
5497 : // new CreateLayer() signatures.
5498 1 : OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)
5499 : {
5500 2 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5501 2 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5502 : }
5503 :
5504 : //!@endcond
5505 :
5506 : /************************************************************************/
5507 : /* GDALDatasetCreateLayer() */
5508 : /************************************************************************/
5509 :
5510 : /**
5511 : \brief This function attempts to create a new layer on the dataset with the
5512 : indicated name, coordinate system, geometry type.
5513 :
5514 : The papszOptions argument can be used to control driver specific creation
5515 : options. These options are normally documented in the format specific
5516 : documentation.
5517 :
5518 : This method is the same as the C++ method GDALDataset::CreateLayer().
5519 :
5520 : Example:
5521 :
5522 : \code{.c}
5523 : #include "gdal.h"
5524 : #include "cpl_string.h"
5525 :
5526 : ...
5527 :
5528 : OGRLayerH hLayer;
5529 : char **papszOptions;
5530 :
5531 : if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
5532 : {
5533 : ...
5534 : }
5535 :
5536 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5537 : hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
5538 : papszOptions );
5539 : CSLDestroy( papszOptions );
5540 :
5541 : if( hLayer == NULL )
5542 : {
5543 : ...
5544 : }
5545 : \endcode
5546 :
5547 : @since GDAL 2.0
5548 :
5549 : @param hDS the dataset handle
5550 : @param pszName the name for the new layer. This should ideally not
5551 : match any existing layer on the datasource.
5552 : @param hSpatialRef the coordinate system to use for the new layer, or NULL if
5553 : no coordinate system is available.
5554 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5555 : are no constraints on the types geometry to be written.
5556 : @param papszOptions a StringList of name=value options. Options are driver
5557 : specific.
5558 :
5559 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5560 :
5561 : */
5562 :
5563 6070 : OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,
5564 : OGRSpatialReferenceH hSpatialRef,
5565 : OGRwkbGeometryType eGType,
5566 : CSLConstList papszOptions)
5567 :
5568 : {
5569 6070 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
5570 :
5571 6070 : if (pszName == nullptr)
5572 : {
5573 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5574 : "Name was NULL in GDALDatasetCreateLayer");
5575 0 : return nullptr;
5576 : }
5577 :
5578 : OGRLayerH hLayer =
5579 12140 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5580 6070 : pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,
5581 : const_cast<char **>(papszOptions)));
5582 :
5583 : #ifdef OGRAPISPY_ENABLED
5584 6070 : if (bOGRAPISpyEnabled)
5585 8 : OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,
5586 : const_cast<char **>(papszOptions), hLayer);
5587 : #endif
5588 :
5589 6070 : return hLayer;
5590 : }
5591 :
5592 : /************************************************************************/
5593 : /* GDALDatasetCreateLayerFromGeomFieldDefn() */
5594 : /************************************************************************/
5595 :
5596 : /**
5597 : \brief This function attempts to create a new layer on the dataset with the
5598 : indicated name and geometry field.
5599 :
5600 : When poGeomFieldDefn is not null, most drivers should honor
5601 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5602 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5603 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5604 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5605 : very few currently.
5606 :
5607 : Note that even if a geometry coordinate precision is set and a driver honors the
5608 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5609 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5610 : with the coordinate precision. That is they are assumed to be valid once their
5611 : coordinates are rounded to it. If it might not be the case, the user may set
5612 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5613 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5614 : the passed geometries.
5615 :
5616 : The papszOptions argument can be used to control driver specific creation
5617 : options. These options are normally documented in the format specific
5618 : documentation.
5619 :
5620 : This method is the same as the C++ method GDALDataset::CreateLayer().
5621 :
5622 : @param hDS the dataset handle
5623 : @param pszName the name for the new layer. This should ideally not
5624 : match any existing layer on the datasource.
5625 : @param hGeomFieldDefn the geometry field definition. May be NULL to indicate
5626 : a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()
5627 : for drivers supporting that interface).
5628 : @param papszOptions a StringList of name=value options. Options are driver
5629 : specific.
5630 :
5631 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5632 :
5633 : @since GDAL 3.9
5634 :
5635 : */
5636 :
5637 : OGRLayerH
5638 14 : GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,
5639 : OGRGeomFieldDefnH hGeomFieldDefn,
5640 : CSLConstList papszOptions)
5641 :
5642 : {
5643 14 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);
5644 :
5645 14 : if (!pszName)
5646 : {
5647 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5648 : "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");
5649 0 : return nullptr;
5650 : }
5651 :
5652 : OGRLayerH hLayer =
5653 28 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5654 14 : pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),
5655 : papszOptions));
5656 14 : return hLayer;
5657 : }
5658 :
5659 : /************************************************************************/
5660 : /* GDALDatasetCopyLayer() */
5661 : /************************************************************************/
5662 :
5663 : /**
5664 : \brief Duplicate an existing layer.
5665 :
5666 : This function creates a new layer, duplicate the field definitions of the
5667 : source layer and then duplicate each features of the source layer.
5668 : The papszOptions argument
5669 : can be used to control driver specific creation options. These options are
5670 : normally documented in the format specific documentation.
5671 : The source layer may come from another dataset.
5672 :
5673 : This method is the same as the C++ method GDALDataset::CopyLayer()
5674 :
5675 : @since GDAL 2.0
5676 :
5677 : @param hDS the dataset handle.
5678 : @param hSrcLayer source layer.
5679 : @param pszNewName the name of the layer to create.
5680 : @param papszOptions a StringList of name=value options. Options are driver
5681 : specific.
5682 :
5683 : @return a handle to the layer, or NULL if an error occurs.
5684 : */
5685 18 : OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,
5686 : const char *pszNewName,
5687 : CSLConstList papszOptions)
5688 :
5689 : {
5690 18 : VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
5691 18 : VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
5692 18 : VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
5693 :
5694 36 : return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(
5695 : OGRLayer::FromHandle(hSrcLayer), pszNewName,
5696 36 : const_cast<char **>(papszOptions)));
5697 : }
5698 :
5699 : /************************************************************************/
5700 : /* GDALDatasetExecuteSQL() */
5701 : /************************************************************************/
5702 :
5703 : /**
5704 : \brief Execute an SQL statement against the data store.
5705 :
5706 : The result of an SQL query is either NULL for statements that are in error,
5707 : or that have no results set, or an OGRLayer pointer representing a results
5708 : set from the query. Note that this OGRLayer is in addition to the layers
5709 : in the data store and must be destroyed with
5710 : ReleaseResultSet() before the dataset is closed
5711 : (destroyed).
5712 :
5713 : This method is the same as the C++ method GDALDataset::ExecuteSQL()
5714 :
5715 : For more information on the SQL dialect supported internally by OGR
5716 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
5717 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
5718 : to the underlying RDBMS.
5719 :
5720 : Starting with OGR 1.10, the <a
5721 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
5722 : also be used.
5723 :
5724 : @since GDAL 2.0
5725 :
5726 : @param hDS the dataset handle.
5727 : @param pszStatement the SQL statement to execute.
5728 : @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
5729 :
5730 : @param pszDialect allows control of the statement dialect. If set to NULL, the
5731 : OGR SQL engine will be used, except for RDBMS drivers that will use their
5732 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
5733 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
5734 :
5735 : @return an OGRLayer containing the results of the query. Deallocate with
5736 : GDALDatasetReleaseResultSet().
5737 :
5738 : */
5739 :
5740 10456 : OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,
5741 : OGRGeometryH hSpatialFilter,
5742 : const char *pszDialect)
5743 :
5744 : {
5745 10456 : VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
5746 :
5747 : OGRLayerH hLayer =
5748 20912 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(
5749 10456 : pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));
5750 :
5751 : #ifdef OGRAPISPY_ENABLED
5752 10456 : if (bOGRAPISpyEnabled)
5753 4 : OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,
5754 : hLayer);
5755 : #endif
5756 :
5757 10456 : return hLayer;
5758 : }
5759 :
5760 : /************************************************************************/
5761 : /* GDALDatasetAbortSQL() */
5762 : /************************************************************************/
5763 :
5764 : /**
5765 : \brief Abort any SQL statement running in the data store.
5766 :
5767 : This function can be safely called from any thread (pending that the dataset
5768 : object is still alive). Driver implementations will make sure that it can be
5769 : called in a thread-safe way.
5770 :
5771 : This might not be implemented by all drivers. At time of writing, only SQLite,
5772 : GPKG and PG drivers implement it
5773 :
5774 : This method is the same as the C++ method GDALDataset::AbortSQL()
5775 :
5776 : @since GDAL 3.2.0
5777 :
5778 : @param hDS the dataset handle.
5779 :
5780 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
5781 : is not supported for this datasource. .
5782 :
5783 : */
5784 :
5785 6 : OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)
5786 :
5787 : {
5788 6 : VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);
5789 6 : return GDALDataset::FromHandle(hDS)->AbortSQL();
5790 : }
5791 :
5792 : /************************************************************************/
5793 : /* GDALDatasetGetStyleTable() */
5794 : /************************************************************************/
5795 :
5796 : /**
5797 : \brief Returns dataset style table.
5798 :
5799 : This function is the same as the C++ method GDALDataset::GetStyleTable()
5800 :
5801 : @since GDAL 2.0
5802 :
5803 : @param hDS the dataset handle
5804 : @return handle to a style table which should not be modified or freed by the
5805 : caller.
5806 : */
5807 :
5808 6 : OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)
5809 :
5810 : {
5811 6 : VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
5812 :
5813 : return reinterpret_cast<OGRStyleTableH>(
5814 6 : GDALDataset::FromHandle(hDS)->GetStyleTable());
5815 : }
5816 :
5817 : /************************************************************************/
5818 : /* GDALDatasetSetStyleTableDirectly() */
5819 : /************************************************************************/
5820 :
5821 : /**
5822 : \brief Set dataset style table.
5823 :
5824 : This function operate exactly as GDALDatasetSetStyleTable() except that it
5825 : assumes ownership of the passed table.
5826 :
5827 : This function is the same as the C++ method
5828 : GDALDataset::SetStyleTableDirectly()
5829 :
5830 : @since GDAL 2.0
5831 :
5832 : @param hDS the dataset handle
5833 : @param hStyleTable style table handle to set
5834 :
5835 : */
5836 :
5837 0 : void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,
5838 : OGRStyleTableH hStyleTable)
5839 :
5840 : {
5841 0 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
5842 :
5843 0 : GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(
5844 0 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5845 : }
5846 :
5847 : /************************************************************************/
5848 : /* GDALDatasetSetStyleTable() */
5849 : /************************************************************************/
5850 :
5851 : /**
5852 : \brief Set dataset style table.
5853 :
5854 : This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
5855 : it assumes ownership of the passed table.
5856 :
5857 : This function is the same as the C++ method GDALDataset::SetStyleTable()
5858 :
5859 : @since GDAL 2.0
5860 :
5861 : @param hDS the dataset handle
5862 : @param hStyleTable style table handle to set
5863 :
5864 : */
5865 :
5866 5 : void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)
5867 :
5868 : {
5869 5 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
5870 5 : VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
5871 :
5872 5 : GDALDataset::FromHandle(hDS)->SetStyleTable(
5873 5 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5874 : }
5875 :
5876 : /************************************************************************/
5877 : /* ValidateLayerCreationOptions() */
5878 : /************************************************************************/
5879 :
5880 : //! @cond Doxygen_Suppress
5881 9060 : int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)
5882 : {
5883 : const char *pszOptionList =
5884 9060 : GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5885 9060 : if (pszOptionList == nullptr && poDriver != nullptr)
5886 : {
5887 : pszOptionList =
5888 9023 : poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5889 : }
5890 18120 : CPLString osDataset;
5891 9060 : osDataset.Printf("dataset %s", GetDescription());
5892 9060 : return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",
5893 18120 : osDataset);
5894 : }
5895 :
5896 : //! @endcond
5897 :
5898 : /************************************************************************/
5899 : /* Release() */
5900 : /************************************************************************/
5901 :
5902 : /**
5903 : \brief Drop a reference to this dataset, and if the reference count drops to one
5904 : close (destroy) the dataset.
5905 :
5906 : This method is the same as the C function OGRReleaseDataSource().
5907 :
5908 : @deprecated. In GDAL 2, use GDALClose() instead
5909 :
5910 : @return OGRERR_NONE on success or an error code.
5911 : */
5912 :
5913 4181 : OGRErr GDALDataset::Release()
5914 :
5915 : {
5916 4181 : ReleaseRef();
5917 4181 : return OGRERR_NONE;
5918 : }
5919 :
5920 : /************************************************************************/
5921 : /* GetRefCount() */
5922 : /************************************************************************/
5923 :
5924 : /**
5925 : \brief Fetch reference count.
5926 :
5927 : This method is the same as the C function OGR_DS_GetRefCount().
5928 :
5929 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5930 :
5931 : @return the current reference count for the datasource object itself.
5932 : */
5933 :
5934 4721 : int GDALDataset::GetRefCount() const
5935 : {
5936 4721 : return nRefCount;
5937 : }
5938 :
5939 : /************************************************************************/
5940 : /* GetSummaryRefCount() */
5941 : /************************************************************************/
5942 :
5943 : /**
5944 : \brief Fetch reference count of datasource and all owned layers.
5945 :
5946 : This method is the same as the C function OGR_DS_GetSummaryRefCount().
5947 :
5948 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5949 :
5950 : @deprecated
5951 :
5952 : @return the current summary reference count for the datasource and its layers.
5953 : */
5954 :
5955 0 : int GDALDataset::GetSummaryRefCount() const
5956 :
5957 : {
5958 0 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5959 0 : int nSummaryCount = nRefCount;
5960 0 : GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
5961 :
5962 0 : for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)
5963 0 : nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
5964 :
5965 0 : return nSummaryCount;
5966 : }
5967 :
5968 : /************************************************************************/
5969 : /* ICreateLayer() */
5970 : /************************************************************************/
5971 :
5972 : /**
5973 : \brief This method attempts to create a new layer on the dataset with the
5974 : indicated name, coordinate system, geometry type.
5975 :
5976 : This method is reserved to implementation by drivers.
5977 :
5978 : The papszOptions argument can be used to control driver specific creation
5979 : options. These options are normally documented in the format specific
5980 : documentation.
5981 :
5982 : @param pszName the name for the new layer. This should ideally not
5983 : match any existing layer on the datasource.
5984 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5985 : or NULL if there is no geometry field.
5986 : @param papszOptions a StringList of name=value options. Options are driver
5987 : specific.
5988 :
5989 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5990 :
5991 : @since GDAL 2.0 (prototype modified in 3.9)
5992 : */
5993 :
5994 : OGRLayer *
5995 16 : GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,
5996 : CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,
5997 : CPL_UNUSED CSLConstList papszOptions)
5998 :
5999 : {
6000 16 : CPLError(CE_Failure, CPLE_NotSupported,
6001 : "CreateLayer() not supported by this dataset.");
6002 :
6003 16 : return nullptr;
6004 : }
6005 :
6006 : /************************************************************************/
6007 : /* CopyLayer() */
6008 : /************************************************************************/
6009 :
6010 : /**
6011 : \brief Duplicate an existing layer.
6012 :
6013 : This method creates a new layer, duplicate the field definitions of the
6014 : source layer and then duplicate each features of the source layer.
6015 : The papszOptions argument
6016 : can be used to control driver specific creation options. These options are
6017 : normally documented in the format specific documentation.
6018 : The source layer may come from another dataset.
6019 :
6020 : This method is the same as the C function GDALDatasetCopyLayer() and the
6021 : deprecated OGR_DS_CopyLayer().
6022 :
6023 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6024 :
6025 : @param poSrcLayer source layer.
6026 : @param pszNewName the name of the layer to create.
6027 : @param papszOptions a StringList of name=value options. Options are driver
6028 : specific. There is a common option to set output layer
6029 : spatial reference: DST_SRSWKT. The option should be in
6030 : WKT format. Starting with GDAL 3.7, the common option
6031 : COPY_MD can be set to NO to prevent the default copying
6032 : of the metadata from the source layer to the target layer.
6033 :
6034 : @return a handle to the layer, or NULL if an error occurs.
6035 : */
6036 :
6037 148 : OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
6038 : char **papszOptions)
6039 :
6040 : {
6041 : /* -------------------------------------------------------------------- */
6042 : /* Create the layer. */
6043 : /* -------------------------------------------------------------------- */
6044 148 : if (!TestCapability(ODsCCreateLayer))
6045 : {
6046 0 : CPLError(CE_Failure, CPLE_NotSupported,
6047 : "This datasource does not support creation of layers.");
6048 0 : return nullptr;
6049 : }
6050 :
6051 148 : const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
6052 296 : OGRSpatialReference oDstSpaRef(pszSRSWKT);
6053 148 : oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
6054 148 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
6055 148 : OGRLayer *poDstLayer = nullptr;
6056 :
6057 296 : CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));
6058 148 : aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr);
6059 148 : aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr);
6060 :
6061 148 : CPLErrorReset();
6062 148 : const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
6063 148 : if (nSrcGeomFieldCount == 1)
6064 : {
6065 96 : OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
6066 96 : if (pszSRSWKT)
6067 5 : oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);
6068 96 : poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,
6069 96 : aosCleanedUpOptions.List());
6070 : }
6071 : else
6072 : {
6073 : poDstLayer =
6074 52 : ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());
6075 : }
6076 :
6077 148 : if (poDstLayer == nullptr)
6078 0 : return nullptr;
6079 :
6080 148 : if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))
6081 : {
6082 147 : char **papszMD = poSrcLayer->GetMetadata();
6083 147 : if (papszMD)
6084 8 : poDstLayer->SetMetadata(papszMD);
6085 : }
6086 :
6087 : /* -------------------------------------------------------------------- */
6088 : /* Add fields. Default to copy all fields, and make sure to */
6089 : /* establish a mapping between indices, rather than names, in */
6090 : /* case the target datasource has altered it (e.g. Shapefile */
6091 : /* limited to 10 char field names). */
6092 : /* -------------------------------------------------------------------- */
6093 148 : const int nSrcFieldCount = poSrcDefn->GetFieldCount();
6094 :
6095 : // Initialize the index-to-index map to -1's.
6096 296 : std::vector<int> anMap(nSrcFieldCount, -1);
6097 :
6098 : // Caution: At the time of writing, the MapInfo driver
6099 : // returns NULL until a field has been added.
6100 148 : OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
6101 148 : int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
6102 329 : for (int iField = 0; iField < nSrcFieldCount; ++iField)
6103 : {
6104 181 : OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
6105 362 : OGRFieldDefn oFieldDefn(poSrcFieldDefn);
6106 :
6107 : // The field may have been already created at layer creation.
6108 181 : int iDstField = -1;
6109 181 : if (poDstFDefn)
6110 181 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
6111 181 : if (iDstField >= 0)
6112 : {
6113 0 : anMap[iField] = iDstField;
6114 : }
6115 181 : else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)
6116 : {
6117 : // Now that we've created a field, GetLayerDefn() won't return NULL.
6118 181 : if (poDstFDefn == nullptr)
6119 0 : poDstFDefn = poDstLayer->GetLayerDefn();
6120 :
6121 : // Sanity check: if it fails, the driver is buggy.
6122 362 : if (poDstFDefn != nullptr &&
6123 181 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
6124 : {
6125 0 : CPLError(CE_Warning, CPLE_AppDefined,
6126 : "The output driver has claimed to have added the %s "
6127 : "field, but it did not!",
6128 : oFieldDefn.GetNameRef());
6129 : }
6130 : else
6131 : {
6132 181 : anMap[iField] = nDstFieldCount;
6133 181 : ++nDstFieldCount;
6134 : }
6135 : }
6136 : }
6137 :
6138 : /* -------------------------------------------------------------------- */
6139 148 : std::unique_ptr<OGRCoordinateTransformation> poCT;
6140 148 : const OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
6141 148 : if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&
6142 0 : sourceSRS->IsSame(&oDstSpaRef) == FALSE)
6143 : {
6144 0 : poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));
6145 0 : if (nullptr == poCT)
6146 : {
6147 0 : CPLError(CE_Failure, CPLE_NotSupported,
6148 : "This input/output spatial reference is not supported.");
6149 0 : return nullptr;
6150 : }
6151 : }
6152 : /* -------------------------------------------------------------------- */
6153 : /* Create geometry fields. */
6154 : /* -------------------------------------------------------------------- */
6155 149 : if (nSrcGeomFieldCount > 1 &&
6156 1 : TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
6157 : {
6158 :
6159 3 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6160 : {
6161 2 : if (nullptr == pszSRSWKT)
6162 : {
6163 2 : poDstLayer->CreateGeomField(
6164 2 : poSrcDefn->GetGeomFieldDefn(iField));
6165 : }
6166 : else
6167 : {
6168 : OGRGeomFieldDefn *pDstGeomFieldDefn =
6169 0 : poSrcDefn->GetGeomFieldDefn(iField);
6170 0 : pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
6171 0 : poDstLayer->CreateGeomField(pDstGeomFieldDefn);
6172 : }
6173 : }
6174 : }
6175 :
6176 : /* -------------------------------------------------------------------- */
6177 : /* Check if the destination layer supports transactions and set a */
6178 : /* default number of features in a single transaction. */
6179 : /* -------------------------------------------------------------------- */
6180 : const int nGroupTransactions =
6181 148 : poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
6182 :
6183 : /* -------------------------------------------------------------------- */
6184 : /* Transfer features. */
6185 : /* -------------------------------------------------------------------- */
6186 148 : poSrcLayer->ResetReading();
6187 :
6188 148 : if (nGroupTransactions <= 0)
6189 : {
6190 : while (true)
6191 : {
6192 : auto poFeature =
6193 2064 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
6194 :
6195 2064 : if (poFeature == nullptr)
6196 138 : break;
6197 :
6198 1926 : CPLErrorReset();
6199 : auto poDstFeature =
6200 1926 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
6201 :
6202 1926 : if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=
6203 : OGRERR_NONE)
6204 : {
6205 0 : CPLError(CE_Failure, CPLE_AppDefined,
6206 : "Unable to translate feature " CPL_FRMT_GIB
6207 : " from layer %s.",
6208 0 : poFeature->GetFID(), poSrcDefn->GetName());
6209 0 : return poDstLayer;
6210 : }
6211 :
6212 1926 : if (nullptr != poCT)
6213 : {
6214 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6215 : {
6216 0 : OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
6217 0 : if (nullptr == pGeom)
6218 0 : continue;
6219 :
6220 0 : const OGRErr eErr = pGeom->transform(poCT.get());
6221 0 : if (eErr == OGRERR_NONE)
6222 0 : continue;
6223 :
6224 0 : CPLError(CE_Failure, CPLE_AppDefined,
6225 : "Unable to transform geometry " CPL_FRMT_GIB
6226 : " from layer %s.",
6227 0 : poFeature->GetFID(), poSrcDefn->GetName());
6228 0 : return poDstLayer;
6229 : }
6230 : }
6231 :
6232 1926 : poDstFeature->SetFID(poFeature->GetFID());
6233 :
6234 1926 : CPLErrorReset();
6235 1926 : if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)
6236 : {
6237 0 : return poDstLayer;
6238 : }
6239 1926 : }
6240 : }
6241 : else
6242 : {
6243 10 : std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;
6244 : try
6245 : {
6246 10 : apoDstFeatures.resize(nGroupTransactions);
6247 : }
6248 0 : catch (const std::exception &e)
6249 : {
6250 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
6251 0 : return poDstLayer;
6252 : }
6253 10 : bool bStopTransfer = false;
6254 72 : while (!bStopTransfer)
6255 : {
6256 : /* --------------------------------------------------------------------
6257 : */
6258 : /* Fill the array with features. */
6259 : /* --------------------------------------------------------------------
6260 : */
6261 : // Number of features in the temporary array.
6262 62 : int nFeatCount = 0; // Used after for.
6263 7072 : for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)
6264 : {
6265 : auto poFeature =
6266 7020 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
6267 :
6268 7020 : if (poFeature == nullptr)
6269 : {
6270 10 : bStopTransfer = true;
6271 10 : break;
6272 : }
6273 :
6274 7010 : CPLErrorReset();
6275 7010 : apoDstFeatures[nFeatCount] =
6276 14020 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
6277 :
6278 14020 : if (apoDstFeatures[nFeatCount]->SetFrom(
6279 14020 : poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)
6280 : {
6281 0 : CPLError(CE_Failure, CPLE_AppDefined,
6282 : "Unable to translate feature " CPL_FRMT_GIB
6283 : " from layer %s.",
6284 0 : poFeature->GetFID(), poSrcDefn->GetName());
6285 0 : bStopTransfer = true;
6286 0 : poFeature.reset();
6287 0 : break;
6288 : }
6289 :
6290 7010 : if (nullptr != poCT)
6291 : {
6292 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6293 : {
6294 : OGRGeometry *pGeom =
6295 0 : apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);
6296 0 : if (nullptr == pGeom)
6297 0 : continue;
6298 :
6299 0 : const OGRErr eErr = pGeom->transform(poCT.get());
6300 0 : if (eErr == OGRERR_NONE)
6301 0 : continue;
6302 :
6303 0 : CPLError(CE_Failure, CPLE_AppDefined,
6304 : "Unable to transform geometry " CPL_FRMT_GIB
6305 : " from layer %s.",
6306 0 : poFeature->GetFID(), poSrcDefn->GetName());
6307 0 : bStopTransfer = true;
6308 0 : poFeature.reset();
6309 0 : break;
6310 : }
6311 : }
6312 :
6313 7010 : if (poFeature)
6314 : {
6315 7010 : apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());
6316 : }
6317 : }
6318 :
6319 62 : CPLErrorReset();
6320 62 : bool bStopTransaction = false;
6321 124 : while (!bStopTransaction)
6322 : {
6323 62 : bStopTransaction = true;
6324 62 : if (poDstLayer->StartTransaction() != OGRERR_NONE)
6325 0 : break;
6326 7072 : for (int i = 0; i < nFeatCount; ++i)
6327 : {
6328 7010 : if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=
6329 : OGRERR_NONE)
6330 : {
6331 0 : bStopTransfer = true;
6332 0 : bStopTransaction = false;
6333 0 : break;
6334 : }
6335 7010 : apoDstFeatures[i].reset();
6336 : }
6337 62 : if (bStopTransaction)
6338 : {
6339 62 : if (poDstLayer->CommitTransaction() != OGRERR_NONE)
6340 0 : break;
6341 : }
6342 : else
6343 : {
6344 0 : poDstLayer->RollbackTransaction();
6345 : }
6346 : }
6347 : }
6348 : }
6349 :
6350 148 : return poDstLayer;
6351 : }
6352 :
6353 : /************************************************************************/
6354 : /* DeleteLayer() */
6355 : /************************************************************************/
6356 :
6357 : /**
6358 : \fn GDALDataset::DeleteLayer(int)
6359 : \brief Delete the indicated layer from the datasource.
6360 :
6361 : If this method is supported
6362 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
6363 :
6364 : This method is the same as the C function GDALDatasetDeleteLayer() and the
6365 : deprecated OGR_DS_DeleteLayer().
6366 :
6367 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6368 :
6369 : @param iLayer the index of the layer to delete.
6370 :
6371 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
6372 : layers is not supported for this datasource.
6373 :
6374 : */
6375 :
6376 389 : OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)
6377 :
6378 : {
6379 389 : CPLError(CE_Failure, CPLE_NotSupported,
6380 : "DeleteLayer() not supported by this dataset.");
6381 :
6382 389 : return OGRERR_UNSUPPORTED_OPERATION;
6383 : }
6384 :
6385 : /************************************************************************/
6386 : /* GetLayerByName() */
6387 : /************************************************************************/
6388 :
6389 : /**
6390 : \brief Fetch a layer by name.
6391 :
6392 : The returned layer remains owned by the
6393 : GDALDataset and should not be deleted by the application.
6394 :
6395 : This method is the same as the C function GDALDatasetGetLayerByName() and the
6396 : deprecated OGR_DS_GetLayerByName().
6397 :
6398 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6399 :
6400 : @param pszName the layer name of the layer to fetch.
6401 :
6402 : @return the layer, or NULL if Layer is not found or an error occurs.
6403 : */
6404 :
6405 29644 : OGRLayer *GDALDataset::GetLayerByName(const char *pszName)
6406 :
6407 : {
6408 59288 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
6409 :
6410 29644 : if (!pszName)
6411 0 : return nullptr;
6412 :
6413 : // First a case sensitive check.
6414 932158 : for (int i = 0; i < GetLayerCount(); ++i)
6415 : {
6416 914100 : OGRLayer *poLayer = GetLayer(i);
6417 :
6418 914100 : if (strcmp(pszName, poLayer->GetName()) == 0)
6419 11586 : return poLayer;
6420 : }
6421 :
6422 : // Then case insensitive.
6423 893644 : for (int i = 0; i < GetLayerCount(); ++i)
6424 : {
6425 875808 : OGRLayer *poLayer = GetLayer(i);
6426 :
6427 875808 : if (EQUAL(pszName, poLayer->GetName()))
6428 222 : return poLayer;
6429 : }
6430 :
6431 17836 : return nullptr;
6432 : }
6433 :
6434 : //! @cond Doxygen_Suppress
6435 : /************************************************************************/
6436 : /* ProcessSQLCreateIndex() */
6437 : /* */
6438 : /* The correct syntax for creating an index in our dialect of */
6439 : /* SQL is: */
6440 : /* */
6441 : /* CREATE INDEX ON <layername> USING <columnname> */
6442 : /************************************************************************/
6443 :
6444 28 : OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)
6445 :
6446 : {
6447 28 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6448 :
6449 : /* -------------------------------------------------------------------- */
6450 : /* Do some general syntax checking. */
6451 : /* -------------------------------------------------------------------- */
6452 56 : if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||
6453 84 : !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||
6454 28 : !EQUAL(papszTokens[4], "USING"))
6455 : {
6456 0 : CSLDestroy(papszTokens);
6457 0 : CPLError(CE_Failure, CPLE_AppDefined,
6458 : "Syntax error in CREATE INDEX command.\n"
6459 : "Was '%s'\n"
6460 : "Should be of form 'CREATE INDEX ON <table> USING <field>'",
6461 : pszSQLCommand);
6462 0 : return OGRERR_FAILURE;
6463 : }
6464 :
6465 : /* -------------------------------------------------------------------- */
6466 : /* Find the named layer. */
6467 : /* -------------------------------------------------------------------- */
6468 28 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6469 28 : if (poLayer == nullptr)
6470 : {
6471 0 : CPLError(CE_Failure, CPLE_AppDefined,
6472 : "CREATE INDEX ON failed, no such layer as `%s'.",
6473 0 : papszTokens[3]);
6474 0 : CSLDestroy(papszTokens);
6475 0 : return OGRERR_FAILURE;
6476 : }
6477 :
6478 : /* -------------------------------------------------------------------- */
6479 : /* Does this layer even support attribute indexes? */
6480 : /* -------------------------------------------------------------------- */
6481 28 : if (poLayer->GetIndex() == nullptr)
6482 : {
6483 0 : CPLError(CE_Failure, CPLE_AppDefined,
6484 : "CREATE INDEX ON not supported by this driver.");
6485 0 : CSLDestroy(papszTokens);
6486 0 : return OGRERR_FAILURE;
6487 : }
6488 :
6489 : /* -------------------------------------------------------------------- */
6490 : /* Find the named field. */
6491 : /* -------------------------------------------------------------------- */
6492 28 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6493 :
6494 28 : CSLDestroy(papszTokens);
6495 :
6496 28 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6497 : {
6498 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6499 : pszSQLCommand);
6500 0 : return OGRERR_FAILURE;
6501 : }
6502 :
6503 : /* -------------------------------------------------------------------- */
6504 : /* Attempt to create the index. */
6505 : /* -------------------------------------------------------------------- */
6506 28 : OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
6507 28 : if (eErr == OGRERR_NONE)
6508 : {
6509 28 : eErr = poLayer->GetIndex()->IndexAllFeatures(i);
6510 : }
6511 : else
6512 : {
6513 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
6514 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
6515 : }
6516 :
6517 28 : return eErr;
6518 : }
6519 :
6520 : /************************************************************************/
6521 : /* ProcessSQLDropIndex() */
6522 : /* */
6523 : /* The correct syntax for dropping one or more indexes in */
6524 : /* the OGR SQL dialect is: */
6525 : /* */
6526 : /* DROP INDEX ON <layername> [USING <columnname>] */
6527 : /************************************************************************/
6528 :
6529 10 : OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)
6530 :
6531 : {
6532 10 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6533 :
6534 : /* -------------------------------------------------------------------- */
6535 : /* Do some general syntax checking. */
6536 : /* -------------------------------------------------------------------- */
6537 20 : if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||
6538 10 : !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||
6539 30 : !EQUAL(papszTokens[2], "ON") ||
6540 10 : (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))
6541 : {
6542 0 : CSLDestroy(papszTokens);
6543 0 : CPLError(CE_Failure, CPLE_AppDefined,
6544 : "Syntax error in DROP INDEX command.\n"
6545 : "Was '%s'\n"
6546 : "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
6547 : pszSQLCommand);
6548 0 : return OGRERR_FAILURE;
6549 : }
6550 :
6551 : /* -------------------------------------------------------------------- */
6552 : /* Find the named layer. */
6553 : /* -------------------------------------------------------------------- */
6554 10 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6555 10 : if (poLayer == nullptr)
6556 : {
6557 0 : CPLError(CE_Failure, CPLE_AppDefined,
6558 : "DROP INDEX ON failed, no such layer as `%s'.",
6559 0 : papszTokens[3]);
6560 0 : CSLDestroy(papszTokens);
6561 0 : return OGRERR_FAILURE;
6562 : }
6563 :
6564 : /* -------------------------------------------------------------------- */
6565 : /* Does this layer even support attribute indexes? */
6566 : /* -------------------------------------------------------------------- */
6567 10 : if (poLayer->GetIndex() == nullptr)
6568 : {
6569 0 : CPLError(CE_Failure, CPLE_AppDefined,
6570 : "Indexes not supported by this driver.");
6571 0 : CSLDestroy(papszTokens);
6572 0 : return OGRERR_FAILURE;
6573 : }
6574 :
6575 : /* -------------------------------------------------------------------- */
6576 : /* If we were not given a field name, drop all indexes. */
6577 : /* -------------------------------------------------------------------- */
6578 10 : if (CSLCount(papszTokens) == 4)
6579 : {
6580 0 : for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)
6581 : {
6582 : OGRAttrIndex *poAttrIndex;
6583 :
6584 0 : poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
6585 0 : if (poAttrIndex != nullptr)
6586 : {
6587 0 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6588 0 : if (eErr != OGRERR_NONE)
6589 : {
6590 0 : CSLDestroy(papszTokens);
6591 0 : return eErr;
6592 : }
6593 : }
6594 : }
6595 :
6596 0 : CSLDestroy(papszTokens);
6597 0 : return OGRERR_NONE;
6598 : }
6599 :
6600 : /* -------------------------------------------------------------------- */
6601 : /* Find the named field. */
6602 : /* -------------------------------------------------------------------- */
6603 10 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6604 10 : CSLDestroy(papszTokens);
6605 :
6606 10 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6607 : {
6608 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6609 : pszSQLCommand);
6610 0 : return OGRERR_FAILURE;
6611 : }
6612 :
6613 : /* -------------------------------------------------------------------- */
6614 : /* Attempt to drop the index. */
6615 : /* -------------------------------------------------------------------- */
6616 10 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6617 :
6618 10 : return eErr;
6619 : }
6620 :
6621 : /************************************************************************/
6622 : /* ProcessSQLDropTable() */
6623 : /* */
6624 : /* The correct syntax for dropping a table (layer) in the OGR SQL */
6625 : /* dialect is: */
6626 : /* */
6627 : /* DROP TABLE <layername> */
6628 : /************************************************************************/
6629 :
6630 500 : OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)
6631 :
6632 : {
6633 500 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6634 :
6635 : /* -------------------------------------------------------------------- */
6636 : /* Do some general syntax checking. */
6637 : /* -------------------------------------------------------------------- */
6638 1000 : if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||
6639 500 : !EQUAL(papszTokens[1], "TABLE"))
6640 : {
6641 0 : CSLDestroy(papszTokens);
6642 0 : CPLError(CE_Failure, CPLE_AppDefined,
6643 : "Syntax error in DROP TABLE command.\n"
6644 : "Was '%s'\n"
6645 : "Should be of form 'DROP TABLE <table>'",
6646 : pszSQLCommand);
6647 0 : return OGRERR_FAILURE;
6648 : }
6649 :
6650 : /* -------------------------------------------------------------------- */
6651 : /* Find the named layer. */
6652 : /* -------------------------------------------------------------------- */
6653 500 : OGRLayer *poLayer = nullptr;
6654 :
6655 500 : int i = 0; // Used after for.
6656 40199 : for (; i < GetLayerCount(); ++i)
6657 : {
6658 40199 : poLayer = GetLayer(i);
6659 :
6660 40199 : if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))
6661 500 : break;
6662 39699 : poLayer = nullptr;
6663 : }
6664 :
6665 500 : if (poLayer == nullptr)
6666 : {
6667 0 : CPLError(CE_Failure, CPLE_AppDefined,
6668 0 : "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
6669 0 : CSLDestroy(papszTokens);
6670 0 : return OGRERR_FAILURE;
6671 : }
6672 :
6673 500 : CSLDestroy(papszTokens);
6674 :
6675 : /* -------------------------------------------------------------------- */
6676 : /* Delete it. */
6677 : /* -------------------------------------------------------------------- */
6678 :
6679 500 : return DeleteLayer(i);
6680 : }
6681 :
6682 : //! @endcond
6683 :
6684 : /************************************************************************/
6685 : /* GDALDatasetParseSQLType() */
6686 : /************************************************************************/
6687 :
6688 : /* All arguments will be altered */
6689 6 : static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
6690 : int &nPrecision)
6691 : {
6692 6 : char *pszParenthesis = strchr(pszType, '(');
6693 6 : if (pszParenthesis)
6694 : {
6695 4 : nWidth = atoi(pszParenthesis + 1);
6696 4 : *pszParenthesis = '\0';
6697 4 : char *pszComma = strchr(pszParenthesis + 1, ',');
6698 4 : if (pszComma)
6699 2 : nPrecision = atoi(pszComma + 1);
6700 : }
6701 :
6702 6 : OGRFieldType eType = OFTString;
6703 6 : if (EQUAL(pszType, "INTEGER"))
6704 0 : eType = OFTInteger;
6705 6 : else if (EQUAL(pszType, "INTEGER[]"))
6706 0 : eType = OFTIntegerList;
6707 6 : else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||
6708 4 : EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
6709 4 : EQUAL(pszType, "REAL") /* unofficial alias */)
6710 2 : eType = OFTReal;
6711 4 : else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||
6712 4 : EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
6713 4 : EQUAL(pszType, "REAL[]") /* unofficial alias */)
6714 0 : eType = OFTRealList;
6715 4 : else if (EQUAL(pszType, "CHARACTER") ||
6716 0 : EQUAL(pszType, "TEXT") /* unofficial alias */ ||
6717 0 : EQUAL(pszType, "STRING") /* unofficial alias */ ||
6718 0 : EQUAL(pszType, "VARCHAR") /* unofficial alias */)
6719 4 : eType = OFTString;
6720 0 : else if (EQUAL(pszType, "TEXT[]") ||
6721 0 : EQUAL(pszType, "STRING[]") /* unofficial alias */ ||
6722 0 : EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
6723 0 : eType = OFTStringList;
6724 0 : else if (EQUAL(pszType, "DATE"))
6725 0 : eType = OFTDate;
6726 0 : else if (EQUAL(pszType, "TIME"))
6727 0 : eType = OFTTime;
6728 0 : else if (EQUAL(pszType, "TIMESTAMP") ||
6729 0 : EQUAL(pszType, "DATETIME") /* unofficial alias */)
6730 0 : eType = OFTDateTime;
6731 : else
6732 0 : CPLError(CE_Warning, CPLE_NotSupported,
6733 : "Unsupported column type '%s'. Defaulting to VARCHAR",
6734 : pszType);
6735 :
6736 6 : return eType;
6737 : }
6738 :
6739 : /************************************************************************/
6740 : /* ProcessSQLAlterTableAddColumn() */
6741 : /* */
6742 : /* The correct syntax for adding a column in the OGR SQL */
6743 : /* dialect is: */
6744 : /* */
6745 : /* ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
6746 : /************************************************************************/
6747 :
6748 : //! @cond Doxygen_Suppress
6749 2 : OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)
6750 :
6751 : {
6752 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6753 :
6754 : /* -------------------------------------------------------------------- */
6755 : /* Do some general syntax checking. */
6756 : /* -------------------------------------------------------------------- */
6757 2 : const char *pszLayerName = nullptr;
6758 2 : const char *pszColumnName = nullptr;
6759 2 : int iTypeIndex = 0;
6760 2 : const int nTokens = CSLCount(papszTokens);
6761 :
6762 2 : if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6763 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&
6764 2 : EQUAL(papszTokens[4], "COLUMN"))
6765 : {
6766 1 : pszLayerName = papszTokens[2];
6767 1 : pszColumnName = papszTokens[5];
6768 1 : iTypeIndex = 6;
6769 : }
6770 1 : else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&
6771 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))
6772 : {
6773 1 : pszLayerName = papszTokens[2];
6774 1 : pszColumnName = papszTokens[4];
6775 1 : iTypeIndex = 5;
6776 : }
6777 : else
6778 : {
6779 0 : CSLDestroy(papszTokens);
6780 0 : CPLError(CE_Failure, CPLE_AppDefined,
6781 : "Syntax error in ALTER TABLE ADD COLUMN command.\n"
6782 : "Was '%s'\n"
6783 : "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
6784 : "<columnname> <columntype>'",
6785 : pszSQLCommand);
6786 0 : return OGRERR_FAILURE;
6787 : }
6788 :
6789 : /* -------------------------------------------------------------------- */
6790 : /* Merge type components into a single string if there were split */
6791 : /* with spaces */
6792 : /* -------------------------------------------------------------------- */
6793 4 : CPLString osType;
6794 6 : for (int i = iTypeIndex; i < nTokens; ++i)
6795 : {
6796 4 : osType += papszTokens[i];
6797 4 : CPLFree(papszTokens[i]);
6798 : }
6799 2 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6800 2 : papszTokens[iTypeIndex + 1] = nullptr;
6801 :
6802 : /* -------------------------------------------------------------------- */
6803 : /* Find the named layer. */
6804 : /* -------------------------------------------------------------------- */
6805 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6806 2 : if (poLayer == nullptr)
6807 : {
6808 0 : CPLError(CE_Failure, CPLE_AppDefined,
6809 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6810 : pszLayerName);
6811 0 : CSLDestroy(papszTokens);
6812 0 : return OGRERR_FAILURE;
6813 : }
6814 :
6815 : /* -------------------------------------------------------------------- */
6816 : /* Add column. */
6817 : /* -------------------------------------------------------------------- */
6818 :
6819 2 : int nWidth = 0;
6820 2 : int nPrecision = 0;
6821 2 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6822 4 : OGRFieldDefn oFieldDefn(pszColumnName, eType);
6823 2 : oFieldDefn.SetWidth(nWidth);
6824 2 : oFieldDefn.SetPrecision(nPrecision);
6825 :
6826 2 : CSLDestroy(papszTokens);
6827 :
6828 2 : return poLayer->CreateField(&oFieldDefn);
6829 : }
6830 :
6831 : /************************************************************************/
6832 : /* ProcessSQLAlterTableDropColumn() */
6833 : /* */
6834 : /* The correct syntax for dropping a column in the OGR SQL */
6835 : /* dialect is: */
6836 : /* */
6837 : /* ALTER TABLE <layername> DROP [COLUMN] <columnname> */
6838 : /************************************************************************/
6839 :
6840 2 : OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)
6841 :
6842 : {
6843 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6844 :
6845 : /* -------------------------------------------------------------------- */
6846 : /* Do some general syntax checking. */
6847 : /* -------------------------------------------------------------------- */
6848 2 : const char *pszLayerName = nullptr;
6849 2 : const char *pszColumnName = nullptr;
6850 3 : if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&
6851 4 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&
6852 1 : EQUAL(papszTokens[4], "COLUMN"))
6853 : {
6854 1 : pszLayerName = papszTokens[2];
6855 1 : pszColumnName = papszTokens[5];
6856 : }
6857 2 : else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&
6858 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))
6859 : {
6860 1 : pszLayerName = papszTokens[2];
6861 1 : pszColumnName = papszTokens[4];
6862 : }
6863 : else
6864 : {
6865 0 : CSLDestroy(papszTokens);
6866 0 : CPLError(CE_Failure, CPLE_AppDefined,
6867 : "Syntax error in ALTER TABLE DROP COLUMN command.\n"
6868 : "Was '%s'\n"
6869 : "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
6870 : "<columnname>'",
6871 : pszSQLCommand);
6872 0 : return OGRERR_FAILURE;
6873 : }
6874 :
6875 : /* -------------------------------------------------------------------- */
6876 : /* Find the named layer. */
6877 : /* -------------------------------------------------------------------- */
6878 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6879 2 : if (poLayer == nullptr)
6880 : {
6881 0 : CPLError(CE_Failure, CPLE_AppDefined,
6882 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6883 : pszLayerName);
6884 0 : CSLDestroy(papszTokens);
6885 0 : return OGRERR_FAILURE;
6886 : }
6887 :
6888 : /* -------------------------------------------------------------------- */
6889 : /* Find the field. */
6890 : /* -------------------------------------------------------------------- */
6891 :
6892 2 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6893 2 : if (nFieldIndex < 0)
6894 : {
6895 0 : CPLError(CE_Failure, CPLE_AppDefined,
6896 : "%s failed, no such field as `%s'.", pszSQLCommand,
6897 : pszColumnName);
6898 0 : CSLDestroy(papszTokens);
6899 0 : return OGRERR_FAILURE;
6900 : }
6901 :
6902 : /* -------------------------------------------------------------------- */
6903 : /* Remove it. */
6904 : /* -------------------------------------------------------------------- */
6905 :
6906 2 : CSLDestroy(papszTokens);
6907 :
6908 2 : return poLayer->DeleteField(nFieldIndex);
6909 : }
6910 :
6911 : /************************************************************************/
6912 : /* ProcessSQLAlterTableRenameColumn() */
6913 : /* */
6914 : /* The correct syntax for renaming a column in the OGR SQL */
6915 : /* dialect is: */
6916 : /* */
6917 : /* ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
6918 : /************************************************************************/
6919 :
6920 2 : OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)
6921 :
6922 : {
6923 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6924 :
6925 : /* -------------------------------------------------------------------- */
6926 : /* Do some general syntax checking. */
6927 : /* -------------------------------------------------------------------- */
6928 2 : const char *pszLayerName = nullptr;
6929 2 : const char *pszOldColName = nullptr;
6930 2 : const char *pszNewColName = nullptr;
6931 3 : if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&
6932 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&
6933 3 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))
6934 : {
6935 1 : pszLayerName = papszTokens[2];
6936 1 : pszOldColName = papszTokens[5];
6937 1 : pszNewColName = papszTokens[7];
6938 : }
6939 2 : else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&
6940 1 : EQUAL(papszTokens[1], "TABLE") &&
6941 2 : EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))
6942 : {
6943 1 : pszLayerName = papszTokens[2];
6944 1 : pszOldColName = papszTokens[4];
6945 1 : pszNewColName = papszTokens[6];
6946 : }
6947 : else
6948 : {
6949 0 : CSLDestroy(papszTokens);
6950 0 : CPLError(CE_Failure, CPLE_AppDefined,
6951 : "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
6952 : "Was '%s'\n"
6953 : "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
6954 : "<columnname> TO <newname>'",
6955 : pszSQLCommand);
6956 0 : return OGRERR_FAILURE;
6957 : }
6958 :
6959 : /* -------------------------------------------------------------------- */
6960 : /* Find the named layer. */
6961 : /* -------------------------------------------------------------------- */
6962 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6963 2 : if (poLayer == nullptr)
6964 : {
6965 0 : CPLError(CE_Failure, CPLE_AppDefined,
6966 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6967 : pszLayerName);
6968 0 : CSLDestroy(papszTokens);
6969 0 : return OGRERR_FAILURE;
6970 : }
6971 :
6972 : /* -------------------------------------------------------------------- */
6973 : /* Find the field. */
6974 : /* -------------------------------------------------------------------- */
6975 :
6976 : const int nFieldIndex =
6977 2 : poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
6978 2 : if (nFieldIndex < 0)
6979 : {
6980 0 : CPLError(CE_Failure, CPLE_AppDefined,
6981 : "%s failed, no such field as `%s'.", pszSQLCommand,
6982 : pszOldColName);
6983 0 : CSLDestroy(papszTokens);
6984 0 : return OGRERR_FAILURE;
6985 : }
6986 :
6987 : /* -------------------------------------------------------------------- */
6988 : /* Rename column. */
6989 : /* -------------------------------------------------------------------- */
6990 : OGRFieldDefn *poOldFieldDefn =
6991 2 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6992 4 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6993 2 : oNewFieldDefn.SetName(pszNewColName);
6994 :
6995 2 : CSLDestroy(papszTokens);
6996 :
6997 2 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6998 2 : ALTER_NAME_FLAG);
6999 : }
7000 :
7001 : /************************************************************************/
7002 : /* ProcessSQLAlterTableAlterColumn() */
7003 : /* */
7004 : /* The correct syntax for altering the type of a column in the */
7005 : /* OGR SQL dialect is: */
7006 : /* */
7007 : /* ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
7008 : /************************************************************************/
7009 :
7010 4 : OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)
7011 :
7012 : {
7013 4 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
7014 :
7015 : /* -------------------------------------------------------------------- */
7016 : /* Do some general syntax checking. */
7017 : /* -------------------------------------------------------------------- */
7018 4 : const char *pszLayerName = nullptr;
7019 4 : const char *pszColumnName = nullptr;
7020 4 : int iTypeIndex = 0;
7021 4 : const int nTokens = CSLCount(papszTokens);
7022 :
7023 4 : if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&
7024 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
7025 2 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))
7026 : {
7027 2 : pszLayerName = papszTokens[2];
7028 2 : pszColumnName = papszTokens[5];
7029 2 : iTypeIndex = 7;
7030 : }
7031 2 : else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
7032 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
7033 2 : EQUAL(papszTokens[5], "TYPE"))
7034 : {
7035 2 : pszLayerName = papszTokens[2];
7036 2 : pszColumnName = papszTokens[4];
7037 2 : iTypeIndex = 6;
7038 : }
7039 : else
7040 : {
7041 0 : CSLDestroy(papszTokens);
7042 0 : CPLError(CE_Failure, CPLE_AppDefined,
7043 : "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
7044 : "Was '%s'\n"
7045 : "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
7046 : "<columnname> TYPE <columntype>'",
7047 : pszSQLCommand);
7048 0 : return OGRERR_FAILURE;
7049 : }
7050 :
7051 : /* -------------------------------------------------------------------- */
7052 : /* Merge type components into a single string if there were split */
7053 : /* with spaces */
7054 : /* -------------------------------------------------------------------- */
7055 8 : CPLString osType;
7056 8 : for (int i = iTypeIndex; i < nTokens; ++i)
7057 : {
7058 4 : osType += papszTokens[i];
7059 4 : CPLFree(papszTokens[i]);
7060 : }
7061 4 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
7062 4 : papszTokens[iTypeIndex + 1] = nullptr;
7063 :
7064 : /* -------------------------------------------------------------------- */
7065 : /* Find the named layer. */
7066 : /* -------------------------------------------------------------------- */
7067 4 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
7068 4 : if (poLayer == nullptr)
7069 : {
7070 0 : CPLError(CE_Failure, CPLE_AppDefined,
7071 : "%s failed, no such layer as `%s'.", pszSQLCommand,
7072 : pszLayerName);
7073 0 : CSLDestroy(papszTokens);
7074 0 : return OGRERR_FAILURE;
7075 : }
7076 :
7077 : /* -------------------------------------------------------------------- */
7078 : /* Find the field. */
7079 : /* -------------------------------------------------------------------- */
7080 :
7081 : const int nFieldIndex =
7082 4 : poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
7083 4 : if (nFieldIndex < 0)
7084 : {
7085 0 : CPLError(CE_Failure, CPLE_AppDefined,
7086 : "%s failed, no such field as `%s'.", pszSQLCommand,
7087 : pszColumnName);
7088 0 : CSLDestroy(papszTokens);
7089 0 : return OGRERR_FAILURE;
7090 : }
7091 :
7092 : /* -------------------------------------------------------------------- */
7093 : /* Alter column. */
7094 : /* -------------------------------------------------------------------- */
7095 :
7096 : OGRFieldDefn *poOldFieldDefn =
7097 4 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
7098 8 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
7099 :
7100 4 : int nWidth = 0;
7101 4 : int nPrecision = 0;
7102 4 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
7103 4 : oNewFieldDefn.SetType(eType);
7104 4 : oNewFieldDefn.SetWidth(nWidth);
7105 4 : oNewFieldDefn.SetPrecision(nPrecision);
7106 :
7107 4 : int l_nFlags = 0;
7108 4 : if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
7109 2 : l_nFlags |= ALTER_TYPE_FLAG;
7110 4 : if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
7111 0 : poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
7112 4 : l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
7113 :
7114 4 : CSLDestroy(papszTokens);
7115 :
7116 4 : if (l_nFlags == 0)
7117 0 : return OGRERR_NONE;
7118 :
7119 4 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
7120 : }
7121 :
7122 : //! @endcond
7123 :
7124 : /************************************************************************/
7125 : /* ExecuteSQL() */
7126 : /************************************************************************/
7127 :
7128 : /**
7129 : \brief Execute an SQL statement against the data store.
7130 :
7131 : The result of an SQL query is either NULL for statements that are in error,
7132 : or that have no results set, or an OGRLayer pointer representing a results
7133 : set from the query. Note that this OGRLayer is in addition to the layers
7134 : in the data store and must be destroyed with
7135 : ReleaseResultSet() before the dataset is closed
7136 : (destroyed).
7137 :
7138 : This method is the same as the C function GDALDatasetExecuteSQL() and the
7139 : deprecated OGR_DS_ExecuteSQL().
7140 :
7141 : For more information on the SQL dialect supported internally by OGR
7142 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
7143 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
7144 : to the underlying RDBMS.
7145 :
7146 : Starting with OGR 1.10, the <a
7147 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
7148 : also be used.
7149 :
7150 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7151 :
7152 : @param pszStatement the SQL statement to execute.
7153 : @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
7154 : @param pszDialect allows control of the statement dialect. If set to NULL, the
7155 : OGR SQL engine will be used, except for RDBMS drivers that will use their
7156 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
7157 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
7158 :
7159 : @return an OGRLayer containing the results of the query. Deallocate with
7160 : ReleaseResultSet().
7161 :
7162 : */
7163 :
7164 3569 : OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,
7165 : OGRGeometry *poSpatialFilter,
7166 : const char *pszDialect)
7167 :
7168 : {
7169 3569 : return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
7170 : }
7171 :
7172 : //! @cond Doxygen_Suppress
7173 : OGRLayer *
7174 3577 : GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
7175 : const char *pszDialect,
7176 : swq_select_parse_options *poSelectParseOptions)
7177 :
7178 : {
7179 3577 : if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))
7180 : {
7181 : #ifdef SQLITE_ENABLED
7182 650 : return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
7183 650 : pszDialect);
7184 : #else
7185 : CPLError(CE_Failure, CPLE_NotSupported,
7186 : "The SQLite driver needs to be compiled to support the "
7187 : "SQLite SQL dialect");
7188 : return nullptr;
7189 : #endif
7190 : }
7191 :
7192 2927 : if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
7193 14 : !EQUAL(pszDialect, "OGRSQL"))
7194 : {
7195 6 : std::string osDialectList = "'OGRSQL'";
7196 : #ifdef SQLITE_ENABLED
7197 3 : osDialectList += ", 'SQLITE'";
7198 : #endif
7199 : const char *pszDialects =
7200 3 : GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);
7201 3 : if (pszDialects)
7202 : {
7203 : const CPLStringList aosTokens(
7204 0 : CSLTokenizeString2(pszDialects, " ", 0));
7205 0 : for (int i = 0; i < aosTokens.size(); ++i)
7206 : {
7207 0 : if (!EQUAL(aosTokens[i], "OGRSQL") &&
7208 0 : !EQUAL(aosTokens[i], "SQLITE"))
7209 : {
7210 0 : osDialectList += ", '";
7211 0 : osDialectList += aosTokens[i];
7212 0 : osDialectList += "'";
7213 : }
7214 : }
7215 : }
7216 3 : CPLError(CE_Warning, CPLE_NotSupported,
7217 : "Dialect '%s' is unsupported. Only supported dialects are %s. "
7218 : "Defaulting to OGRSQL",
7219 : pszDialect, osDialectList.c_str());
7220 : }
7221 :
7222 : /* -------------------------------------------------------------------- */
7223 : /* Handle CREATE INDEX statements specially. */
7224 : /* -------------------------------------------------------------------- */
7225 2927 : if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))
7226 : {
7227 28 : ProcessSQLCreateIndex(pszStatement);
7228 28 : return nullptr;
7229 : }
7230 :
7231 : /* -------------------------------------------------------------------- */
7232 : /* Handle DROP INDEX statements specially. */
7233 : /* -------------------------------------------------------------------- */
7234 2899 : if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))
7235 : {
7236 10 : ProcessSQLDropIndex(pszStatement);
7237 10 : return nullptr;
7238 : }
7239 :
7240 : /* -------------------------------------------------------------------- */
7241 : /* Handle DROP TABLE statements specially. */
7242 : /* -------------------------------------------------------------------- */
7243 2889 : if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))
7244 : {
7245 500 : ProcessSQLDropTable(pszStatement);
7246 500 : return nullptr;
7247 : }
7248 :
7249 : /* -------------------------------------------------------------------- */
7250 : /* Handle ALTER TABLE statements specially. */
7251 : /* -------------------------------------------------------------------- */
7252 2389 : if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))
7253 : {
7254 11 : char **papszTokens = CSLTokenizeString(pszStatement);
7255 11 : const int nTokens = CSLCount(papszTokens);
7256 11 : if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))
7257 : {
7258 2 : ProcessSQLAlterTableAddColumn(pszStatement);
7259 2 : CSLDestroy(papszTokens);
7260 2 : return nullptr;
7261 : }
7262 9 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))
7263 : {
7264 2 : ProcessSQLAlterTableDropColumn(pszStatement);
7265 2 : CSLDestroy(papszTokens);
7266 2 : return nullptr;
7267 : }
7268 7 : else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&
7269 1 : EQUAL(papszTokens[4], "TO"))
7270 : {
7271 1 : const char *pszSrcTableName = papszTokens[2];
7272 1 : const char *pszDstTableName = papszTokens[5];
7273 1 : auto poSrcLayer = GetLayerByName(pszSrcTableName);
7274 1 : if (poSrcLayer)
7275 : {
7276 1 : CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));
7277 : }
7278 : else
7279 : {
7280 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");
7281 : }
7282 1 : CSLDestroy(papszTokens);
7283 1 : return nullptr;
7284 : }
7285 6 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))
7286 : {
7287 2 : ProcessSQLAlterTableRenameColumn(pszStatement);
7288 2 : CSLDestroy(papszTokens);
7289 2 : return nullptr;
7290 : }
7291 4 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))
7292 : {
7293 4 : ProcessSQLAlterTableAlterColumn(pszStatement);
7294 4 : CSLDestroy(papszTokens);
7295 4 : return nullptr;
7296 : }
7297 : else
7298 : {
7299 0 : CPLError(CE_Failure, CPLE_AppDefined,
7300 : "Unsupported ALTER TABLE command : %s", pszStatement);
7301 0 : CSLDestroy(papszTokens);
7302 0 : return nullptr;
7303 : }
7304 : }
7305 :
7306 : /* -------------------------------------------------------------------- */
7307 : /* Preparse the SQL statement. */
7308 : /* -------------------------------------------------------------------- */
7309 2378 : swq_select *psSelectInfo = new swq_select();
7310 2378 : swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
7311 2378 : if (poSelectParseOptions != nullptr)
7312 8 : poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
7313 2378 : if (psSelectInfo->preparse(pszStatement,
7314 2378 : poCustomFuncRegistrar != nullptr) != CE_None)
7315 : {
7316 142 : delete psSelectInfo;
7317 142 : return nullptr;
7318 : }
7319 :
7320 : /* -------------------------------------------------------------------- */
7321 : /* If there is no UNION ALL, build result layer. */
7322 : /* -------------------------------------------------------------------- */
7323 2236 : if (psSelectInfo->poOtherSelect == nullptr)
7324 : {
7325 2230 : return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
7326 2230 : pszDialect, poSelectParseOptions);
7327 : }
7328 :
7329 : /* -------------------------------------------------------------------- */
7330 : /* Build result union layer. */
7331 : /* -------------------------------------------------------------------- */
7332 6 : int nSrcLayers = 0;
7333 6 : OGRLayer **papoSrcLayers = nullptr;
7334 :
7335 6 : do
7336 : {
7337 12 : swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
7338 12 : psSelectInfo->poOtherSelect = nullptr;
7339 :
7340 12 : OGRLayer *poLayer = BuildLayerFromSelectInfo(
7341 : psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
7342 12 : if (poLayer == nullptr)
7343 : {
7344 : // Each source layer owns an independent select info.
7345 0 : for (int i = 0; i < nSrcLayers; ++i)
7346 0 : delete papoSrcLayers[i];
7347 0 : CPLFree(papoSrcLayers);
7348 :
7349 : // So we just have to destroy the remaining select info.
7350 0 : delete psNextSelectInfo;
7351 :
7352 0 : return nullptr;
7353 : }
7354 : else
7355 : {
7356 24 : papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
7357 12 : papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
7358 12 : papoSrcLayers[nSrcLayers] = poLayer;
7359 12 : ++nSrcLayers;
7360 :
7361 12 : psSelectInfo = psNextSelectInfo;
7362 : }
7363 12 : } while (psSelectInfo != nullptr);
7364 :
7365 6 : return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
7366 : }
7367 :
7368 : //! @endcond
7369 :
7370 : /************************************************************************/
7371 : /* AbortSQL() */
7372 : /************************************************************************/
7373 :
7374 : /**
7375 : \brief Abort any SQL statement running in the data store.
7376 :
7377 : This function can be safely called from any thread (pending that the dataset
7378 : object is still alive). Driver implementations will make sure that it can be
7379 : called in a thread-safe way.
7380 :
7381 : This might not be implemented by all drivers. At time of writing, only SQLite,
7382 : GPKG and PG drivers implement it
7383 :
7384 : This method is the same as the C method GDALDatasetAbortSQL()
7385 :
7386 : @since GDAL 3.2.0
7387 :
7388 :
7389 : */
7390 :
7391 0 : OGRErr GDALDataset::AbortSQL()
7392 : {
7393 0 : CPLError(CE_Failure, CPLE_NotSupported,
7394 : "AbortSQL is not supported for this driver.");
7395 0 : return OGRERR_UNSUPPORTED_OPERATION;
7396 : }
7397 :
7398 : /************************************************************************/
7399 : /* BuildLayerFromSelectInfo() */
7400 : /************************************************************************/
7401 :
7402 : struct GDALSQLParseInfo
7403 : {
7404 : swq_field_list sFieldList;
7405 : int nExtraDSCount;
7406 : GDALDataset **papoExtraDS;
7407 : char *pszWHERE;
7408 : };
7409 :
7410 2242 : OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
7411 : swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
7412 : const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
7413 : {
7414 4484 : std::unique_ptr<swq_select> psSelectInfoUnique(psSelectInfo);
7415 :
7416 2242 : std::unique_ptr<OGRGenSQLResultsLayer> poResults;
7417 : GDALSQLParseInfo *psParseInfo =
7418 2242 : BuildParseInfo(psSelectInfoUnique.get(), poSelectParseOptions);
7419 :
7420 2242 : if (psParseInfo)
7421 : {
7422 2207 : const auto nErrorCounter = CPLGetErrorCounter();
7423 4414 : poResults = std::make_unique<OGRGenSQLResultsLayer>(
7424 2207 : this, std::move(psSelectInfoUnique), poSpatialFilter,
7425 4414 : psParseInfo->pszWHERE, pszDialect);
7426 2284 : if (CPLGetErrorCounter() > nErrorCounter &&
7427 77 : CPLGetLastErrorType() != CE_None)
7428 77 : poResults.reset();
7429 : }
7430 :
7431 2242 : DestroyParseInfo(psParseInfo);
7432 :
7433 4484 : return poResults.release();
7434 : }
7435 :
7436 : /************************************************************************/
7437 : /* DestroyParseInfo() */
7438 : /************************************************************************/
7439 :
7440 : //! @cond Doxygen_Suppress
7441 2311 : void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
7442 : {
7443 2311 : if (psParseInfo == nullptr)
7444 35 : return;
7445 :
7446 2276 : CPLFree(psParseInfo->sFieldList.names);
7447 2276 : CPLFree(psParseInfo->sFieldList.types);
7448 2276 : CPLFree(psParseInfo->sFieldList.table_ids);
7449 2276 : CPLFree(psParseInfo->sFieldList.ids);
7450 :
7451 : // Release the datasets we have opened with OGROpenShared()
7452 : // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
7453 : // has taken a reference on them, which it will release in its
7454 : // destructor.
7455 2283 : for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)
7456 7 : GDALClose(psParseInfo->papoExtraDS[iEDS]);
7457 :
7458 2276 : CPLFree(psParseInfo->papoExtraDS);
7459 2276 : CPLFree(psParseInfo->pszWHERE);
7460 2276 : CPLFree(psParseInfo);
7461 : }
7462 :
7463 : /************************************************************************/
7464 : /* BuildParseInfo() */
7465 : /************************************************************************/
7466 :
7467 : GDALSQLParseInfo *
7468 2276 : GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
7469 : swq_select_parse_options *poSelectParseOptions)
7470 : {
7471 2276 : int nFirstLayerFirstSpecialFieldIndex = 0;
7472 :
7473 : GDALSQLParseInfo *psParseInfo =
7474 2276 : static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
7475 :
7476 : /* -------------------------------------------------------------------- */
7477 : /* Validate that all the source tables are recognized, count */
7478 : /* fields. */
7479 : /* -------------------------------------------------------------------- */
7480 2276 : int nFieldCount = 0;
7481 :
7482 4620 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7483 : {
7484 2347 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7485 2347 : GDALDataset *poTableDS = this;
7486 :
7487 2347 : if (psTableDef->data_source != nullptr)
7488 : {
7489 7 : poTableDS = GDALDataset::FromHandle(
7490 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7491 7 : if (poTableDS == nullptr)
7492 : {
7493 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
7494 0 : CPLError(CE_Failure, CPLE_AppDefined,
7495 : "Unable to open secondary datasource "
7496 : "`%s' required by JOIN.",
7497 : psTableDef->data_source);
7498 :
7499 0 : DestroyParseInfo(psParseInfo);
7500 0 : return nullptr;
7501 : }
7502 :
7503 : // Keep in an array to release at the end of this function.
7504 14 : psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
7505 7 : psParseInfo->papoExtraDS,
7506 7 : sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
7507 7 : psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
7508 : }
7509 :
7510 : OGRLayer *poSrcLayer =
7511 2347 : poTableDS->GetLayerByName(psTableDef->table_name);
7512 :
7513 2347 : if (poSrcLayer == nullptr)
7514 : {
7515 3 : CPLError(CE_Failure, CPLE_AppDefined,
7516 : "SELECT from table %s failed, no such table/featureclass.",
7517 : psTableDef->table_name);
7518 :
7519 3 : DestroyParseInfo(psParseInfo);
7520 3 : return nullptr;
7521 : }
7522 :
7523 2344 : nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
7524 2344 : if (iTable == 0 ||
7525 34 : (poSelectParseOptions &&
7526 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7527 2307 : nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7528 :
7529 2344 : const char *pszFID = poSrcLayer->GetFIDColumn();
7530 2957 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7531 613 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7532 563 : nFieldCount++;
7533 : }
7534 :
7535 : /* -------------------------------------------------------------------- */
7536 : /* Build the field list for all indicated tables. */
7537 : /* -------------------------------------------------------------------- */
7538 :
7539 2273 : psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
7540 2273 : psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
7541 :
7542 2273 : psParseInfo->sFieldList.count = 0;
7543 2273 : psParseInfo->sFieldList.names = static_cast<char **>(
7544 2273 : CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7545 4546 : psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
7546 2273 : sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7547 2273 : psParseInfo->sFieldList.table_ids = static_cast<int *>(
7548 2273 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7549 2273 : psParseInfo->sFieldList.ids = static_cast<int *>(
7550 2273 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7551 :
7552 2273 : bool bIsFID64 = false;
7553 4617 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7554 : {
7555 2344 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7556 2344 : GDALDataset *poTableDS = this;
7557 :
7558 2344 : if (psTableDef->data_source != nullptr)
7559 : {
7560 7 : poTableDS = GDALDataset::FromHandle(
7561 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7562 7 : CPLAssert(poTableDS != nullptr);
7563 7 : poTableDS->Dereference();
7564 : }
7565 :
7566 : OGRLayer *poSrcLayer =
7567 2344 : poTableDS->GetLayerByName(psTableDef->table_name);
7568 :
7569 2344 : for (int iField = 0;
7570 18551 : iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)
7571 : {
7572 : OGRFieldDefn *poFDefn =
7573 16207 : poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
7574 16207 : const int iOutField = psParseInfo->sFieldList.count++;
7575 32414 : psParseInfo->sFieldList.names[iOutField] =
7576 16207 : const_cast<char *>(poFDefn->GetNameRef());
7577 16207 : if (poFDefn->GetType() == OFTInteger)
7578 : {
7579 4088 : if (poFDefn->GetSubType() == OFSTBoolean)
7580 160 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7581 : else
7582 3928 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7583 : }
7584 12119 : else if (poFDefn->GetType() == OFTInteger64)
7585 : {
7586 762 : if (poFDefn->GetSubType() == OFSTBoolean)
7587 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7588 : else
7589 762 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7590 : }
7591 11357 : else if (poFDefn->GetType() == OFTReal)
7592 2719 : psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
7593 8638 : else if (poFDefn->GetType() == OFTString)
7594 5584 : psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
7595 3054 : else if (poFDefn->GetType() == OFTTime)
7596 83 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
7597 2971 : else if (poFDefn->GetType() == OFTDate)
7598 143 : psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
7599 2828 : else if (poFDefn->GetType() == OFTDateTime)
7600 939 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
7601 : else
7602 1889 : psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
7603 :
7604 16207 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7605 16207 : psParseInfo->sFieldList.ids[iOutField] = iField;
7606 : }
7607 :
7608 2344 : if (iTable == 0)
7609 : {
7610 2273 : nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
7611 : }
7612 :
7613 2344 : if (iTable == 0 ||
7614 34 : (poSelectParseOptions &&
7615 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7616 : {
7617 :
7618 2307 : for (int iField = 0;
7619 4261 : iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7620 : iField++)
7621 : {
7622 : OGRGeomFieldDefn *poFDefn =
7623 1954 : poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
7624 1954 : const int iOutField = psParseInfo->sFieldList.count++;
7625 3908 : psParseInfo->sFieldList.names[iOutField] =
7626 1954 : const_cast<char *>(poFDefn->GetNameRef());
7627 1954 : if (*psParseInfo->sFieldList.names[iOutField] == '\0')
7628 1139 : psParseInfo->sFieldList.names[iOutField] =
7629 : const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
7630 1954 : psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
7631 :
7632 1954 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7633 1954 : psParseInfo->sFieldList.ids[iOutField] =
7634 1954 : GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
7635 : poSrcLayer->GetLayerDefn(), iField);
7636 : }
7637 : }
7638 :
7639 2345 : if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7640 1 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7641 : {
7642 1 : bIsFID64 = true;
7643 : }
7644 : }
7645 :
7646 : /* -------------------------------------------------------------------- */
7647 : /* Expand '*' in 'SELECT *' now before we add the pseudo fields */
7648 : /* -------------------------------------------------------------------- */
7649 2273 : const bool bAlwaysPrefixWithTableName =
7650 2315 : poSelectParseOptions &&
7651 42 : poSelectParseOptions->bAlwaysPrefixWithTableName;
7652 2273 : if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
7653 2273 : bAlwaysPrefixWithTableName) != CE_None)
7654 : {
7655 2 : DestroyParseInfo(psParseInfo);
7656 2 : return nullptr;
7657 : }
7658 :
7659 13626 : for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
7660 : {
7661 11355 : psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
7662 11355 : const_cast<char *>(SpecialFieldNames[iField]);
7663 11355 : psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
7664 11355 : (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
7665 : : SpecialFieldTypes[iField];
7666 11355 : psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
7667 11355 : psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
7668 11355 : nFirstLayerFirstSpecialFieldIndex + iField;
7669 11355 : psParseInfo->sFieldList.count++;
7670 : }
7671 :
7672 : /* In the case a layer has an explicit FID column name, then add it */
7673 : /* so it can be selected */
7674 4613 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7675 : {
7676 2342 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7677 2342 : GDALDataset *poTableDS = this;
7678 :
7679 2342 : if (psTableDef->data_source != nullptr)
7680 : {
7681 7 : poTableDS = GDALDataset::FromHandle(
7682 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7683 7 : CPLAssert(poTableDS != nullptr);
7684 7 : poTableDS->Dereference();
7685 : }
7686 :
7687 : OGRLayer *poSrcLayer =
7688 2342 : poTableDS->GetLayerByName(psTableDef->table_name);
7689 :
7690 2342 : const char *pszFID = poSrcLayer->GetFIDColumn();
7691 2955 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7692 613 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7693 : {
7694 563 : const int iOutField = psParseInfo->sFieldList.count++;
7695 563 : psParseInfo->sFieldList.names[iOutField] =
7696 : const_cast<char *>(pszFID);
7697 563 : if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7698 0 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7699 : {
7700 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7701 : }
7702 : else
7703 : {
7704 563 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7705 : }
7706 563 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7707 1126 : psParseInfo->sFieldList.ids[iOutField] =
7708 563 : poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
7709 : }
7710 : }
7711 :
7712 : /* -------------------------------------------------------------------- */
7713 : /* Finish the parse operation. */
7714 : /* -------------------------------------------------------------------- */
7715 2271 : if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
7716 : CE_None)
7717 : {
7718 30 : DestroyParseInfo(psParseInfo);
7719 30 : return nullptr;
7720 : }
7721 :
7722 : /* -------------------------------------------------------------------- */
7723 : /* Extract the WHERE expression to use separately. */
7724 : /* -------------------------------------------------------------------- */
7725 2241 : if (psSelectInfo->where_expr != nullptr)
7726 : {
7727 960 : psParseInfo->pszWHERE =
7728 960 : psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
7729 : // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
7730 : }
7731 :
7732 2241 : return psParseInfo;
7733 : }
7734 :
7735 : //! @endcond
7736 :
7737 : /************************************************************************/
7738 : /* ReleaseResultSet() */
7739 : /************************************************************************/
7740 :
7741 : /**
7742 : \brief Release results of ExecuteSQL().
7743 :
7744 : This method should only be used to deallocate OGRLayers resulting from
7745 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
7746 : results set before destroying the GDALDataset may cause errors.
7747 :
7748 : This method is the same as the C function GDALDatasetReleaseResultSet() and the
7749 : deprecated OGR_DS_ReleaseResultSet().
7750 :
7751 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7752 :
7753 : @param poResultsSet the result of a previous ExecuteSQL() call.
7754 : */
7755 :
7756 2160 : void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)
7757 :
7758 : {
7759 2160 : delete poResultsSet;
7760 2160 : }
7761 :
7762 : /************************************************************************/
7763 : /* GetStyleTable() */
7764 : /************************************************************************/
7765 :
7766 : /**
7767 : \brief Returns dataset style table.
7768 :
7769 : This method is the same as the C function GDALDatasetGetStyleTable() and the
7770 : deprecated OGR_DS_GetStyleTable().
7771 :
7772 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7773 :
7774 : @return pointer to a style table which should not be modified or freed by the
7775 : caller.
7776 : */
7777 :
7778 853 : OGRStyleTable *GDALDataset::GetStyleTable()
7779 : {
7780 853 : return m_poStyleTable;
7781 : }
7782 :
7783 : /************************************************************************/
7784 : /* SetStyleTableDirectly() */
7785 : /************************************************************************/
7786 :
7787 : /**
7788 : \brief Set dataset style table.
7789 :
7790 : This method operate exactly as SetStyleTable() except that it
7791 : assumes ownership of the passed table.
7792 :
7793 : This method is the same as the C function GDALDatasetSetStyleTableDirectly()
7794 : and the deprecated OGR_DS_SetStyleTableDirectly().
7795 :
7796 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7797 :
7798 : @param poStyleTable pointer to style table to set
7799 :
7800 : */
7801 0 : void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
7802 : {
7803 0 : if (m_poStyleTable)
7804 0 : delete m_poStyleTable;
7805 0 : m_poStyleTable = poStyleTable;
7806 0 : }
7807 :
7808 : /************************************************************************/
7809 : /* SetStyleTable() */
7810 : /************************************************************************/
7811 :
7812 : /**
7813 : \brief Set dataset style table.
7814 :
7815 : This method operate exactly as SetStyleTableDirectly() except
7816 : that it does not assume ownership of the passed table.
7817 :
7818 : This method is the same as the C function GDALDatasetSetStyleTable() and the
7819 : deprecated OGR_DS_SetStyleTable().
7820 :
7821 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7822 :
7823 : @param poStyleTable pointer to style table to set
7824 :
7825 : */
7826 :
7827 849 : void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
7828 : {
7829 849 : if (m_poStyleTable)
7830 0 : delete m_poStyleTable;
7831 849 : if (poStyleTable)
7832 1 : m_poStyleTable = poStyleTable->Clone();
7833 849 : }
7834 :
7835 : /************************************************************************/
7836 : /* IsGenericSQLDialect() */
7837 : /************************************************************************/
7838 :
7839 : //! @cond Doxygen_Suppress
7840 1748 : int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
7841 : {
7842 3188 : return pszDialect != nullptr &&
7843 3188 : (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
7844 : }
7845 :
7846 : //! @endcond
7847 :
7848 : /************************************************************************/
7849 : /* GetLayerCount() */
7850 : /************************************************************************/
7851 :
7852 : /**
7853 : \brief Get the number of layers in this dataset.
7854 :
7855 : This method is the same as the C function GDALDatasetGetLayerCount(),
7856 : and the deprecated OGR_DS_GetLayerCount().
7857 :
7858 : Note that even if this method is const, there is no guarantee it can be
7859 : safely called by concurrent threads on the same GDALDataset object.
7860 :
7861 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7862 :
7863 : @return layer count.
7864 : */
7865 :
7866 114749 : int GDALDataset::GetLayerCount() const
7867 : {
7868 114749 : return 0;
7869 : }
7870 :
7871 : /************************************************************************/
7872 : /* GetLayer() */
7873 : /************************************************************************/
7874 :
7875 : /**
7876 : \fn const GDALDataset::GetLayer(int) const
7877 : \brief Fetch a layer by index.
7878 :
7879 : The returned layer remains owned by the
7880 : GDALDataset and should not be deleted by the application.
7881 :
7882 : Note that even if this method is const, there is no guarantee it can be
7883 : safely called by concurrent threads on the same GDALDataset object.
7884 :
7885 : See GetLayers() for a C++ iterator version of this method.
7886 :
7887 : This method is the same as the C function GDALDatasetGetLayer() and the
7888 : deprecated OGR_DS_GetLayer().
7889 :
7890 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7891 :
7892 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7893 :
7894 : @return the layer, or NULL if iLayer is out of range or an error occurs.
7895 :
7896 : @see GetLayers()
7897 :
7898 : @since GDAL 3.12
7899 : */
7900 :
7901 0 : const OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer) const
7902 : {
7903 0 : return nullptr;
7904 : }
7905 :
7906 : /**
7907 : \fn GDALDataset::GetLayer(int)
7908 : \brief Fetch a layer by index.
7909 :
7910 : The returned layer remains owned by the
7911 : GDALDataset and should not be deleted by the application.
7912 :
7913 : See GetLayers() for a C++ iterator version of this method.
7914 :
7915 : This method is the same as the C function GDALDatasetGetLayer() and the
7916 : deprecated OGR_DS_GetLayer().
7917 :
7918 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7919 :
7920 : @return the layer, or NULL if iLayer is out of range or an error occurs.
7921 :
7922 : @see GetLayers()
7923 : */
7924 :
7925 : /************************************************************************/
7926 : /* IsLayerPrivate() */
7927 : /************************************************************************/
7928 :
7929 : /**
7930 : \fn GDALDataset::IsLayerPrivate(int)
7931 : \brief Returns true if the layer at the specified index is deemed a private or
7932 : system table, or an internal detail only.
7933 :
7934 : This method is the same as the C function GDALDatasetIsLayerPrivate().
7935 :
7936 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7937 :
7938 : @return true if the layer is a private or system table.
7939 :
7940 : @since GDAL 3.4
7941 : */
7942 :
7943 868 : bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const
7944 : {
7945 868 : return false;
7946 : }
7947 :
7948 : /************************************************************************/
7949 : /* ResetReading() */
7950 : /************************************************************************/
7951 :
7952 : /**
7953 : \brief Reset feature reading to start on the first feature.
7954 :
7955 : This affects GetNextFeature().
7956 :
7957 : Depending on drivers, this may also have the side effect of calling
7958 : OGRLayer::ResetReading() on the layers of this dataset.
7959 :
7960 : This method is the same as the C function GDALDatasetResetReading().
7961 :
7962 : @since GDAL 2.2
7963 : */
7964 7 : void GDALDataset::ResetReading()
7965 : {
7966 7 : if (!m_poPrivate)
7967 0 : return;
7968 7 : m_poPrivate->nCurrentLayerIdx = 0;
7969 7 : m_poPrivate->nLayerCount = -1;
7970 7 : m_poPrivate->poCurrentLayer = nullptr;
7971 7 : m_poPrivate->nFeatureReadInLayer = 0;
7972 7 : m_poPrivate->nFeatureReadInDataset = 0;
7973 7 : m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
7974 7 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
7975 : }
7976 :
7977 : /************************************************************************/
7978 : /* GDALDatasetResetReading() */
7979 : /************************************************************************/
7980 :
7981 : /**
7982 : \brief Reset feature reading to start on the first feature.
7983 :
7984 : This affects GDALDatasetGetNextFeature().
7985 :
7986 : Depending on drivers, this may also have the side effect of calling
7987 : OGR_L_ResetReading() on the layers of this dataset.
7988 :
7989 : This method is the same as the C++ method GDALDataset::ResetReading()
7990 :
7991 : @param hDS dataset handle
7992 : @since GDAL 2.2
7993 : */
7994 14 : void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)
7995 : {
7996 14 : VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
7997 :
7998 14 : return GDALDataset::FromHandle(hDS)->ResetReading();
7999 : }
8000 :
8001 : /************************************************************************/
8002 : /* GetNextFeature() */
8003 : /************************************************************************/
8004 :
8005 : /**
8006 : \brief Fetch the next available feature from this dataset.
8007 :
8008 : This method is intended for the few drivers where OGRLayer::GetNextFeature()
8009 : is not efficient, but in general OGRLayer::GetNextFeature() is a more
8010 : natural API.
8011 :
8012 : See GetFeatures() for a C++ iterator version of this method.
8013 :
8014 : The returned feature becomes the responsibility of the caller to
8015 : delete with OGRFeature::DestroyFeature().
8016 :
8017 : Depending on the driver, this method may return features from layers in a
8018 : non sequential way. This is what may happen when the
8019 : ODsCRandomLayerRead capability is declared (for example for the
8020 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
8021 : advised to use GDALDataset::GetNextFeature() instead of
8022 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
8023 : implementation.
8024 :
8025 : The default implementation, used by most drivers, will
8026 : however iterate over each layer, and then over each feature within this
8027 : layer.
8028 :
8029 : This method takes into account spatial and attribute filters set on layers that
8030 : will be iterated upon.
8031 :
8032 : The ResetReading() method can be used to start at the beginning again.
8033 :
8034 : Depending on drivers, this may also have the side effect of calling
8035 : OGRLayer::GetNextFeature() on the layers of this dataset.
8036 :
8037 : This method is the same as the C function GDALDatasetGetNextFeature().
8038 :
8039 : @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
8040 : layer to which the object belongs to, or NULL.
8041 : It is possible that the output of *ppoBelongingLayer
8042 : to be NULL despite the feature not being NULL.
8043 : @param pdfProgressPct a pointer to a double variable to receive the
8044 : percentage progress (in [0,1] range), or NULL.
8045 : On return, the pointed value might be negative if
8046 : determining the progress is not possible.
8047 : @param pfnProgress a progress callback to report progress (for
8048 : GetNextFeature() calls that might have a long
8049 : duration) and offer cancellation possibility, or NULL.
8050 : @param pProgressData user data provided to pfnProgress, or NULL
8051 : @return a feature, or NULL if no more features are available.
8052 : @since GDAL 2.2
8053 : @see GetFeatures()
8054 : */
8055 :
8056 60 : OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,
8057 : double *pdfProgressPct,
8058 : GDALProgressFunc pfnProgress,
8059 : void *pProgressData)
8060 : {
8061 60 : if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)
8062 : {
8063 2 : if (ppoBelongingLayer != nullptr)
8064 2 : *ppoBelongingLayer = nullptr;
8065 2 : if (pdfProgressPct != nullptr)
8066 1 : *pdfProgressPct = 1.0;
8067 2 : if (pfnProgress != nullptr)
8068 0 : pfnProgress(1.0, "", pProgressData);
8069 2 : return nullptr;
8070 : }
8071 :
8072 58 : if (m_poPrivate->poCurrentLayer == nullptr &&
8073 8 : (pdfProgressPct != nullptr || pfnProgress != nullptr))
8074 : {
8075 1 : if (m_poPrivate->nLayerCount < 0)
8076 : {
8077 1 : m_poPrivate->nLayerCount = GetLayerCount();
8078 : }
8079 :
8080 1 : if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)
8081 : {
8082 1 : m_poPrivate->nTotalFeatures = 0;
8083 5 : for (int i = 0; i < m_poPrivate->nLayerCount; i++)
8084 : {
8085 4 : OGRLayer *poLayer = GetLayer(i);
8086 8 : if (poLayer == nullptr ||
8087 4 : !poLayer->TestCapability(OLCFastFeatureCount))
8088 : {
8089 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
8090 0 : break;
8091 : }
8092 4 : GIntBig nCount = poLayer->GetFeatureCount(FALSE);
8093 4 : if (nCount < 0)
8094 : {
8095 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
8096 0 : break;
8097 : }
8098 4 : m_poPrivate->nTotalFeatures += nCount;
8099 : }
8100 : }
8101 : }
8102 :
8103 : while (true)
8104 : {
8105 71 : if (m_poPrivate->poCurrentLayer == nullptr)
8106 : {
8107 44 : m_poPrivate->poCurrentLayer =
8108 22 : GetLayer(m_poPrivate->nCurrentLayerIdx);
8109 22 : if (m_poPrivate->poCurrentLayer == nullptr)
8110 : {
8111 7 : m_poPrivate->nCurrentLayerIdx = -1;
8112 7 : if (ppoBelongingLayer != nullptr)
8113 7 : *ppoBelongingLayer = nullptr;
8114 7 : if (pdfProgressPct != nullptr)
8115 1 : *pdfProgressPct = 1.0;
8116 7 : return nullptr;
8117 : }
8118 15 : m_poPrivate->poCurrentLayer->ResetReading();
8119 15 : m_poPrivate->nFeatureReadInLayer = 0;
8120 15 : if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)
8121 : {
8122 0 : if (m_poPrivate->poCurrentLayer->TestCapability(
8123 0 : OLCFastFeatureCount))
8124 0 : m_poPrivate->nTotalFeaturesInLayer =
8125 0 : m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
8126 : else
8127 0 : m_poPrivate->nTotalFeaturesInLayer = 0;
8128 : }
8129 : }
8130 64 : OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
8131 64 : if (poFeature == nullptr)
8132 : {
8133 13 : m_poPrivate->nCurrentLayerIdx++;
8134 13 : m_poPrivate->poCurrentLayer = nullptr;
8135 13 : continue;
8136 : }
8137 :
8138 51 : m_poPrivate->nFeatureReadInLayer++;
8139 51 : m_poPrivate->nFeatureReadInDataset++;
8140 51 : if (pdfProgressPct != nullptr || pfnProgress != nullptr)
8141 : {
8142 4 : double dfPct = 0.0;
8143 4 : if (m_poPrivate->nTotalFeatures > 0)
8144 : {
8145 4 : dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
8146 4 : m_poPrivate->nTotalFeatures;
8147 : }
8148 : else
8149 : {
8150 0 : dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /
8151 0 : m_poPrivate->nLayerCount;
8152 0 : if (m_poPrivate->nTotalFeaturesInLayer > 0)
8153 : {
8154 0 : dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
8155 0 : m_poPrivate->nTotalFeaturesInLayer /
8156 0 : m_poPrivate->nLayerCount;
8157 : }
8158 : }
8159 4 : if (pdfProgressPct)
8160 4 : *pdfProgressPct = dfPct;
8161 4 : if (pfnProgress)
8162 0 : pfnProgress(dfPct, "", nullptr);
8163 : }
8164 :
8165 51 : if (ppoBelongingLayer != nullptr)
8166 51 : *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
8167 51 : return poFeature;
8168 13 : }
8169 : }
8170 :
8171 : /************************************************************************/
8172 : /* GDALDatasetGetNextFeature() */
8173 : /************************************************************************/
8174 : /**
8175 : \brief Fetch the next available feature from this dataset.
8176 :
8177 : This method is intended for the few drivers where OGR_L_GetNextFeature()
8178 : is not efficient, but in general OGR_L_GetNextFeature() is a more
8179 : natural API.
8180 :
8181 : The returned feature becomes the responsibility of the caller to
8182 : delete with OGRFeature::DestroyFeature().
8183 :
8184 : Depending on the driver, this method may return features from layers in a
8185 : non sequential way. This is what may happen when the
8186 : ODsCRandomLayerRead capability is declared (for example for the
8187 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
8188 : advised to use GDALDataset::GetNextFeature() instead of
8189 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
8190 : implementation.
8191 :
8192 : The default implementation, used by most drivers, will
8193 : however iterate over each layer, and then over each feature within this
8194 : layer.
8195 :
8196 : This method takes into account spatial and attribute filters set on layers that
8197 : will be iterated upon.
8198 :
8199 : The ResetReading() method can be used to start at the beginning again.
8200 :
8201 : Depending on drivers, this may also have the side effect of calling
8202 : OGRLayer::GetNextFeature() on the layers of this dataset.
8203 :
8204 : This method is the same as the C++ method GDALDataset::GetNextFeature()
8205 :
8206 : @param hDS dataset handle.
8207 : @param phBelongingLayer a pointer to a OGRLayer* variable to receive the
8208 : layer to which the object belongs to, or NULL.
8209 : It is possible that the output of *ppoBelongingLayer
8210 : to be NULL despite the feature not being NULL.
8211 : @param pdfProgressPct a pointer to a double variable to receive the
8212 : percentage progress (in [0,1] range), or NULL.
8213 : On return, the pointed value might be negative if
8214 : determining the progress is not possible.
8215 : @param pfnProgress a progress callback to report progress (for
8216 : GetNextFeature() calls that might have a long
8217 : duration) and offer cancellation possibility, or NULL
8218 : @param pProgressData user data provided to pfnProgress, or NULL
8219 : @return a feature, or NULL if no more features are available.
8220 : @since GDAL 2.2
8221 : */
8222 1917 : OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,
8223 : OGRLayerH *phBelongingLayer,
8224 : double *pdfProgressPct,
8225 : GDALProgressFunc pfnProgress,
8226 : void *pProgressData)
8227 : {
8228 1917 : VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
8229 :
8230 3834 : return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(
8231 : reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
8232 3834 : pfnProgress, pProgressData));
8233 : }
8234 :
8235 : /************************************************************************/
8236 : /* TestCapability() */
8237 : /************************************************************************/
8238 :
8239 : /**
8240 : \fn GDALDataset::TestCapability( const char * pszCap )
8241 : \brief Test if capability is available.
8242 :
8243 : One of the following dataset capability names can be passed into this
8244 : method, and a TRUE or FALSE value will be returned indicating whether or not
8245 : the capability is available for this object.
8246 :
8247 : <ul>
8248 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
8249 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
8250 : layers.<p>
8251 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
8252 : datasource support CreateGeomField() just after layer creation.<p>
8253 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
8254 : geometries.<p>
8255 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
8256 : transactions.<p>
8257 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
8258 : transactions through emulation.<p>
8259 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
8260 : GetNextFeature() implementation, potentially returning features from
8261 : layers in a non sequential way.<p>
8262 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
8263 : CreateFeature() on layers in a non sequential way.<p>
8264 : <li> <b>GDsCAddRelationship</b>: True if AddRelationship() is supported</li>
8265 : <li> <b>GDsCDeleteRelationship</b>: True if DeleteRelationship() is supported</li>
8266 : <li> <b>GDsCUpdateRelationship</b>: True if UpdateRelationship() is supported</li>
8267 : <li> <b>GDsCFastGetExtent</b>: True if GetExtent() is fast</li>
8268 : <li> <b>GDsCFastGetExtentWGS84LongLat</b>: True if GetExtentWGS84LongLat() is fast</li>
8269 : </ul>
8270 :
8271 : The \#define macro forms of the capability names should be used in preference
8272 : to the strings themselves to avoid misspelling.
8273 :
8274 : This method is the same as the C function GDALDatasetTestCapability() and the
8275 : deprecated OGR_DS_TestCapability().
8276 :
8277 : In GDAL 1.X, this method used to be in the OGRDataSource class.
8278 :
8279 : @param pszCap the capability to test.
8280 :
8281 : @return TRUE if capability available otherwise FALSE.
8282 : */
8283 :
8284 588 : int GDALDataset::TestCapability(const char *pszCap) const
8285 : {
8286 588 : if (EQUAL(pszCap, GDsCFastGetExtent) ||
8287 586 : EQUAL(pszCap, GDsCFastGetExtentWGS84LongLat))
8288 : {
8289 4 : for (auto &&poLayer : GetLayers())
8290 : {
8291 2 : if (!poLayer->TestCapability(OLCFastGetExtent))
8292 2 : return FALSE;
8293 : }
8294 2 : return TRUE;
8295 : }
8296 584 : return FALSE;
8297 : }
8298 :
8299 : /************************************************************************/
8300 : /* GDALDatasetTestCapability() */
8301 : /************************************************************************/
8302 :
8303 : /**
8304 : \brief Test if capability is available.
8305 :
8306 : One of the following dataset capability names can be passed into this
8307 : function, and a TRUE or FALSE value will be returned indicating whether or not
8308 : the capability is available for this object.
8309 :
8310 : <ul>
8311 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
8312 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
8313 : layers.<p>
8314 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
8315 : datasource support CreateGeomField() just after layer creation.<p>
8316 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
8317 : geometries.<p>
8318 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
8319 : transactions.<p>
8320 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
8321 : transactions through emulation.<p>
8322 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
8323 : GetNextFeature() implementation, potentially returning features from
8324 : layers in a non sequential way.<p>
8325 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
8326 : CreateFeature() on layers in a non sequential way.<p>
8327 : <li> <b>GDsCAddRelationship</b>: True if AddRelationship() is supported</li>
8328 : <li> <b>GDsCDeleteRelationship</b>: True if DeleteRelationship() is supported</li>
8329 : <li> <b>GDsCUpdateRelationship</b>: True if UpdateRelationship() is supported</li>
8330 : <li> <b>GDsCFastGetExtent</b>: True if GetExtent() is fast</li>
8331 : <li> <b>GDsCFastGetExtentWGS84LongLat</b>: True if GetExtentWGS84LongLat() is fast</li>
8332 : </ul>
8333 :
8334 : The \#define macro forms of the capability names should be used in preference
8335 : to the strings themselves to avoid misspelling.
8336 :
8337 : This function is the same as the C++ method GDALDataset::TestCapability()
8338 :
8339 : @since GDAL 2.0
8340 :
8341 : @param hDS the dataset handle.
8342 : @param pszCap the capability to test.
8343 :
8344 : @return TRUE if capability available otherwise FALSE.
8345 : */
8346 122 : int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)
8347 :
8348 : {
8349 122 : VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
8350 122 : VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
8351 :
8352 122 : return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
8353 : }
8354 :
8355 : /************************************************************************/
8356 : /* StartTransaction() */
8357 : /************************************************************************/
8358 :
8359 : /**
8360 : \fn GDALDataset::StartTransaction(int)
8361 : \brief For datasources which support transactions, StartTransaction creates a
8362 : `transaction.
8363 :
8364 : If starting the transaction fails, will return
8365 : OGRERR_FAILURE. Datasources which do not support transactions will
8366 : always return OGRERR_UNSUPPORTED_OPERATION.
8367 :
8368 : Nested transactions are not supported.
8369 :
8370 : All changes done after the start of the transaction are definitely applied in
8371 : the datasource if CommitTransaction() is called. They may be canceled by
8372 : calling RollbackTransaction() instead.
8373 :
8374 : At the time of writing, transactions only apply on vector layers.
8375 :
8376 : Datasets that support transactions will advertise the ODsCTransactions
8377 : capability. Use of transactions at dataset level is generally preferred to
8378 : transactions at layer level, whose scope is rarely limited to the layer from
8379 : which it was started.
8380 :
8381 : In case StartTransaction() fails, neither CommitTransaction() or
8382 : RollbackTransaction() should be called.
8383 :
8384 : If an error occurs after a successful StartTransaction(), the whole transaction
8385 : may or may not be implicitly canceled, depending on drivers. (e.g. the PG
8386 : driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
8387 : an explicit call to RollbackTransaction() should be done to keep things
8388 : balanced.
8389 :
8390 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8391 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8392 : with significant overhead, in which case the user must explicitly allow for
8393 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8394 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8395 : ODsCTransactions).
8396 :
8397 : This function is the same as the C function GDALDatasetStartTransaction().
8398 :
8399 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8400 : transaction
8401 : mechanism is acceptable.
8402 :
8403 : @return OGRERR_NONE on success.
8404 : @since GDAL 2.0
8405 : */
8406 :
8407 37 : OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
8408 : {
8409 37 : return OGRERR_UNSUPPORTED_OPERATION;
8410 : }
8411 :
8412 : /************************************************************************/
8413 : /* GDALDatasetStartTransaction() */
8414 : /************************************************************************/
8415 :
8416 : /**
8417 : \brief For datasources which support transactions, StartTransaction creates a
8418 : transaction.
8419 :
8420 : If starting the transaction fails, will return
8421 : OGRERR_FAILURE. Datasources which do not support transactions will
8422 : always return OGRERR_UNSUPPORTED_OPERATION.
8423 :
8424 : Nested transactions are not supported.
8425 :
8426 : All changes done after the start of the transaction are definitely applied in
8427 : the datasource if CommitTransaction() is called. They may be canceled by
8428 : calling RollbackTransaction() instead.
8429 :
8430 : At the time of writing, transactions only apply on vector layers.
8431 :
8432 : Datasets that support transactions will advertise the ODsCTransactions
8433 : capability.
8434 : Use of transactions at dataset level is generally preferred to transactions at
8435 : layer level, whose scope is rarely limited to the layer from which it was
8436 : started.
8437 :
8438 : In case StartTransaction() fails, neither CommitTransaction() or
8439 : RollbackTransaction() should be called.
8440 :
8441 : If an error occurs after a successful StartTransaction(), the whole
8442 : transaction may or may not be implicitly canceled, depending on drivers. (e.g.
8443 : the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
8444 : error, an explicit call to RollbackTransaction() should be done to keep things
8445 : balanced.
8446 :
8447 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8448 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8449 : with significant overhead, in which case the user must explicitly allow for
8450 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8451 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8452 : ODsCTransactions).
8453 :
8454 : This function is the same as the C++ method GDALDataset::StartTransaction()
8455 :
8456 : @param hDS the dataset handle.
8457 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8458 : transaction
8459 : mechanism is acceptable.
8460 :
8461 : @return OGRERR_NONE on success.
8462 : @since GDAL 2.0
8463 : */
8464 105 : OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
8465 : {
8466 105 : VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
8467 : OGRERR_INVALID_HANDLE);
8468 :
8469 : #ifdef OGRAPISPY_ENABLED
8470 105 : if (bOGRAPISpyEnabled)
8471 2 : OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
8472 : #endif
8473 :
8474 105 : return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
8475 : }
8476 :
8477 : /************************************************************************/
8478 : /* CommitTransaction() */
8479 : /************************************************************************/
8480 :
8481 : /**
8482 : \brief For datasources which support transactions, CommitTransaction commits a
8483 : transaction.
8484 :
8485 : If no transaction is active, or the commit fails, will return
8486 : OGRERR_FAILURE. Datasources which do not support transactions will
8487 : always return OGRERR_UNSUPPORTED_OPERATION.
8488 :
8489 : Depending on drivers, this may or may not abort layer sequential readings that
8490 : are active.
8491 :
8492 : This function is the same as the C function GDALDatasetCommitTransaction().
8493 :
8494 : @return OGRERR_NONE on success.
8495 : @since GDAL 2.0
8496 : */
8497 52 : OGRErr GDALDataset::CommitTransaction()
8498 : {
8499 52 : return OGRERR_UNSUPPORTED_OPERATION;
8500 : }
8501 :
8502 : /************************************************************************/
8503 : /* GDALDatasetCommitTransaction() */
8504 : /************************************************************************/
8505 :
8506 : /**
8507 : \brief For datasources which support transactions, CommitTransaction commits a
8508 : transaction.
8509 :
8510 : If no transaction is active, or the commit fails, will return
8511 : OGRERR_FAILURE. Datasources which do not support transactions will
8512 : always return OGRERR_UNSUPPORTED_OPERATION.
8513 :
8514 : Depending on drivers, this may or may not abort layer sequential readings that
8515 : are active.
8516 :
8517 : This function is the same as the C++ method GDALDataset::CommitTransaction()
8518 :
8519 : @return OGRERR_NONE on success.
8520 : @since GDAL 2.0
8521 : */
8522 76 : OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
8523 : {
8524 76 : VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
8525 : OGRERR_INVALID_HANDLE);
8526 :
8527 : #ifdef OGRAPISPY_ENABLED
8528 76 : if (bOGRAPISpyEnabled)
8529 2 : OGRAPISpy_Dataset_CommitTransaction(hDS);
8530 : #endif
8531 :
8532 76 : return GDALDataset::FromHandle(hDS)->CommitTransaction();
8533 : }
8534 :
8535 : /************************************************************************/
8536 : /* RollbackTransaction() */
8537 : /************************************************************************/
8538 :
8539 : /**
8540 : \brief For datasources which support transactions, RollbackTransaction will
8541 : roll back a datasource to its state before the start of the current
8542 : transaction.
8543 : If no transaction is active, or the rollback fails, will return
8544 : OGRERR_FAILURE. Datasources which do not support transactions will
8545 : always return OGRERR_UNSUPPORTED_OPERATION.
8546 :
8547 : This function is the same as the C function GDALDatasetRollbackTransaction().
8548 :
8549 : @return OGRERR_NONE on success.
8550 : @since GDAL 2.0
8551 : */
8552 2 : OGRErr GDALDataset::RollbackTransaction()
8553 : {
8554 2 : return OGRERR_UNSUPPORTED_OPERATION;
8555 : }
8556 :
8557 : /************************************************************************/
8558 : /* GDALDatasetRollbackTransaction() */
8559 : /************************************************************************/
8560 :
8561 : /**
8562 : \brief For datasources which support transactions, RollbackTransaction will
8563 : roll back a datasource to its state before the start of the current
8564 : transaction.
8565 : If no transaction is active, or the rollback fails, will return
8566 : OGRERR_FAILURE. Datasources which do not support transactions will
8567 : always return OGRERR_UNSUPPORTED_OPERATION.
8568 :
8569 : This function is the same as the C++ method GDALDataset::RollbackTransaction().
8570 :
8571 : @return OGRERR_NONE on success.
8572 : @since GDAL 2.0
8573 : */
8574 44 : OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
8575 : {
8576 44 : VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
8577 : OGRERR_INVALID_HANDLE);
8578 :
8579 : #ifdef OGRAPISPY_ENABLED
8580 44 : if (bOGRAPISpyEnabled)
8581 2 : OGRAPISpy_Dataset_RollbackTransaction(hDS);
8582 : #endif
8583 :
8584 44 : return GDALDataset::FromHandle(hDS)->RollbackTransaction();
8585 : }
8586 :
8587 : //! @cond Doxygen_Suppress
8588 :
8589 : /************************************************************************/
8590 : /* ShareLockWithParentDataset() */
8591 : /************************************************************************/
8592 :
8593 : /* To be used typically by the GTiff driver to link overview datasets */
8594 : /* with their main dataset, so that they share the same lock */
8595 : /* Cf https://github.com/OSGeo/gdal/issues/1488 */
8596 : /* The parent dataset should remain alive while the this dataset is alive */
8597 :
8598 2360 : void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)
8599 : {
8600 2360 : if (m_poPrivate != nullptr)
8601 : {
8602 2361 : m_poPrivate->poParentDataset = poParentDataset;
8603 : }
8604 2360 : }
8605 :
8606 : /************************************************************************/
8607 : /* SetQueryLoggerFunc() */
8608 : /************************************************************************/
8609 :
8610 0 : bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,
8611 : CPL_UNUSED void *context)
8612 : {
8613 0 : return false;
8614 : }
8615 :
8616 : /************************************************************************/
8617 : /* EnterReadWrite() */
8618 : /************************************************************************/
8619 :
8620 7995830 : int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
8621 : {
8622 15991500 : if (m_poPrivate == nullptr ||
8623 7995800 : IsThreadSafe(GDAL_OF_RASTER | (nOpenFlags & GDAL_OF_UPDATE)))
8624 11980 : return FALSE;
8625 :
8626 7983760 : if (m_poPrivate->poParentDataset)
8627 242562 : return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
8628 :
8629 7741190 : if (eAccess == GA_Update)
8630 : {
8631 2197280 : if (m_poPrivate->eStateReadWriteMutex ==
8632 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8633 : {
8634 : // In case dead-lock would occur, which is not impossible,
8635 : // this can be used to prevent it, but at the risk of other
8636 : // issues.
8637 10384 : if (CPLTestBool(
8638 : CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
8639 : {
8640 10384 : m_poPrivate->eStateReadWriteMutex =
8641 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
8642 : }
8643 : else
8644 : {
8645 0 : m_poPrivate->eStateReadWriteMutex =
8646 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8647 : }
8648 : }
8649 2197280 : if (m_poPrivate->eStateReadWriteMutex ==
8650 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)
8651 : {
8652 : // There should be no race related to creating this mutex since
8653 : // it should be first created through IWriteBlock() / IRasterIO()
8654 : // and then GDALRasterBlock might call it from another thread.
8655 : #ifdef DEBUG_VERBOSE
8656 : CPLDebug("GDAL",
8657 : "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
8658 : CPLGetPID(), GetDescription());
8659 : #endif
8660 1536110 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8661 :
8662 : const int nCountMutex =
8663 1536160 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
8664 1536100 : if (nCountMutex == 0 && eRWFlag == GF_Read)
8665 : {
8666 520795 : CPLReleaseMutex(m_poPrivate->hMutex);
8667 1653440 : for (int i = 0; i < nBands; i++)
8668 : {
8669 1132640 : auto blockCache = papoBands[i]->poBandBlockCache;
8670 1132640 : if (blockCache)
8671 816959 : blockCache->WaitCompletionPendingTasks();
8672 : }
8673 520795 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8674 : }
8675 :
8676 1536140 : return TRUE;
8677 : }
8678 : }
8679 6205080 : return FALSE;
8680 : }
8681 :
8682 : /************************************************************************/
8683 : /* LeaveReadWrite() */
8684 : /************************************************************************/
8685 :
8686 1765110 : void GDALDataset::LeaveReadWrite()
8687 : {
8688 1765110 : if (m_poPrivate)
8689 : {
8690 1765100 : if (m_poPrivate->poParentDataset)
8691 : {
8692 228947 : m_poPrivate->poParentDataset->LeaveReadWrite();
8693 228947 : return;
8694 : }
8695 :
8696 1536160 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
8697 1536070 : CPLReleaseMutex(m_poPrivate->hMutex);
8698 : #ifdef DEBUG_VERBOSE
8699 : CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
8700 : CPLGetPID(), GetDescription());
8701 : #endif
8702 : }
8703 : }
8704 :
8705 : /************************************************************************/
8706 : /* InitRWLock() */
8707 : /************************************************************************/
8708 :
8709 3985380 : void GDALDataset::InitRWLock()
8710 : {
8711 3985380 : if (m_poPrivate)
8712 : {
8713 3985380 : if (m_poPrivate->poParentDataset)
8714 : {
8715 8592 : m_poPrivate->poParentDataset->InitRWLock();
8716 8592 : return;
8717 : }
8718 :
8719 3976780 : if (m_poPrivate->eStateReadWriteMutex ==
8720 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8721 : {
8722 1 : if (EnterReadWrite(GF_Write))
8723 1 : LeaveReadWrite();
8724 : }
8725 : }
8726 : }
8727 :
8728 : /************************************************************************/
8729 : /* DisableReadWriteMutex() */
8730 : /************************************************************************/
8731 :
8732 : // The mutex logic is broken in multi-threaded situations, for example
8733 : // with 2 WarpedVRT datasets being read at the same time. In that
8734 : // particular case, the mutex is not needed, so allow the VRTWarpedDataset code
8735 : // to disable it.
8736 20307 : void GDALDataset::DisableReadWriteMutex()
8737 : {
8738 20307 : if (m_poPrivate)
8739 : {
8740 20307 : if (m_poPrivate->poParentDataset)
8741 : {
8742 0 : m_poPrivate->poParentDataset->DisableReadWriteMutex();
8743 0 : return;
8744 : }
8745 :
8746 20307 : m_poPrivate->eStateReadWriteMutex =
8747 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8748 : }
8749 : }
8750 :
8751 : /************************************************************************/
8752 : /* TemporarilyDropReadWriteLock() */
8753 : /************************************************************************/
8754 :
8755 3392350 : void GDALDataset::TemporarilyDropReadWriteLock()
8756 : {
8757 3392350 : if (m_poPrivate == nullptr)
8758 0 : return;
8759 :
8760 3392350 : if (m_poPrivate->poParentDataset)
8761 : {
8762 26296 : m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
8763 26295 : return;
8764 : }
8765 :
8766 : #ifndef __COVERITY__
8767 3366050 : if (m_poPrivate->hMutex)
8768 : {
8769 : #ifdef DEBUG_VERBOSE
8770 : CPLDebug("GDAL",
8771 : "[Thread " CPL_FRMT_GIB "] "
8772 : "Temporarily drop RW mutex for %s",
8773 : CPLGetPID(), GetDescription());
8774 : #endif
8775 417975 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8776 : const int nCount =
8777 417976 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8778 : #ifdef DEBUG_EXTRA
8779 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
8780 : #endif
8781 1261100 : for (int i = 0; i < nCount + 1; i++)
8782 : {
8783 : // The mutex is recursive
8784 843123 : CPLReleaseMutex(m_poPrivate->hMutex);
8785 : }
8786 : }
8787 : #endif
8788 : }
8789 :
8790 : /************************************************************************/
8791 : /* ReacquireReadWriteLock() */
8792 : /************************************************************************/
8793 :
8794 3392400 : void GDALDataset::ReacquireReadWriteLock()
8795 : {
8796 3392400 : if (m_poPrivate == nullptr)
8797 0 : return;
8798 :
8799 3392400 : if (m_poPrivate->poParentDataset)
8800 : {
8801 26296 : m_poPrivate->poParentDataset->ReacquireReadWriteLock();
8802 26295 : return;
8803 : }
8804 :
8805 : #ifndef __COVERITY__
8806 3366110 : if (m_poPrivate->hMutex)
8807 : {
8808 : #ifdef DEBUG_VERBOSE
8809 : CPLDebug("GDAL",
8810 : "[Thread " CPL_FRMT_GIB "] "
8811 : "Reacquire temporarily dropped RW mutex for %s",
8812 : CPLGetPID(), GetDescription());
8813 : #endif
8814 417971 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8815 : const int nCount =
8816 417973 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8817 : #ifdef DEBUG_EXTRA
8818 : CPLAssert(nCount ==
8819 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
8820 : #endif
8821 417974 : if (nCount == 0)
8822 18501 : CPLReleaseMutex(m_poPrivate->hMutex);
8823 443660 : for (int i = 0; i < nCount - 1; i++)
8824 : {
8825 : // The mutex is recursive
8826 25685 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8827 : }
8828 : }
8829 : #endif
8830 : }
8831 :
8832 : /************************************************************************/
8833 : /* AcquireMutex() */
8834 : /************************************************************************/
8835 :
8836 196 : int GDALDataset::AcquireMutex()
8837 : {
8838 196 : if (m_poPrivate == nullptr)
8839 0 : return 0;
8840 196 : if (m_poPrivate->poParentDataset)
8841 : {
8842 0 : return m_poPrivate->poParentDataset->AcquireMutex();
8843 : }
8844 :
8845 196 : return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8846 : }
8847 :
8848 : /************************************************************************/
8849 : /* ReleaseMutex() */
8850 : /************************************************************************/
8851 :
8852 196 : void GDALDataset::ReleaseMutex()
8853 : {
8854 196 : if (m_poPrivate)
8855 : {
8856 196 : if (m_poPrivate->poParentDataset)
8857 : {
8858 0 : m_poPrivate->poParentDataset->ReleaseMutex();
8859 0 : return;
8860 : }
8861 :
8862 196 : CPLReleaseMutex(m_poPrivate->hMutex);
8863 : }
8864 : }
8865 :
8866 : //! @endcond
8867 :
8868 : /************************************************************************/
8869 : /* GDALDataset::Features::Iterator::Private */
8870 : /************************************************************************/
8871 :
8872 : struct GDALDataset::Features::Iterator::Private
8873 : {
8874 : GDALDataset::FeatureLayerPair m_oPair{};
8875 : GDALDataset *m_poDS = nullptr;
8876 : bool m_bEOF = true;
8877 : };
8878 :
8879 4 : GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8880 4 : : m_poPrivate(new GDALDataset::Features::Iterator::Private())
8881 : {
8882 4 : m_poPrivate->m_poDS = poDS;
8883 4 : if (bStart)
8884 : {
8885 2 : poDS->ResetReading();
8886 4 : m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(
8887 2 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8888 2 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8889 : }
8890 4 : }
8891 :
8892 : GDALDataset::Features::Iterator::~Iterator() = default;
8893 :
8894 : const GDALDataset::FeatureLayerPair &
8895 20 : GDALDataset::Features::Iterator::operator*() const
8896 : {
8897 20 : return m_poPrivate->m_oPair;
8898 : }
8899 :
8900 20 : GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()
8901 : {
8902 40 : m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(
8903 20 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8904 20 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8905 20 : return *this;
8906 : }
8907 :
8908 22 : bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const
8909 : {
8910 22 : return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
8911 : }
8912 :
8913 : /************************************************************************/
8914 : /* GetFeatures() */
8915 : /************************************************************************/
8916 :
8917 : /** Function that return an iterable object over features in the dataset
8918 : * layer.
8919 : *
8920 : * This is a C++ iterator friendly version of GetNextFeature().
8921 : *
8922 : * Using this iterator for standard range-based loops is safe, but
8923 : * due to implementation limitations, you shouldn't try to access
8924 : * (dereference) more than one iterator step at a time, since the
8925 : * FeatureLayerPair reference which is returned is reused.
8926 : *
8927 : * Typical use is:
8928 : * \code{.cpp}
8929 : * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
8930 : * {
8931 : * std::cout << "Feature of layer " <<
8932 : * oFeatureLayerPair.layer->GetName() << std::endl;
8933 : * oFeatureLayerPair.feature->DumpReadable();
8934 : * }
8935 : * \endcode
8936 : *
8937 : * @see GetNextFeature()
8938 : *
8939 : * @since GDAL 2.3
8940 : */
8941 2 : GDALDataset::Features GDALDataset::GetFeatures()
8942 : {
8943 2 : return Features(this);
8944 : }
8945 :
8946 : /************************************************************************/
8947 : /* begin() */
8948 : /************************************************************************/
8949 :
8950 : /**
8951 : \brief Return beginning of feature iterator.
8952 :
8953 : @since GDAL 2.3
8954 : */
8955 :
8956 2 : const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
8957 : {
8958 2 : return {m_poSelf, true};
8959 : }
8960 :
8961 : /************************************************************************/
8962 : /* end() */
8963 : /************************************************************************/
8964 :
8965 : /**
8966 : \brief Return end of feature iterator.
8967 :
8968 : @since GDAL 2.3
8969 : */
8970 :
8971 2 : const GDALDataset::Features::Iterator GDALDataset::Features::end() const
8972 : {
8973 2 : return {m_poSelf, false};
8974 : }
8975 :
8976 : /************************************************************************/
8977 : /* GDALDataset::Layers::Iterator::Private */
8978 : /************************************************************************/
8979 :
8980 : struct GDALDataset::Layers::Iterator::Private
8981 : {
8982 : OGRLayer *m_poLayer = nullptr;
8983 : int m_iCurLayer = 0;
8984 : int m_nLayerCount = 0;
8985 : GDALDataset *m_poDS = nullptr;
8986 : };
8987 :
8988 2 : GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())
8989 : {
8990 2 : }
8991 :
8992 : // False positive of cppcheck 1.72
8993 : // cppcheck-suppress uninitMemberVar
8994 9 : GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)
8995 9 : : m_poPrivate(new Private(*(oOther.m_poPrivate)))
8996 : {
8997 9 : }
8998 :
8999 5 : GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept
9000 5 : : m_poPrivate(std::move(oOther.m_poPrivate))
9001 : {
9002 5 : }
9003 :
9004 592 : GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)
9005 592 : : m_poPrivate(new Private())
9006 : {
9007 592 : m_poPrivate->m_poDS = poDS;
9008 592 : m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
9009 592 : if (bStart)
9010 : {
9011 298 : if (m_poPrivate->m_nLayerCount)
9012 289 : m_poPrivate->m_poLayer = poDS->GetLayer(0);
9013 : }
9014 : else
9015 : {
9016 294 : m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
9017 : }
9018 592 : }
9019 :
9020 : GDALDataset::Layers::Iterator::~Iterator() = default;
9021 :
9022 : // False positive of cppcheck 1.72
9023 : // cppcheck-suppress operatorEqVarError
9024 : GDALDataset::Layers::Iterator &
9025 1 : GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)
9026 : {
9027 1 : *m_poPrivate = *oOther.m_poPrivate;
9028 1 : return *this;
9029 : }
9030 :
9031 3 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(
9032 : GDALDataset::Layers::Iterator &&oOther) noexcept
9033 : {
9034 3 : m_poPrivate = std::move(oOther.m_poPrivate);
9035 3 : return *this;
9036 : }
9037 :
9038 351 : OGRLayer *GDALDataset::Layers::Iterator::operator*() const
9039 : {
9040 351 : return m_poPrivate->m_poLayer;
9041 : }
9042 :
9043 326 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()
9044 : {
9045 326 : m_poPrivate->m_iCurLayer++;
9046 326 : if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
9047 : {
9048 68 : m_poPrivate->m_poLayer =
9049 68 : m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
9050 : }
9051 : else
9052 : {
9053 258 : m_poPrivate->m_poLayer = nullptr;
9054 : }
9055 326 : return *this;
9056 : }
9057 :
9058 2 : GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
9059 : {
9060 2 : GDALDataset::Layers::Iterator temp = *this;
9061 2 : ++(*this);
9062 2 : return temp;
9063 : }
9064 :
9065 614 : bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const
9066 : {
9067 614 : return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
9068 : }
9069 :
9070 : /************************************************************************/
9071 : /* GetLayers() */
9072 : /************************************************************************/
9073 :
9074 : /** Function that returns an iterable object over layers in the dataset.
9075 : *
9076 : * This is a C++ iterator friendly version of GetLayer().
9077 : *
9078 : * Typical use is:
9079 : * \code{.cpp}
9080 : * for( auto&& poLayer: poDS->GetLayers() )
9081 : * {
9082 : * std::cout << "Layer << poLayer->GetName() << std::endl;
9083 : * }
9084 : * \endcode
9085 : *
9086 : * @see GetLayer()
9087 : *
9088 : * @since GDAL 2.3
9089 : */
9090 299 : GDALDataset::Layers GDALDataset::GetLayers()
9091 : {
9092 299 : return Layers(this);
9093 : }
9094 :
9095 : /************************************************************************/
9096 : /* begin() */
9097 : /************************************************************************/
9098 :
9099 : /**
9100 : \brief Return beginning of layer iterator.
9101 :
9102 : @since GDAL 2.3
9103 : */
9104 :
9105 298 : GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
9106 : {
9107 298 : return {m_poSelf, true};
9108 : }
9109 :
9110 : /************************************************************************/
9111 : /* end() */
9112 : /************************************************************************/
9113 :
9114 : /**
9115 : \brief Return end of layer iterator.
9116 :
9117 : @since GDAL 2.3
9118 : */
9119 :
9120 294 : GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
9121 : {
9122 294 : return {m_poSelf, false};
9123 : }
9124 :
9125 : /************************************************************************/
9126 : /* size() */
9127 : /************************************************************************/
9128 :
9129 : /**
9130 : \brief Get the number of layers in this dataset.
9131 :
9132 : @return layer count.
9133 :
9134 : @since GDAL 2.3
9135 : */
9136 :
9137 1 : size_t GDALDataset::Layers::size() const
9138 : {
9139 1 : return static_cast<size_t>(m_poSelf->GetLayerCount());
9140 : }
9141 :
9142 : /************************************************************************/
9143 : /* operator[]() */
9144 : /************************************************************************/
9145 : /**
9146 : \brief Fetch a layer by index.
9147 :
9148 : The returned layer remains owned by the
9149 : GDALDataset and should not be deleted by the application.
9150 :
9151 : @param iLayer a layer number between 0 and size()-1.
9152 :
9153 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
9154 :
9155 : @since GDAL 2.3
9156 : */
9157 :
9158 9 : OGRLayer *GDALDataset::Layers::operator[](int iLayer)
9159 : {
9160 9 : return m_poSelf->GetLayer(iLayer);
9161 : }
9162 :
9163 : /************************************************************************/
9164 : /* operator[]() */
9165 : /************************************************************************/
9166 : /**
9167 : \brief Fetch a layer by index.
9168 :
9169 : The returned layer remains owned by the
9170 : GDALDataset and should not be deleted by the application.
9171 :
9172 : @param iLayer a layer number between 0 and size()-1.
9173 :
9174 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
9175 :
9176 : @since GDAL 2.3
9177 : */
9178 :
9179 1 : OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)
9180 : {
9181 1 : return m_poSelf->GetLayer(static_cast<int>(iLayer));
9182 : }
9183 :
9184 : /************************************************************************/
9185 : /* operator[]() */
9186 : /************************************************************************/
9187 : /**
9188 : \brief Fetch a layer by name.
9189 :
9190 : The returned layer remains owned by the
9191 : GDALDataset and should not be deleted by the application.
9192 :
9193 : @param pszLayerName layer name
9194 :
9195 : @return the layer, or nullptr if pszLayerName does not match with a layer
9196 :
9197 : @since GDAL 2.3
9198 : */
9199 :
9200 1 : OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)
9201 : {
9202 1 : return m_poSelf->GetLayerByName(pszLayerName);
9203 : }
9204 :
9205 : /************************************************************************/
9206 : /* GDALDataset::ConstLayers::Iterator::Private */
9207 : /************************************************************************/
9208 :
9209 : struct GDALDataset::ConstLayers::Iterator::Private
9210 : {
9211 : const OGRLayer *m_poLayer = nullptr;
9212 : int m_iCurLayer = 0;
9213 : int m_nLayerCount = 0;
9214 : const GDALDataset *m_poDS = nullptr;
9215 : };
9216 :
9217 2 : GDALDataset::ConstLayers::Iterator::Iterator() : m_poPrivate(new Private())
9218 : {
9219 2 : }
9220 :
9221 : // False positive of cppcheck 1.72
9222 : // cppcheck-suppress uninitMemberVar
9223 9 : GDALDataset::ConstLayers::Iterator::Iterator(const Iterator &oOther)
9224 9 : : m_poPrivate(new Private(*(oOther.m_poPrivate)))
9225 : {
9226 9 : }
9227 :
9228 5 : GDALDataset::ConstLayers::Iterator::Iterator(Iterator &&oOther) noexcept
9229 5 : : m_poPrivate(std::move(oOther.m_poPrivate))
9230 : {
9231 5 : }
9232 :
9233 34214 : GDALDataset::ConstLayers::Iterator::Iterator(const GDALDataset *poDS,
9234 34214 : bool bStart)
9235 34214 : : m_poPrivate(new Private())
9236 : {
9237 34216 : m_poPrivate->m_poDS = poDS;
9238 34216 : m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
9239 34219 : if (bStart)
9240 : {
9241 17111 : if (m_poPrivate->m_nLayerCount)
9242 218 : m_poPrivate->m_poLayer = poDS->GetLayer(0);
9243 : }
9244 : else
9245 : {
9246 17108 : m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
9247 : }
9248 34219 : }
9249 :
9250 : GDALDataset::ConstLayers::Iterator::~Iterator() = default;
9251 :
9252 : // False positive of cppcheck 1.72
9253 : // cppcheck-suppress operatorEqVarError
9254 : GDALDataset::ConstLayers::Iterator &
9255 1 : GDALDataset::ConstLayers::Iterator::operator=(const Iterator &oOther)
9256 : {
9257 1 : *m_poPrivate = *oOther.m_poPrivate;
9258 1 : return *this;
9259 : }
9260 :
9261 : GDALDataset::ConstLayers::Iterator &
9262 3 : GDALDataset::ConstLayers::Iterator::operator=(
9263 : GDALDataset::ConstLayers::Iterator &&oOther) noexcept
9264 : {
9265 3 : m_poPrivate = std::move(oOther.m_poPrivate);
9266 3 : return *this;
9267 : }
9268 :
9269 16176 : const OGRLayer *GDALDataset::ConstLayers::Iterator::operator*() const
9270 : {
9271 16176 : return m_poPrivate->m_poLayer;
9272 : }
9273 :
9274 : GDALDataset::ConstLayers::Iterator &
9275 16171 : GDALDataset::ConstLayers::Iterator::operator++()
9276 : {
9277 16171 : m_poPrivate->m_iCurLayer++;
9278 16171 : if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
9279 : {
9280 15964 : m_poPrivate->m_poLayer =
9281 15964 : m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
9282 : }
9283 : else
9284 : {
9285 207 : m_poPrivate->m_poLayer = nullptr;
9286 : }
9287 16171 : return *this;
9288 : }
9289 :
9290 : GDALDataset::ConstLayers::Iterator
9291 2 : GDALDataset::ConstLayers::Iterator::operator++(int)
9292 : {
9293 2 : GDALDataset::ConstLayers::Iterator temp = *this;
9294 2 : ++(*this);
9295 2 : return temp;
9296 : }
9297 :
9298 33270 : bool GDALDataset::ConstLayers::Iterator::operator!=(const Iterator &it) const
9299 : {
9300 33270 : return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
9301 : }
9302 :
9303 : /************************************************************************/
9304 : /* GetLayers() */
9305 : /************************************************************************/
9306 :
9307 : /** Function that returns an iterable object over layers in the dataset.
9308 : *
9309 : * This is a C++ iterator friendly version of GetLayer().
9310 : *
9311 : * Typical use is:
9312 : * \code{.cpp}
9313 : * for( auto&& poLayer: poDS->GetLayers() )
9314 : * {
9315 : * std::cout << "Layer << poLayer->GetName() << std::endl;
9316 : * }
9317 : * \endcode
9318 : *
9319 : * @see GetLayer()
9320 : *
9321 : * @since GDAL 3.12
9322 : */
9323 17112 : GDALDataset::ConstLayers GDALDataset::GetLayers() const
9324 : {
9325 17112 : return ConstLayers(this);
9326 : }
9327 :
9328 : /************************************************************************/
9329 : /* begin() */
9330 : /************************************************************************/
9331 :
9332 : /**
9333 : \brief Return beginning of layer iterator.
9334 :
9335 : @since GDAL 3.12
9336 : */
9337 :
9338 17112 : GDALDataset::ConstLayers::Iterator GDALDataset::ConstLayers::begin() const
9339 : {
9340 17112 : return {m_poSelf, true};
9341 : }
9342 :
9343 : /************************************************************************/
9344 : /* end() */
9345 : /************************************************************************/
9346 :
9347 : /**
9348 : \brief Return end of layer iterator.
9349 :
9350 : @since GDAL 3.12
9351 : */
9352 :
9353 17105 : GDALDataset::ConstLayers::Iterator GDALDataset::ConstLayers::end() const
9354 : {
9355 17105 : return {m_poSelf, false};
9356 : }
9357 :
9358 : /************************************************************************/
9359 : /* size() */
9360 : /************************************************************************/
9361 :
9362 : /**
9363 : \brief Get the number of layers in this dataset.
9364 :
9365 : @return layer count.
9366 :
9367 : @since GDAL 3.12
9368 : */
9369 :
9370 1 : size_t GDALDataset::ConstLayers::size() const
9371 : {
9372 1 : return static_cast<size_t>(m_poSelf->GetLayerCount());
9373 : }
9374 :
9375 : /************************************************************************/
9376 : /* operator[]() */
9377 : /************************************************************************/
9378 : /**
9379 : \brief Fetch a layer by index.
9380 :
9381 : The returned layer remains owned by the
9382 : GDALDataset and should not be deleted by the application.
9383 :
9384 : @param iLayer a layer number between 0 and size()-1.
9385 :
9386 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
9387 :
9388 : @since GDAL 3.12
9389 : */
9390 :
9391 9 : const OGRLayer *GDALDataset::ConstLayers::operator[](int iLayer)
9392 : {
9393 9 : return m_poSelf->GetLayer(iLayer);
9394 : }
9395 :
9396 : /************************************************************************/
9397 : /* operator[]() */
9398 : /************************************************************************/
9399 : /**
9400 : \brief Fetch a layer by index.
9401 :
9402 : The returned layer remains owned by the
9403 : GDALDataset and should not be deleted by the application.
9404 :
9405 : @param iLayer a layer number between 0 and size()-1.
9406 :
9407 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
9408 :
9409 : @since GDAL 3.12
9410 : */
9411 :
9412 1 : const OGRLayer *GDALDataset::ConstLayers::operator[](size_t iLayer)
9413 : {
9414 1 : return m_poSelf->GetLayer(static_cast<int>(iLayer));
9415 : }
9416 :
9417 : /************************************************************************/
9418 : /* operator[]() */
9419 : /************************************************************************/
9420 : /**
9421 : \brief Fetch a layer by name.
9422 :
9423 : The returned layer remains owned by the
9424 : GDALDataset and should not be deleted by the application.
9425 :
9426 : @param pszLayerName layer name
9427 :
9428 : @return the layer, or nullptr if pszLayerName does not match with a layer
9429 :
9430 : @since GDAL 3.12
9431 : */
9432 :
9433 1 : const OGRLayer *GDALDataset::ConstLayers::operator[](const char *pszLayerName)
9434 : {
9435 1 : return const_cast<GDALDataset *>(m_poSelf)->GetLayerByName(pszLayerName);
9436 : }
9437 :
9438 : /************************************************************************/
9439 : /* GDALDataset::Bands::Iterator::Private */
9440 : /************************************************************************/
9441 :
9442 : struct GDALDataset::Bands::Iterator::Private
9443 : {
9444 : GDALRasterBand *m_poBand = nullptr;
9445 : int m_iCurBand = 0;
9446 : int m_nBandCount = 0;
9447 : GDALDataset *m_poDS = nullptr;
9448 : };
9449 :
9450 6 : GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)
9451 6 : : m_poPrivate(new GDALDataset::Bands::Iterator::Private())
9452 : {
9453 6 : m_poPrivate->m_poDS = poDS;
9454 6 : m_poPrivate->m_nBandCount = poDS->GetRasterCount();
9455 6 : if (bStart)
9456 : {
9457 3 : if (m_poPrivate->m_nBandCount)
9458 3 : m_poPrivate->m_poBand = poDS->GetRasterBand(1);
9459 : }
9460 : else
9461 : {
9462 3 : m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
9463 : }
9464 6 : }
9465 :
9466 : GDALDataset::Bands::Iterator::~Iterator() = default;
9467 :
9468 5 : GDALRasterBand *GDALDataset::Bands::Iterator::operator*()
9469 : {
9470 5 : return m_poPrivate->m_poBand;
9471 : }
9472 :
9473 3 : GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()
9474 : {
9475 3 : m_poPrivate->m_iCurBand++;
9476 3 : if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
9477 : {
9478 2 : m_poPrivate->m_poBand =
9479 2 : m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
9480 : }
9481 : else
9482 : {
9483 1 : m_poPrivate->m_poBand = nullptr;
9484 : }
9485 3 : return *this;
9486 : }
9487 :
9488 6 : bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const
9489 : {
9490 6 : return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
9491 : }
9492 :
9493 : /************************************************************************/
9494 : /* GetBands() */
9495 : /************************************************************************/
9496 :
9497 : /** Function that returns an iterable object over GDALRasterBand in the dataset.
9498 : *
9499 : * This is a C++ iterator friendly version of GetRasterBand().
9500 : *
9501 : * Typical use is:
9502 : * \code{.cpp}
9503 : * for( auto&& poBand: poDS->GetBands() )
9504 : * {
9505 : * std::cout << "Band << poBand->GetDescription() << std::endl;
9506 : * }
9507 : * \endcode
9508 : *
9509 : * @see GetRasterBand()
9510 : *
9511 : * @since GDAL 2.3
9512 : */
9513 7 : GDALDataset::Bands GDALDataset::GetBands()
9514 : {
9515 7 : return Bands(this);
9516 : }
9517 :
9518 : /************************************************************************/
9519 : /* begin() */
9520 : /************************************************************************/
9521 :
9522 : /**
9523 : \brief Return beginning of band iterator.
9524 :
9525 : @since GDAL 2.3
9526 : */
9527 :
9528 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
9529 : {
9530 3 : return {m_poSelf, true};
9531 : }
9532 :
9533 : /************************************************************************/
9534 : /* end() */
9535 : /************************************************************************/
9536 :
9537 : /**
9538 : \brief Return end of band iterator.
9539 :
9540 : @since GDAL 2.3
9541 : */
9542 :
9543 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
9544 : {
9545 3 : return {m_poSelf, false};
9546 : }
9547 :
9548 : /************************************************************************/
9549 : /* size() */
9550 : /************************************************************************/
9551 :
9552 : /**
9553 : \brief Get the number of raster bands in this dataset.
9554 :
9555 : @return raster band count.
9556 :
9557 : @since GDAL 2.3
9558 : */
9559 :
9560 2 : size_t GDALDataset::Bands::size() const
9561 : {
9562 2 : return static_cast<size_t>(m_poSelf->GetRasterCount());
9563 : }
9564 :
9565 : /************************************************************************/
9566 : /* operator[]() */
9567 : /************************************************************************/
9568 : /**
9569 : \brief Fetch a raster band by index.
9570 :
9571 : The returned band remains owned by the
9572 : GDALDataset and should not be deleted by the application.
9573 :
9574 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9575 : consistent with the conventions of C/C++, i.e. starting at 0.
9576 :
9577 : @param iBand a band index between 0 and size()-1.
9578 :
9579 : @return the band, or nullptr if iBand is out of range or an error occurs.
9580 :
9581 : @since GDAL 2.3
9582 : */
9583 :
9584 1 : GDALRasterBand *GDALDataset::Bands::operator[](int iBand)
9585 : {
9586 1 : return m_poSelf->GetRasterBand(1 + iBand);
9587 : }
9588 :
9589 : /************************************************************************/
9590 : /* operator[]() */
9591 : /************************************************************************/
9592 :
9593 : /**
9594 : \brief Fetch a raster band by index.
9595 :
9596 : The returned band remains owned by the
9597 : GDALDataset and should not be deleted by the application.
9598 :
9599 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9600 : consistent with the conventions of C/C++, i.e. starting at 0.
9601 :
9602 : @param iBand a band index between 0 and size()-1.
9603 :
9604 : @return the band, or nullptr if iBand is out of range or an error occurs.
9605 :
9606 : @since GDAL 2.3
9607 : */
9608 :
9609 1 : GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)
9610 : {
9611 1 : return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
9612 : }
9613 :
9614 : /************************************************************************/
9615 : /* GetRootGroup() */
9616 : /************************************************************************/
9617 :
9618 : /**
9619 : \brief Return the root GDALGroup of this dataset.
9620 :
9621 : Only valid for multidimensional datasets.
9622 :
9623 : This is the same as the C function GDALDatasetGetRootGroup().
9624 :
9625 : @since GDAL 3.1
9626 : */
9627 :
9628 2788 : std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
9629 : {
9630 2788 : return nullptr;
9631 : }
9632 :
9633 : /************************************************************************/
9634 : /* GetRawBinaryLayout() */
9635 : /************************************************************************/
9636 :
9637 : //! @cond Doxygen_Suppress
9638 : /**
9639 : \brief Return the layout of a dataset that can be considered as a raw binary
9640 : format.
9641 :
9642 : @param sLayout Structure that will be set if the dataset is a raw binary one.
9643 : @return true if the dataset is a raw binary one.
9644 : @since GDAL 3.1
9645 : */
9646 :
9647 0 : bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)
9648 : {
9649 0 : CPL_IGNORE_RET_VAL(sLayout);
9650 0 : return false;
9651 : }
9652 :
9653 : //! @endcond
9654 :
9655 : /************************************************************************/
9656 : /* ClearStatistics() */
9657 : /************************************************************************/
9658 :
9659 : /**
9660 : \brief Clear statistics
9661 :
9662 : Only implemented for now in PAM supported datasets
9663 :
9664 : This is the same as the C function GDALDatasetClearStatistics().
9665 :
9666 : @since GDAL 3.2
9667 : */
9668 :
9669 11 : void GDALDataset::ClearStatistics()
9670 : {
9671 22 : auto poRootGroup = GetRootGroup();
9672 11 : if (poRootGroup)
9673 1 : poRootGroup->ClearStatistics();
9674 11 : }
9675 :
9676 : /************************************************************************/
9677 : /* GDALDatasetClearStatistics() */
9678 : /************************************************************************/
9679 :
9680 : /**
9681 : \brief Clear statistics
9682 :
9683 : This is the same as the C++ method GDALDataset::ClearStatistics().
9684 :
9685 : @since GDAL 3.2
9686 : */
9687 :
9688 2 : void GDALDatasetClearStatistics(GDALDatasetH hDS)
9689 : {
9690 2 : VALIDATE_POINTER0(hDS, __func__);
9691 2 : GDALDataset::FromHandle(hDS)->ClearStatistics();
9692 : }
9693 :
9694 : /************************************************************************/
9695 : /* GetFieldDomainNames() */
9696 : /************************************************************************/
9697 :
9698 : /** Returns a list of the names of all field domains stored in the dataset.
9699 : *
9700 : * @note The default implementation assumes that drivers fully populate
9701 : * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect
9702 : * then a specialized implementation of GetFieldDomainNames() must be
9703 : * implemented.
9704 : *
9705 : * @param papszOptions Driver specific options determining how attributes
9706 : * should be retrieved. Pass nullptr for default behavior.
9707 : *
9708 : * @return list of field domain names
9709 : * @since GDAL 3.5
9710 : */
9711 : std::vector<std::string>
9712 43 : GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const
9713 : {
9714 :
9715 43 : std::vector<std::string> names;
9716 43 : names.reserve(m_oMapFieldDomains.size());
9717 55 : for (const auto &it : m_oMapFieldDomains)
9718 : {
9719 12 : names.emplace_back(it.first);
9720 : }
9721 43 : return names;
9722 : }
9723 :
9724 : /************************************************************************/
9725 : /* GDALDatasetGetFieldDomainNames() */
9726 : /************************************************************************/
9727 :
9728 : /** Returns a list of the names of all field domains stored in the dataset.
9729 : *
9730 : * This is the same as the C++ method GDALDataset::GetFieldDomainNames().
9731 : *
9732 : * @param hDS Dataset handle.
9733 : * @param papszOptions Driver specific options determining how attributes
9734 : * should be retrieved. Pass nullptr for default behavior.
9735 : *
9736 : * @return list of field domain names, to be freed with CSLDestroy()
9737 : * @since GDAL 3.5
9738 : */
9739 32 : char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,
9740 : CSLConstList papszOptions)
9741 : {
9742 32 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9743 : auto names =
9744 64 : GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);
9745 64 : CPLStringList res;
9746 137 : for (const auto &name : names)
9747 : {
9748 105 : res.AddString(name.c_str());
9749 : }
9750 32 : return res.StealList();
9751 : }
9752 :
9753 : /************************************************************************/
9754 : /* GetFieldDomain() */
9755 : /************************************************************************/
9756 :
9757 : /** Get a field domain from its name.
9758 : *
9759 : * @return the field domain, or nullptr if not found.
9760 : * @since GDAL 3.3
9761 : */
9762 270 : const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const
9763 : {
9764 270 : const auto iter = m_oMapFieldDomains.find(name);
9765 270 : if (iter == m_oMapFieldDomains.end())
9766 116 : return nullptr;
9767 154 : return iter->second.get();
9768 : }
9769 :
9770 : /************************************************************************/
9771 : /* GDALDatasetGetFieldDomain() */
9772 : /************************************************************************/
9773 :
9774 : /** Get a field domain from its name.
9775 : *
9776 : * This is the same as the C++ method GDALDataset::GetFieldDomain().
9777 : *
9778 : * @param hDS Dataset handle.
9779 : * @param pszName Name of field domain.
9780 : * @return the field domain (ownership remains to the dataset), or nullptr if
9781 : * not found.
9782 : * @since GDAL 3.3
9783 : */
9784 114 : OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)
9785 : {
9786 114 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9787 114 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9788 114 : return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(
9789 114 : GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
9790 : }
9791 :
9792 : /************************************************************************/
9793 : /* AddFieldDomain() */
9794 : /************************************************************************/
9795 :
9796 : /** Add a field domain to the dataset.
9797 : *
9798 : * Only a few drivers will support this operation, and some of them might only
9799 : * support it only for some types of field domains.
9800 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9801 : * support this operation. A dataset having at least some support for this
9802 : * operation should report the ODsCAddFieldDomain dataset capability.
9803 : *
9804 : * Anticipated failures will not be emitted through the CPLError()
9805 : * infrastructure, but will be reported in the failureReason output parameter.
9806 : *
9807 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9808 : * default implementation of GetFieldDomainNames() to work correctly, or
9809 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9810 : * implemented.
9811 : *
9812 : * @param domain The domain definition.
9813 : * @param failureReason Output parameter. Will contain an error message if
9814 : * an error occurs.
9815 : * @return true in case of success.
9816 : * @since GDAL 3.3
9817 : */
9818 0 : bool GDALDataset::AddFieldDomain(
9819 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9820 : std::string &failureReason)
9821 : {
9822 0 : failureReason = "AddFieldDomain not supported by this driver";
9823 0 : return false;
9824 : }
9825 :
9826 : /************************************************************************/
9827 : /* GDALDatasetAddFieldDomain() */
9828 : /************************************************************************/
9829 :
9830 : /** Add a field domain to the dataset.
9831 : *
9832 : * Only a few drivers will support this operation, and some of them might only
9833 : * support it only for some types of field domains.
9834 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9835 : * support this operation. A dataset having at least some support for this
9836 : * operation should report the ODsCAddFieldDomain dataset capability.
9837 : *
9838 : * Anticipated failures will not be emitted through the CPLError()
9839 : * infrastructure, but will be reported in the ppszFailureReason output
9840 : * parameter.
9841 : *
9842 : * @param hDS Dataset handle.
9843 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9844 : * the passed object is copied.
9845 : * @param ppszFailureReason Output parameter. Will contain an error message if
9846 : * an error occurs (*ppszFailureReason to be freed
9847 : * with CPLFree). May be NULL.
9848 : * @return true in case of success.
9849 : * @since GDAL 3.3
9850 : */
9851 37 : bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,
9852 : char **ppszFailureReason)
9853 : {
9854 37 : VALIDATE_POINTER1(hDS, __func__, false);
9855 37 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9856 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9857 74 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9858 37 : if (poDomain == nullptr)
9859 0 : return false;
9860 37 : std::string failureReason;
9861 74 : const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(
9862 37 : std::move(poDomain), failureReason);
9863 37 : if (ppszFailureReason)
9864 : {
9865 37 : *ppszFailureReason =
9866 37 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9867 : }
9868 37 : return bRet;
9869 : }
9870 :
9871 : /************************************************************************/
9872 : /* DeleteFieldDomain() */
9873 : /************************************************************************/
9874 :
9875 : /** Removes a field domain from the dataset.
9876 : *
9877 : * Only a few drivers will support this operation.
9878 : *
9879 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9880 : * support this operation. A dataset having at least some support for this
9881 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9882 : *
9883 : * Anticipated failures will not be emitted through the CPLError()
9884 : * infrastructure, but will be reported in the failureReason output parameter.
9885 : *
9886 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9887 : * default implementation of GetFieldDomainNames() to work correctly, or
9888 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9889 : * implemented.
9890 : *
9891 : * @param name The domain name.
9892 : * @param failureReason Output parameter. Will contain an error message if
9893 : * an error occurs.
9894 : * @return true in case of success.
9895 : * @since GDAL 3.5
9896 : */
9897 0 : bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,
9898 : std::string &failureReason)
9899 : {
9900 0 : failureReason = "DeleteFieldDomain not supported by this driver";
9901 0 : return false;
9902 : }
9903 :
9904 : /************************************************************************/
9905 : /* GDALDatasetDeleteFieldDomain() */
9906 : /************************************************************************/
9907 :
9908 : /** Removes a field domain from the dataset.
9909 : *
9910 : * Only a few drivers will support this operation.
9911 : *
9912 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9913 : * support this operation. A dataset having at least some support for this
9914 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9915 : *
9916 : * Anticipated failures will not be emitted through the CPLError()
9917 : * infrastructure, but will be reported in the ppszFailureReason output
9918 : * parameter.
9919 : *
9920 : * @param hDS Dataset handle.
9921 : * @param pszName The domain name.
9922 : * @param ppszFailureReason Output parameter. Will contain an error message if
9923 : * an error occurs (*ppszFailureReason to be freed
9924 : * with CPLFree). May be NULL.
9925 : * @return true in case of success.
9926 : * @since GDAL 3.3
9927 : */
9928 8 : bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,
9929 : char **ppszFailureReason)
9930 : {
9931 8 : VALIDATE_POINTER1(hDS, __func__, false);
9932 8 : VALIDATE_POINTER1(pszName, __func__, false);
9933 8 : std::string failureReason;
9934 : const bool bRet =
9935 8 : GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);
9936 8 : if (ppszFailureReason)
9937 : {
9938 0 : *ppszFailureReason =
9939 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9940 : }
9941 8 : return bRet;
9942 : }
9943 :
9944 : /************************************************************************/
9945 : /* UpdateFieldDomain() */
9946 : /************************************************************************/
9947 :
9948 : /** Updates an existing field domain by replacing its definition.
9949 : *
9950 : * The existing field domain with matching name will be replaced.
9951 : *
9952 : * Only a few drivers will support this operation, and some of them might only
9953 : * support it only for some types of field domains.
9954 : * At the time of writing (GDAL 3.5), only the Memory driver
9955 : * supports this operation. A dataset having at least some support for this
9956 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9957 : *
9958 : * Anticipated failures will not be emitted through the CPLError()
9959 : * infrastructure, but will be reported in the failureReason output parameter.
9960 : *
9961 : * @param domain The domain definition.
9962 : * @param failureReason Output parameter. Will contain an error message if
9963 : * an error occurs.
9964 : * @return true in case of success.
9965 : * @since GDAL 3.5
9966 : */
9967 0 : bool GDALDataset::UpdateFieldDomain(
9968 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9969 : std::string &failureReason)
9970 : {
9971 0 : failureReason = "UpdateFieldDomain not supported by this driver";
9972 0 : return false;
9973 : }
9974 :
9975 : /************************************************************************/
9976 : /* GDALDatasetUpdateFieldDomain() */
9977 : /************************************************************************/
9978 :
9979 : /** Updates an existing field domain by replacing its definition.
9980 : *
9981 : * The existing field domain with matching name will be replaced.
9982 : *
9983 : * Only a few drivers will support this operation, and some of them might only
9984 : * support it only for some types of field domains.
9985 : * At the time of writing (GDAL 3.5), only the Memory driver
9986 : * supports this operation. A dataset having at least some support for this
9987 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9988 : *
9989 : * Anticipated failures will not be emitted through the CPLError()
9990 : * infrastructure, but will be reported in the failureReason output parameter.
9991 : *
9992 : * @param hDS Dataset handle.
9993 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9994 : * the passed object is copied.
9995 : * @param ppszFailureReason Output parameter. Will contain an error message if
9996 : * an error occurs (*ppszFailureReason to be freed
9997 : * with CPLFree). May be NULL.
9998 : * @return true in case of success.
9999 : * @since GDAL 3.5
10000 : */
10001 4 : bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,
10002 : OGRFieldDomainH hFieldDomain,
10003 : char **ppszFailureReason)
10004 : {
10005 4 : VALIDATE_POINTER1(hDS, __func__, false);
10006 4 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
10007 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
10008 8 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
10009 4 : if (poDomain == nullptr)
10010 0 : return false;
10011 4 : std::string failureReason;
10012 8 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(
10013 4 : std::move(poDomain), failureReason);
10014 4 : if (ppszFailureReason)
10015 : {
10016 0 : *ppszFailureReason =
10017 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
10018 : }
10019 4 : return bRet;
10020 : }
10021 :
10022 : /************************************************************************/
10023 : /* GetRelationshipNames() */
10024 : /************************************************************************/
10025 :
10026 : /** Returns a list of the names of all relationships stored in the dataset.
10027 : *
10028 : * @param papszOptions Driver specific options determining how relationships
10029 : * should be retrieved. Pass nullptr for default behavior.
10030 : *
10031 : * @return list of relationship names
10032 : * @since GDAL 3.6
10033 : */
10034 : std::vector<std::string>
10035 168 : GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const
10036 : {
10037 168 : return {};
10038 : }
10039 :
10040 : /************************************************************************/
10041 : /* GDALDatasetGetRelationshipNames() */
10042 : /************************************************************************/
10043 :
10044 : /** Returns a list of the names of all relationships stored in the dataset.
10045 : *
10046 : * This is the same as the C++ method GDALDataset::GetRelationshipNames().
10047 : *
10048 : * @param hDS Dataset handle.
10049 : * @param papszOptions Driver specific options determining how relationships
10050 : * should be retrieved. Pass nullptr for default behavior.
10051 : *
10052 : * @return list of relationship names, to be freed with CSLDestroy()
10053 : * @since GDAL 3.6
10054 : */
10055 46 : char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,
10056 : CSLConstList papszOptions)
10057 : {
10058 46 : VALIDATE_POINTER1(hDS, __func__, nullptr);
10059 : auto names =
10060 92 : GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);
10061 92 : CPLStringList res;
10062 146 : for (const auto &name : names)
10063 : {
10064 100 : res.AddString(name.c_str());
10065 : }
10066 46 : return res.StealList();
10067 : }
10068 :
10069 : /************************************************************************/
10070 : /* GetRelationship() */
10071 : /************************************************************************/
10072 :
10073 : /** Get a relationship from its name.
10074 : *
10075 : * @return the relationship, or nullptr if not found.
10076 : * @since GDAL 3.6
10077 : */
10078 : const GDALRelationship *
10079 0 : GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const
10080 : {
10081 0 : return nullptr;
10082 : }
10083 :
10084 : /************************************************************************/
10085 : /* GDALDatasetGetRelationship() */
10086 : /************************************************************************/
10087 :
10088 : /** Get a relationship from its name.
10089 : *
10090 : * This is the same as the C++ method GDALDataset::GetRelationship().
10091 : *
10092 : * @param hDS Dataset handle.
10093 : * @param pszName Name of relationship.
10094 : * @return the relationship (ownership remains to the dataset), or nullptr if
10095 : * not found.
10096 : * @since GDAL 3.6
10097 : */
10098 52 : GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,
10099 : const char *pszName)
10100 : {
10101 52 : VALIDATE_POINTER1(hDS, __func__, nullptr);
10102 52 : VALIDATE_POINTER1(pszName, __func__, nullptr);
10103 52 : return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(
10104 52 : GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));
10105 : }
10106 :
10107 : /************************************************************************/
10108 : /* AddRelationship() */
10109 : /************************************************************************/
10110 :
10111 : /** Add a relationship to the dataset.
10112 : *
10113 : * Only a few drivers will support this operation, and some of them might only
10114 : * support it only for some types of relationships.
10115 : *
10116 : * A dataset having at least some support for this
10117 : * operation should report the GDsCAddRelationship dataset capability.
10118 : *
10119 : * Anticipated failures will not be emitted through the CPLError()
10120 : * infrastructure, but will be reported in the failureReason output parameter.
10121 : *
10122 : * When adding a many-to-many relationship
10123 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
10124 : * mapping table name (see GDALRelationship::GetMappingTableName) to instruct
10125 : * the driver to create an appropriately named and structured mapping table.
10126 : * Some dataset formats require particular naming conventions and field
10127 : * structures for the mapping table, and delegating the construction of the
10128 : * mapping table to the driver will avoid these pitfalls.
10129 : *
10130 : * @param relationship The relationship definition.
10131 : * @param failureReason Output parameter. Will contain an error message if
10132 : * an error occurs.
10133 : * @return true in case of success.
10134 : * @since GDAL 3.6
10135 : */
10136 0 : bool GDALDataset::AddRelationship(
10137 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
10138 : std::string &failureReason)
10139 : {
10140 0 : failureReason = "AddRelationship not supported by this driver";
10141 0 : return false;
10142 : }
10143 :
10144 : /************************************************************************/
10145 : /* GDALDatasetAddRelationship() */
10146 : /************************************************************************/
10147 :
10148 : /** Add a relationship to the dataset.
10149 : *
10150 : * Only a few drivers will support this operation, and some of them might only
10151 : * support it only for some types of relationships.
10152 : *
10153 : * A dataset having at least some support for this
10154 : * operation should report the GDsCAddRelationship dataset capability.
10155 : *
10156 : * Anticipated failures will not be emitted through the CPLError()
10157 : * infrastructure, but will be reported in the failureReason output parameter.
10158 : *
10159 : * When adding a many-to-many relationship
10160 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
10161 : * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the
10162 : * driver to create an appropriately named and structured mapping table. Some
10163 : * dataset formats require particular naming conventions and field structures
10164 : * for the mapping table, and delegating the construction of the mapping table
10165 : * to the driver will avoid these pitfalls.
10166 : *
10167 : * @param hDS Dataset handle.
10168 : * @param hRelationship The relationship definition. Contrary to the C++
10169 : * version, the passed object is copied.
10170 : * @param ppszFailureReason Output parameter. Will contain an error message if
10171 : * an error occurs (*ppszFailureReason to be freed
10172 : * with CPLFree). May be NULL.
10173 : * @return true in case of success.
10174 : * @since GDAL 3.6
10175 : */
10176 42 : bool GDALDatasetAddRelationship(GDALDatasetH hDS,
10177 : GDALRelationshipH hRelationship,
10178 : char **ppszFailureReason)
10179 : {
10180 42 : VALIDATE_POINTER1(hDS, __func__, false);
10181 42 : VALIDATE_POINTER1(hRelationship, __func__, false);
10182 : std::unique_ptr<GDALRelationship> poRelationship(
10183 84 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
10184 42 : std::string failureReason;
10185 84 : const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(
10186 42 : std::move(poRelationship), failureReason);
10187 42 : if (ppszFailureReason)
10188 : {
10189 0 : *ppszFailureReason =
10190 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
10191 : }
10192 42 : return bRet;
10193 : }
10194 :
10195 : /************************************************************************/
10196 : /* DeleteRelationship() */
10197 : /************************************************************************/
10198 :
10199 : /** Removes a relationship from the dataset.
10200 : *
10201 : * Only a few drivers will support this operation.
10202 : *
10203 : * A dataset having at least some support for this
10204 : * operation should report the GDsCDeleteRelationship dataset capability.
10205 : *
10206 : * Anticipated failures will not be emitted through the CPLError()
10207 : * infrastructure, but will be reported in the failureReason output parameter.
10208 : *
10209 : * @param name The relationship name.
10210 : * @param failureReason Output parameter. Will contain an error message if
10211 : * an error occurs.
10212 : * @return true in case of success.
10213 : * @since GDAL 3.6
10214 : */
10215 0 : bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,
10216 : std::string &failureReason)
10217 : {
10218 0 : failureReason = "DeleteRelationship not supported by this driver";
10219 0 : return false;
10220 : }
10221 :
10222 : /************************************************************************/
10223 : /* GDALDatasetDeleteRelationship() */
10224 : /************************************************************************/
10225 :
10226 : /** Removes a relationship from the dataset.
10227 : *
10228 : * Only a few drivers will support this operation.
10229 : *
10230 : * A dataset having at least some support for this
10231 : * operation should report the GDsCDeleteRelationship dataset capability.
10232 : *
10233 : * Anticipated failures will not be emitted through the CPLError()
10234 : * infrastructure, but will be reported in the ppszFailureReason output
10235 : * parameter.
10236 : *
10237 : * @param hDS Dataset handle.
10238 : * @param pszName The relationship name.
10239 : * @param ppszFailureReason Output parameter. Will contain an error message if
10240 : * an error occurs (*ppszFailureReason to be freed
10241 : * with CPLFree). May be NULL.
10242 : * @return true in case of success.
10243 : * @since GDAL 3.6
10244 : */
10245 6 : bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,
10246 : char **ppszFailureReason)
10247 : {
10248 6 : VALIDATE_POINTER1(hDS, __func__, false);
10249 6 : VALIDATE_POINTER1(pszName, __func__, false);
10250 6 : std::string failureReason;
10251 12 : const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(
10252 6 : pszName, failureReason);
10253 6 : if (ppszFailureReason)
10254 : {
10255 0 : *ppszFailureReason =
10256 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
10257 : }
10258 6 : return bRet;
10259 : }
10260 :
10261 : /************************************************************************/
10262 : /* UpdateRelationship() */
10263 : /************************************************************************/
10264 :
10265 : /** Updates an existing relationship by replacing its definition.
10266 : *
10267 : * The existing relationship with matching name will be replaced.
10268 : *
10269 : * Only a few drivers will support this operation, and some of them might only
10270 : * support it only for some types of relationships.
10271 : * A dataset having at least some support for this
10272 : * operation should report the GDsCUpdateRelationship dataset capability.
10273 : *
10274 : * Anticipated failures will not be emitted through the CPLError()
10275 : * infrastructure, but will be reported in the failureReason output parameter.
10276 : *
10277 : * @param relationship The relationship definition.
10278 : * @param failureReason Output parameter. Will contain an error message if
10279 : * an error occurs.
10280 : * @return true in case of success.
10281 : * @since GDAL 3.6
10282 : */
10283 0 : bool GDALDataset::UpdateRelationship(
10284 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
10285 : std::string &failureReason)
10286 : {
10287 0 : failureReason = "UpdateRelationship not supported by this driver";
10288 0 : return false;
10289 : }
10290 :
10291 : /************************************************************************/
10292 : /* GDALDatasetUpdateRelationship() */
10293 : /************************************************************************/
10294 :
10295 : /** Updates an existing relationship by replacing its definition.
10296 : *
10297 : * The existing relationship with matching name will be replaced.
10298 : *
10299 : * Only a few drivers will support this operation, and some of them might only
10300 : * support it only for some types of relationships.
10301 : * A dataset having at least some support for this
10302 : * operation should report the GDsCUpdateRelationship dataset capability.
10303 : *
10304 : * Anticipated failures will not be emitted through the CPLError()
10305 : * infrastructure, but will be reported in the failureReason output parameter.
10306 : *
10307 : * @param hDS Dataset handle.
10308 : * @param hRelationship The relationship definition. Contrary to the C++
10309 : * version, the passed object is copied.
10310 : * @param ppszFailureReason Output parameter. Will contain an error message if
10311 : * an error occurs (*ppszFailureReason to be freed
10312 : * with CPLFree). May be NULL.
10313 : * @return true in case of success.
10314 : * @since GDAL 3.5
10315 : */
10316 9 : bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,
10317 : GDALRelationshipH hRelationship,
10318 : char **ppszFailureReason)
10319 : {
10320 9 : VALIDATE_POINTER1(hDS, __func__, false);
10321 9 : VALIDATE_POINTER1(hRelationship, __func__, false);
10322 : std::unique_ptr<GDALRelationship> poRelationship(
10323 18 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
10324 9 : std::string failureReason;
10325 18 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(
10326 9 : std::move(poRelationship), failureReason);
10327 9 : if (ppszFailureReason)
10328 : {
10329 0 : *ppszFailureReason =
10330 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
10331 : }
10332 9 : return bRet;
10333 : }
10334 :
10335 : /************************************************************************/
10336 : /* GDALDatasetSetQueryLoggerFunc() */
10337 : /************************************************************************/
10338 :
10339 : /**
10340 : * Sets the SQL query logger callback.
10341 : *
10342 : * When supported by the driver, the callback will be called with
10343 : * the executed SQL text, the error message, the execution time in milliseconds,
10344 : * the number of records fetched/affected and the client status data.
10345 : *
10346 : * A value of -1 in the execution time or in the number of records indicates
10347 : * that the values are unknown.
10348 : *
10349 : * @param hDS Dataset handle.
10350 : * @param pfnQueryLoggerFunc Callback function
10351 : * @param poQueryLoggerArg Opaque client status data
10352 : * @return true in case of success.
10353 : * @since GDAL 3.7
10354 : */
10355 1 : bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,
10356 : GDALQueryLoggerFunc pfnQueryLoggerFunc,
10357 : void *poQueryLoggerArg)
10358 : {
10359 1 : VALIDATE_POINTER1(hDS, __func__, false);
10360 2 : return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,
10361 1 : poQueryLoggerArg);
10362 : }
10363 :
10364 : //! @cond Doxygen_Suppress
10365 :
10366 : /************************************************************************/
10367 : /* SetEnableOverviews() */
10368 : /************************************************************************/
10369 :
10370 7497 : void GDALDataset::SetEnableOverviews(bool bEnable)
10371 : {
10372 7497 : if (m_poPrivate)
10373 : {
10374 7497 : m_poPrivate->m_bOverviewsEnabled = bEnable;
10375 : }
10376 7497 : }
10377 :
10378 : /************************************************************************/
10379 : /* AreOverviewsEnabled() */
10380 : /************************************************************************/
10381 :
10382 2006110 : bool GDALDataset::AreOverviewsEnabled() const
10383 : {
10384 2006110 : return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
10385 : }
10386 :
10387 : /************************************************************************/
10388 : /* IsAllBands() */
10389 : /************************************************************************/
10390 :
10391 3489 : bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const
10392 : {
10393 3489 : if (nBands != nBandCount)
10394 1 : return false;
10395 3488 : if (panBandList)
10396 : {
10397 12668 : for (int i = 0; i < nBandCount; ++i)
10398 : {
10399 9271 : if (panBandList[i] != i + 1)
10400 27 : return false;
10401 : }
10402 : }
10403 3461 : return true;
10404 : }
10405 :
10406 : //! @endcond
10407 :
10408 : /************************************************************************/
10409 : /* GetCompressionFormats() */
10410 : /************************************************************************/
10411 :
10412 : /** Return the compression formats that can be natively obtained for the
10413 : * window of interest and requested bands.
10414 : *
10415 : * For example, a tiled dataset may be able to return data in a compressed
10416 : * format if the window of interest matches exactly a tile. For some formats,
10417 : * drivers may also be able to merge several tiles together (not currently
10418 : * implemented though).
10419 : *
10420 : * Each format string is a pseudo MIME type, whose first part can be passed
10421 : * as the pszFormat argument of ReadCompressedData(), with additional
10422 : * parameters specified as key=value with a semi-colon separator.
10423 : *
10424 : * The amount and types of optional parameters passed after the MIME type is
10425 : * format dependent, and driver dependent (some drivers might not be able to
10426 : * return those extra information without doing a rather costly processing).
10427 : *
10428 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
10429 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
10430 : * consequently "JPEG" can be passed as the pszFormat argument of
10431 : * ReadCompressedData(). For JPEG, implementations can use the
10432 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
10433 : * above from a JPEG codestream.
10434 : *
10435 : * Several values might be returned. For example,
10436 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
10437 : * if the JPEGXL codestream includes a JPEG reconstruction box.
10438 : *
10439 : * In the general case this method will return an empty list.
10440 : *
10441 : * This is the same as C function GDALDatasetGetCompressionFormats().
10442 : *
10443 : * @param nXOff The pixel offset to the top left corner of the region
10444 : * of the band to be accessed. This would be zero to start from the left side.
10445 : *
10446 : * @param nYOff The line offset to the top left corner of the region
10447 : * of the band to be accessed. This would be zero to start from the top.
10448 : *
10449 : * @param nXSize The width of the region of the band to be accessed in pixels.
10450 : *
10451 : * @param nYSize The height of the region of the band to be accessed in lines.
10452 : *
10453 : * @param nBandCount the number of bands being requested.
10454 : *
10455 : * @param panBandList the list of nBandCount band numbers.
10456 : * Note band numbers are 1 based. This may be NULL to select the first
10457 : * nBandCount bands.
10458 : *
10459 : * @return a list of compatible formats (which may be empty)
10460 : *
10461 : * For example, to check if native compression format(s) are available on the
10462 : * whole image:
10463 : * \code{.cpp}
10464 : * const CPLStringList aosFormats =
10465 : * poDataset->GetCompressionFormats(0, 0,
10466 : * poDataset->GetRasterXSize(),
10467 : * poDataset->GetRasterYSize(),
10468 : * poDataset->GetRasterCount(),
10469 : * nullptr);
10470 : * for( const char* pszFormat: aosFormats )
10471 : * {
10472 : * // Remove optional parameters and just print out the MIME type.
10473 : * const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));
10474 : * printf("Found format %s\n, aosTokens[0]);
10475 : * }
10476 : * \endcode
10477 : *
10478 : * @since GDAL 3.7
10479 : */
10480 : CPLStringList
10481 0 : GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
10482 : CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10483 : CPL_UNUSED int nBandCount,
10484 : CPL_UNUSED const int *panBandList)
10485 : {
10486 0 : return CPLStringList();
10487 : }
10488 :
10489 : /************************************************************************/
10490 : /* GDALDatasetGetCompressionFormats() */
10491 : /************************************************************************/
10492 :
10493 : /** Return the compression formats that can be natively obtained for the
10494 : * window of interest and requested bands.
10495 : *
10496 : * For example, a tiled dataset may be able to return data in a compressed
10497 : * format if the window of interest matches exactly a tile. For some formats,
10498 : * drivers may also be able to merge several tiles together (not currently
10499 : * implemented though).
10500 : *
10501 : * Each format string is a pseudo MIME type, whose first part can be passed
10502 : * as the pszFormat argument of ReadCompressedData(), with additional
10503 : * parameters specified as key=value with a semi-colon separator.
10504 : *
10505 : * The amount and types of optional parameters passed after the MIME type is
10506 : * format dependent, and driver dependent (some drivers might not be able to
10507 : * return those extra information without doing a rather costly processing).
10508 : *
10509 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
10510 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
10511 : * consequently "JPEG" can be passed as the pszFormat argument of
10512 : * ReadCompressedData(). For JPEG, implementations can use the
10513 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
10514 : * above from a JPEG codestream.
10515 : *
10516 : * Several values might be returned. For example,
10517 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
10518 : * if the JPEGXL codestream includes a JPEG reconstruction box.
10519 : *
10520 : * In the general case this method will return an empty list.
10521 : *
10522 : * This is the same as C++ method GDALDataset::GetCompressionFormats().
10523 : *
10524 : * @param hDS Dataset handle.
10525 : *
10526 : * @param nXOff The pixel offset to the top left corner of the region
10527 : * of the band to be accessed. This would be zero to start from the left side.
10528 : *
10529 : * @param nYOff The line offset to the top left corner of the region
10530 : * of the band to be accessed. This would be zero to start from the top.
10531 : *
10532 : * @param nXSize The width of the region of the band to be accessed in pixels.
10533 : *
10534 : * @param nYSize The height of the region of the band to be accessed in lines.
10535 : *
10536 : * @param nBandCount the number of bands being requested.
10537 : *
10538 : * @param panBandList the list of nBandCount band numbers.
10539 : * Note band numbers are 1 based. This may be NULL to select the first
10540 : * nBandCount bands.
10541 : *
10542 : * @return a list of compatible formats (which may be empty) that should be
10543 : * freed with CSLDestroy(), or nullptr.
10544 : *
10545 : * @since GDAL 3.7
10546 : */
10547 9 : char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,
10548 : int nXSize, int nYSize, int nBandCount,
10549 : const int *panBandList)
10550 : {
10551 9 : VALIDATE_POINTER1(hDS, __func__, nullptr);
10552 9 : return GDALDataset::FromHandle(hDS)
10553 9 : ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,
10554 9 : panBandList)
10555 9 : .StealList();
10556 : }
10557 :
10558 : /************************************************************************/
10559 : /* ReadCompressedData() */
10560 : /************************************************************************/
10561 :
10562 : /** Return the compressed content that can be natively obtained for the
10563 : * window of interest and requested bands.
10564 : *
10565 : * For example, a tiled dataset may be able to return data in compressed format
10566 : * if the window of interest matches exactly a tile. For some formats, drivers
10567 : * may also be example to merge several tiles together (not currently
10568 : * implemented though).
10569 : *
10570 : * The implementation should make sure that the content returned forms a valid
10571 : * standalone file. For example, for the GeoTIFF implementation of this method,
10572 : * when extracting a JPEG tile, the method will automatically add the content
10573 : * of the JPEG Huffman and/or quantization tables that might be stored in the
10574 : * TIFF JpegTables tag, and not in tile data itself.
10575 : *
10576 : * In the general case this method will return CE_Failure.
10577 : *
10578 : * This is the same as C function GDALDatasetReadCompressedData().
10579 : *
10580 : * @param pszFormat Requested compression format (e.g. "JPEG",
10581 : * "WEBP", "JXL"). This is the MIME type of one of the values
10582 : * returned by GetCompressionFormats(). The format string is designed to
10583 : * potentially include at a later point key=value optional parameters separated
10584 : * by a semi-colon character. At time of writing, none are implemented.
10585 : * ReadCompressedData() implementations should verify optional parameters and
10586 : * return CE_Failure if they cannot support one of them.
10587 : *
10588 : * @param nXOff The pixel offset to the top left corner of the region
10589 : * of the band to be accessed. This would be zero to start from the left side.
10590 : *
10591 : * @param nYOff The line offset to the top left corner of the region
10592 : * of the band to be accessed. This would be zero to start from the top.
10593 : *
10594 : * @param nXSize The width of the region of the band to be accessed in pixels.
10595 : *
10596 : * @param nYSize The height of the region of the band to be accessed in lines.
10597 : *
10598 : * @param nBandCount the number of bands being requested.
10599 : *
10600 : * @param panBandList the list of nBandCount band numbers.
10601 : * Note band numbers are 1 based. This may be NULL to select the first
10602 : * nBandCount bands.
10603 : *
10604 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10605 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10606 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10607 : * buffer will be filled with the compressed data, provided that pnBufferSize
10608 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10609 : * of *ppBuffer, is sufficiently large to hold the data.
10610 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10611 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10612 : * free it with VSIFree().
10613 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10614 : * but *pnBufferSize will be updated with an upper bound of the size that would
10615 : * be necessary to hold it (if pnBufferSize != nullptr).
10616 : *
10617 : * @param pnBufferSize Output buffer size, or nullptr.
10618 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10619 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10620 : * method is successful, *pnBufferSize will be updated with the actual size
10621 : * used.
10622 : *
10623 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10624 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10625 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10626 : * *ppszDetailedFormat might contain strings like
10627 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10628 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10629 : * The string will contain at least as much information as what
10630 : * GetCompressionFormats() returns, and potentially more when
10631 : * ppBuffer != nullptr.
10632 : *
10633 : * @return CE_None in case of success, CE_Failure otherwise.
10634 : *
10635 : * For example, to request JPEG content on the whole image and let GDAL deal
10636 : * with the buffer allocation.
10637 : * \code{.cpp}
10638 : * void* pBuffer = nullptr;
10639 : * size_t nBufferSize = 0;
10640 : * CPLErr eErr =
10641 : * poDataset->ReadCompressedData("JPEG",
10642 : * 0, 0,
10643 : * poDataset->GetRasterXSize(),
10644 : * poDataset->GetRasterYSize(),
10645 : * poDataset->GetRasterCount(),
10646 : * nullptr, // panBandList
10647 : * &pBuffer,
10648 : * &nBufferSize,
10649 : * nullptr // ppszDetailedFormat
10650 : * );
10651 : * if (eErr == CE_None)
10652 : * {
10653 : * CPLAssert(pBuffer != nullptr);
10654 : * CPLAssert(nBufferSize > 0);
10655 : * VSILFILE* fp = VSIFOpenL("my.jpeg", "wb");
10656 : * if (fp)
10657 : * {
10658 : * VSIFWriteL(pBuffer, nBufferSize, 1, fp);
10659 : * VSIFCloseL(fp);
10660 : * }
10661 : * VSIFree(pBuffer);
10662 : * }
10663 : * \endcode
10664 : *
10665 : * Or to manage the buffer allocation on your side:
10666 : * \code{.cpp}
10667 : * size_t nUpperBoundBufferSize = 0;
10668 : * CPLErr eErr =
10669 : * poDataset->ReadCompressedData("JPEG",
10670 : * 0, 0,
10671 : * poDataset->GetRasterXSize(),
10672 : * poDataset->GetRasterYSize(),
10673 : * poDataset->GetRasterCount(),
10674 : * nullptr, // panBandList
10675 : * nullptr, // ppBuffer,
10676 : * &nUpperBoundBufferSize,
10677 : * nullptr // ppszDetailedFormat
10678 : * );
10679 : * if (eErr == CE_None)
10680 : * {
10681 : * std::vector<uint8_t> myBuffer;
10682 : * myBuffer.resize(nUpperBoundBufferSize);
10683 : * void* pBuffer = myBuffer.data();
10684 : * size_t nActualSize = nUpperBoundBufferSize;
10685 : * char* pszDetailedFormat = nullptr;
10686 : * // We also request detailed format, but we could have passed it to
10687 : * // nullptr as well.
10688 : * eErr =
10689 : * poDataset->ReadCompressedData("JPEG",
10690 : * 0, 0,
10691 : * poDataset->GetRasterXSize(),
10692 : * poDataset->GetRasterYSize(),
10693 : * poDataset->GetRasterCount(),
10694 : * nullptr, // panBandList
10695 : * &pBuffer,
10696 : * &nActualSize,
10697 : * &pszDetailedFormat);
10698 : * if (eErr == CE_None)
10699 : * {
10700 : * CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified
10701 : * CPLAssert(nActualSize <= nUpperBoundBufferSize);
10702 : * myBuffer.resize(nActualSize);
10703 : * // do something useful
10704 : * VSIFree(pszDetailedFormat);
10705 : * }
10706 : * }
10707 : * \endcode
10708 : *
10709 : * @since GDAL 3.7
10710 : */
10711 441 : CPLErr GDALDataset::ReadCompressedData(
10712 : CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,
10713 : CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10714 : CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,
10715 : CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,
10716 : CPL_UNUSED char **ppszDetailedFormat)
10717 : {
10718 441 : return CE_Failure;
10719 : }
10720 :
10721 : /************************************************************************/
10722 : /* GDALDatasetReadCompressedData() */
10723 : /************************************************************************/
10724 :
10725 : /** Return the compressed content that can be natively obtained for the
10726 : * window of interest and requested bands.
10727 : *
10728 : * For example, a tiled dataset may be able to return data in compressed format
10729 : * if the window of interest matches exactly a tile. For some formats, drivers
10730 : * may also be example to merge several tiles together (not currently
10731 : * implemented though).
10732 : *
10733 : * The implementation should make sure that the content returned forms a valid
10734 : * standalone file. For example, for the GeoTIFF implementation of this method,
10735 : * when extracting a JPEG tile, the method will automatically adds the content
10736 : * of the JPEG Huffman and/or quantization tables that might be stored in the
10737 : * TIFF JpegTables tag, and not in tile data itself.
10738 : *
10739 : * In the general case this method will return CE_Failure.
10740 : *
10741 : * This is the same as C++ method GDALDataset:ReadCompressedData().
10742 : *
10743 : * @param hDS Dataset handle.
10744 : *
10745 : * @param pszFormat Requested compression format (e.g. "JPEG",
10746 : * "WEBP", "JXL"). This is the MIME type of one of the values
10747 : * returned by GetCompressionFormats(). The format string is designed to
10748 : * potentially include at a later point key=value optional parameters separated
10749 : * by a semi-colon character. At time of writing, none are implemented.
10750 : * ReadCompressedData() implementations should verify optional parameters and
10751 : * return CE_Failure if they cannot support one of them.
10752 : *
10753 : * @param nXOff The pixel offset to the top left corner of the region
10754 : * of the band to be accessed. This would be zero to start from the left side.
10755 : *
10756 : * @param nYOff The line offset to the top left corner of the region
10757 : * of the band to be accessed. This would be zero to start from the top.
10758 : *
10759 : * @param nXSize The width of the region of the band to be accessed in pixels.
10760 : *
10761 : * @param nYSize The height of the region of the band to be accessed in lines.
10762 : *
10763 : * @param nBandCount the number of bands being requested.
10764 : *
10765 : * @param panBandList the list of nBandCount band numbers.
10766 : * Note band numbers are 1 based. This may be NULL to select the first
10767 : * nBandCount bands.
10768 : *
10769 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10770 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10771 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10772 : * buffer will be filled with the compressed data, provided that pnBufferSize
10773 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10774 : * of *ppBuffer, is sufficiently large to hold the data.
10775 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10776 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10777 : * free it with VSIFree().
10778 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10779 : * but *pnBufferSize will be updated with an upper bound of the size that would
10780 : * be necessary to hold it (if pnBufferSize != nullptr).
10781 : *
10782 : * @param pnBufferSize Output buffer size, or nullptr.
10783 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10784 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10785 : * method is successful, *pnBufferSize will be updated with the actual size
10786 : * used.
10787 : *
10788 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10789 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10790 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10791 : * *ppszDetailedFormat might contain strings like
10792 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10793 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10794 : * The string will contain at least as much information as what
10795 : * GetCompressionFormats() returns, and potentially more when
10796 : * ppBuffer != nullptr.
10797 : *
10798 : * @return CE_None in case of success, CE_Failure otherwise.
10799 : *
10800 : * @since GDAL 3.7
10801 : */
10802 28 : CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,
10803 : int nXOff, int nYOff, int nXSize,
10804 : int nYSize, int nBandCount,
10805 : const int *panBandList, void **ppBuffer,
10806 : size_t *pnBufferSize,
10807 : char **ppszDetailedFormat)
10808 : {
10809 28 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10810 56 : return GDALDataset::FromHandle(hDS)->ReadCompressedData(
10811 : pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,
10812 28 : ppBuffer, pnBufferSize, ppszDetailedFormat);
10813 : }
10814 :
10815 : /************************************************************************/
10816 : /* CanBeCloned() */
10817 : /************************************************************************/
10818 :
10819 : //! @cond Doxygen_Suppress
10820 :
10821 : /** This method is called by GDALThreadSafeDataset::Create() to determine if
10822 : * it is possible to create a thread-safe wrapper for a dataset, which involves
10823 : * the ability to Clone() it.
10824 : *
10825 : * Implementations of this method must be thread-safe.
10826 : *
10827 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10828 : * expressing the intended use for thread-safety.
10829 : * Currently, the only valid scope is in the base
10830 : * implementation is GDAL_OF_RASTER.
10831 : * @param bCanShareState Determines if cloned datasets are allowed to share
10832 : * state with the dataset they have been cloned from.
10833 : * If set to true, the dataset from which they have been
10834 : * cloned from must remain opened during the lifetime of
10835 : * its clones.
10836 : * @return true if the Clone() method is expected to succeed with the same values
10837 : * of nScopeFlags and bCanShareState.
10838 : */
10839 149 : bool GDALDataset::CanBeCloned(int nScopeFlags,
10840 : [[maybe_unused]] bool bCanShareState) const
10841 : {
10842 149 : return m_bCanBeReopened && nScopeFlags == GDAL_OF_RASTER;
10843 : }
10844 :
10845 : //! @endcond
10846 :
10847 : /************************************************************************/
10848 : /* Clone() */
10849 : /************************************************************************/
10850 :
10851 : //! @cond Doxygen_Suppress
10852 :
10853 : /** This method "clones" the current dataset, that is it returns a new instance
10854 : * that is opened on the same underlying "file".
10855 : *
10856 : * The base implementation uses GDALDataset::Open() to re-open the dataset.
10857 : * The MEM driver has a specialized implementation that returns a new instance,
10858 : * but which shares the same memory buffer as this.
10859 : *
10860 : * Implementations of this method must be thread-safe.
10861 : *
10862 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10863 : * expressing the intended use for thread-safety.
10864 : * Currently, the only valid scope is in the base
10865 : * implementation is GDAL_OF_RASTER.
10866 : * @param bCanShareState Determines if cloned datasets are allowed to share
10867 : * state with the dataset they have been cloned from.
10868 : * If set to true, the dataset from which they have been
10869 : * cloned from must remain opened during the lifetime of
10870 : * its clones.
10871 : * @return a new instance, or nullptr in case of error.
10872 : */
10873 : std::unique_ptr<GDALDataset>
10874 2051 : GDALDataset::Clone(int nScopeFlags, [[maybe_unused]] bool bCanShareState) const
10875 : {
10876 4102 : CPLStringList aosAllowedDrivers;
10877 2051 : if (poDriver)
10878 2051 : aosAllowedDrivers.AddString(poDriver->GetDescription());
10879 : return std::unique_ptr<GDALDataset>(GDALDataset::Open(
10880 2051 : GetDescription(),
10881 2051 : nScopeFlags | GDAL_OF_INTERNAL | GDAL_OF_VERBOSE_ERROR,
10882 4102 : aosAllowedDrivers.List(), papszOpenOptions));
10883 : }
10884 :
10885 : //! @endcond
10886 :
10887 : /************************************************************************/
10888 : /* GeolocationToPixelLine() */
10889 : /************************************************************************/
10890 :
10891 : /** Transform georeferenced coordinates to pixel/line coordinates.
10892 : *
10893 : * When poSRS is null, those georeferenced coordinates (dfGeolocX, dfGeolocY)
10894 : * must be in the "natural" SRS of the dataset, that is the one returned by
10895 : * GetSpatialRef() if there is a geotransform, GetGCPSpatialRef() if there are
10896 : * GCPs, WGS 84 if there are RPC coefficients, or the SRS of the geolocation
10897 : * array (generally WGS 84) if there is a geolocation array.
10898 : * If that natural SRS is a geographic one, dfGeolocX must be a longitude, and
10899 : * dfGeolocY a latitude. If that natural SRS is a projected one, dfGeolocX must
10900 : * be a easting, and dfGeolocY a northing.
10901 : *
10902 : * When poSRS is set to a non-null value, (dfGeolocX, dfGeolocY) must be
10903 : * expressed in that CRS, and that tuple must be conformant with the
10904 : * data-axis-to-crs-axis setting of poSRS, that is the one returned by
10905 : * the OGRSpatialReference::GetDataAxisToSRSAxisMapping(). If you want to be sure
10906 : * of the axis order, then make sure to call poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER)
10907 : * before calling this method, and in that case, dfGeolocX must be a longitude
10908 : * or an easting value, and dfGeolocX a latitude or a northing value.
10909 : *
10910 : * This method uses GDALCreateGenImgProjTransformer2() underneath.
10911 : *
10912 : * @param dfGeolocX X coordinate of the position (longitude or easting if poSRS
10913 : * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10914 : * where interpolation should be done.
10915 : * @param dfGeolocY Y coordinate of the position (latitude or northing if poSRS
10916 : * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10917 : * where interpolation should be done.
10918 : * @param poSRS If set, override the natural CRS in which dfGeolocX, dfGeolocY are expressed
10919 : * @param[out] pdfPixel Pointer to the variable where to the store the pixel/column coordinate.
10920 : * @param[out] pdfLine Pointer to the variable where to the store the line coordinate.
10921 : * @param papszTransformerOptions Options accepted by GDALCreateGenImgProjTransformer2(), or nullptr.
10922 : *
10923 : * @return CE_None on success, or an error code on failure.
10924 : * @since GDAL 3.11
10925 : */
10926 :
10927 : CPLErr
10928 15 : GDALDataset::GeolocationToPixelLine(double dfGeolocX, double dfGeolocY,
10929 : const OGRSpatialReference *poSRS,
10930 : double *pdfPixel, double *pdfLine,
10931 : CSLConstList papszTransformerOptions) const
10932 : {
10933 30 : CPLStringList aosTO(papszTransformerOptions);
10934 :
10935 15 : if (poSRS)
10936 : {
10937 4 : const char *const apszOptions[] = {"FORMAT=WKT2", nullptr};
10938 8 : const std::string osWKT = poSRS->exportToWkt(apszOptions);
10939 4 : aosTO.SetNameValue("DST_SRS", osWKT.c_str());
10940 4 : const auto eAxisMappingStrategy = poSRS->GetAxisMappingStrategy();
10941 4 : if (eAxisMappingStrategy == OAMS_TRADITIONAL_GIS_ORDER)
10942 : aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10943 1 : "TRADITIONAL_GIS_ORDER");
10944 3 : else if (eAxisMappingStrategy == OAMS_AUTHORITY_COMPLIANT)
10945 : aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10946 1 : "AUTHORITY_COMPLIANT");
10947 : else
10948 : {
10949 2 : const auto &anValues = poSRS->GetDataAxisToSRSAxisMapping();
10950 4 : std::string osVal;
10951 6 : for (int v : anValues)
10952 : {
10953 4 : if (!osVal.empty())
10954 2 : osVal += ',';
10955 4 : osVal += std::to_string(v);
10956 : }
10957 : aosTO.SetNameValue("DST_SRS_DATA_AXIS_TO_SRS_AXIS_MAPPING",
10958 2 : osVal.c_str());
10959 : }
10960 : }
10961 :
10962 15 : auto hTransformer = GDALCreateGenImgProjTransformer2(
10963 : GDALDataset::ToHandle(const_cast<GDALDataset *>(this)), nullptr,
10964 15 : aosTO.List());
10965 15 : if (hTransformer == nullptr)
10966 : {
10967 1 : return CE_Failure;
10968 : }
10969 :
10970 14 : double z = 0;
10971 14 : int bSuccess = 0;
10972 14 : GDALGenImgProjTransform(hTransformer, TRUE, 1, &dfGeolocX, &dfGeolocY, &z,
10973 : &bSuccess);
10974 14 : GDALDestroyTransformer(hTransformer);
10975 14 : if (bSuccess)
10976 : {
10977 14 : if (pdfPixel)
10978 14 : *pdfPixel = dfGeolocX;
10979 14 : if (pdfLine)
10980 14 : *pdfLine = dfGeolocY;
10981 14 : return CE_None;
10982 : }
10983 : else
10984 : {
10985 0 : return CE_Failure;
10986 : }
10987 : }
10988 :
10989 : /************************************************************************/
10990 : /* GDALDatasetGeolocationToPixelLine() */
10991 : /************************************************************************/
10992 :
10993 : /** Transform georeferenced coordinates to pixel/line coordinates.
10994 : *
10995 : * @see GDALDataset::GeolocationToPixelLine()
10996 : * @since GDAL 3.11
10997 : */
10998 :
10999 0 : CPLErr GDALDatasetGeolocationToPixelLine(GDALDatasetH hDS, double dfGeolocX,
11000 : double dfGeolocY,
11001 : OGRSpatialReferenceH hSRS,
11002 : double *pdfPixel, double *pdfLine,
11003 : CSLConstList papszTransformerOptions)
11004 : {
11005 0 : VALIDATE_POINTER1(hDS, "GDALDatasetGeolocationToPixelLine", CE_Failure);
11006 :
11007 0 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
11008 0 : return poDS->GeolocationToPixelLine(
11009 0 : dfGeolocX, dfGeolocY, OGRSpatialReference::FromHandle(hSRS), pdfPixel,
11010 0 : pdfLine, papszTransformerOptions);
11011 : }
11012 :
11013 : /************************************************************************/
11014 : /* GetExtent() */
11015 : /************************************************************************/
11016 :
11017 : /** Return extent of dataset in specified CRS.
11018 : *
11019 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
11020 : *
11021 : * For rasters, the base implementation of this method only succeeds if
11022 : * GetGeoTransform() and GetSpatialRef() succeed.
11023 : * For vectors, the base implementation of this method iterates over layers
11024 : * and call their OGRLayer::GetExtent() method.
11025 : *
11026 : * TestCapability(GDsCFastGetExtent) can be used to test if the execution
11027 : * time of this method is fast.
11028 : *
11029 : * This is the same as C function GDALGetExtent()
11030 : *
11031 : * @param[out] psExtent Pointer to output extent. Must NOT be null.
11032 : * @param poCRS CRS in which to express the extent. If not specified, this will
11033 : * be the raster CRS or the CRS of the first layer for a vector dataset.
11034 : * @return CE_None in case of success, CE_Failure otherwise
11035 : * @since GDAL 3.12
11036 : */
11037 :
11038 23 : CPLErr GDALDataset::GetExtent(OGREnvelope *psExtent,
11039 : const OGRSpatialReference *poCRS) const
11040 : {
11041 23 : const OGRSpatialReference *poThisCRS = GetSpatialRefRasterOnly();
11042 23 : int nLayerCount = 0;
11043 23 : if (!poThisCRS)
11044 : {
11045 11 : nLayerCount = GetLayerCount();
11046 11 : if (nLayerCount >= 1)
11047 : {
11048 3 : if (auto poLayer = GetLayer(0))
11049 3 : poThisCRS = poLayer->GetSpatialRef();
11050 : }
11051 : }
11052 23 : if (!poCRS)
11053 15 : poCRS = poThisCRS;
11054 8 : else if (!poThisCRS)
11055 3 : return CE_Failure;
11056 :
11057 20 : *psExtent = OGREnvelope();
11058 :
11059 20 : GDALGeoTransform gt;
11060 20 : auto poThisDS = const_cast<GDALDataset *>(this);
11061 20 : const bool bHasGT = poThisDS->GetGeoTransform(gt) == CE_None;
11062 20 : if (bHasGT)
11063 : {
11064 0 : std::unique_ptr<OGRCoordinateTransformation> poCT;
11065 15 : if (poCRS)
11066 : {
11067 12 : poCT.reset(OGRCreateCoordinateTransformation(poThisCRS, poCRS));
11068 : }
11069 :
11070 15 : constexpr int DENSIFY_POINT_COUNT = 21;
11071 15 : double dfULX = gt[0];
11072 15 : double dfULY = gt[3];
11073 15 : double dfURX = 0, dfURY = 0;
11074 15 : gt.Apply(nRasterXSize, 0, &dfURX, &dfURY);
11075 15 : double dfLLX = 0, dfLLY = 0;
11076 15 : gt.Apply(0, nRasterYSize, &dfLLX, &dfLLY);
11077 15 : double dfLRX = 0, dfLRY = 0;
11078 15 : gt.Apply(nRasterXSize, nRasterYSize, &dfLRX, &dfLRY);
11079 15 : const double xmin = std::min({dfULX, dfURX, dfLLX, dfLRX});
11080 15 : const double ymin = std::min({dfULY, dfURY, dfLLY, dfLRY});
11081 15 : const double xmax = std::max({dfULX, dfURX, dfLLX, dfLRX});
11082 15 : const double ymax = std::max({dfULY, dfURY, dfLLY, dfLRY});
11083 15 : if (poCT)
11084 : {
11085 12 : OGREnvelope sEnvTmp;
11086 24 : if (!poCT->TransformBounds(xmin, ymin, xmax, ymax, &(sEnvTmp.MinX),
11087 : &(sEnvTmp.MinY), &(sEnvTmp.MaxX),
11088 12 : &(sEnvTmp.MaxY), DENSIFY_POINT_COUNT))
11089 : {
11090 0 : return CE_Failure;
11091 : }
11092 12 : *psExtent = sEnvTmp;
11093 : }
11094 : else
11095 : {
11096 3 : psExtent->MinX = xmin;
11097 3 : psExtent->MinY = ymin;
11098 3 : psExtent->MaxX = xmax;
11099 3 : psExtent->MaxY = ymax;
11100 : }
11101 : }
11102 :
11103 20 : if (nLayerCount > 0)
11104 : {
11105 6 : for (auto &&poLayer : poThisDS->GetLayers())
11106 : {
11107 3 : auto poLayerCRS = poLayer->GetSpatialRef();
11108 3 : if (poLayerCRS)
11109 : {
11110 3 : OGREnvelope sLayerExtent;
11111 3 : if (poLayer->GetExtent(&sLayerExtent) == OGRERR_NONE)
11112 : {
11113 : auto poCT = std::unique_ptr<OGRCoordinateTransformation>(
11114 6 : OGRCreateCoordinateTransformation(poLayerCRS, poCRS));
11115 3 : if (poCT)
11116 : {
11117 3 : constexpr int DENSIFY_POINT_COUNT = 21;
11118 3 : OGREnvelope sEnvTmp;
11119 3 : if (poCT->TransformBounds(
11120 : sLayerExtent.MinX, sLayerExtent.MinY,
11121 : sLayerExtent.MaxX, sLayerExtent.MaxY,
11122 : &(sEnvTmp.MinX), &(sEnvTmp.MinY),
11123 : &(sEnvTmp.MaxX), &(sEnvTmp.MaxY),
11124 3 : DENSIFY_POINT_COUNT))
11125 : {
11126 3 : psExtent->Merge(sEnvTmp);
11127 : }
11128 : }
11129 : }
11130 : }
11131 : }
11132 : }
11133 :
11134 20 : return psExtent->IsInit() ? CE_None : CE_Failure;
11135 : }
11136 :
11137 : /************************************************************************/
11138 : /* GDALGetExtent() */
11139 : /************************************************************************/
11140 :
11141 : /** Return extent of dataset in specified CRS.
11142 : *
11143 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
11144 : *
11145 : * For rasters, the base implementation of this method only succeeds if
11146 : * GetGeoTransform() and GetSpatialRef() succeed.
11147 : * For vectors, the base implementation of this method iterates over layers
11148 : * and call their OGRLayer::GetExtent() method.
11149 : *
11150 : * TestCapability(GDsCFastGetExtent) can be used to test if the execution
11151 : * time of this method is fast.
11152 : *
11153 : * This is the same as C++ method GDALDataset::GetExtent()
11154 : *
11155 : * @param hDS Dataset handle. Must NOT be null.
11156 : * @param[out] psExtent Pointer to output extent. Must NOT be null.
11157 : * @param hCRS CRS in which to express the extent. If not specified, this will
11158 : * be the raster CRS or the CRS of the first layer for a vector dataset.
11159 : * @return extent in poCRS (valid only if IsInit() method returns true)
11160 : * @since GDAL 3.12
11161 : */
11162 :
11163 10 : CPLErr GDALGetExtent(GDALDatasetH hDS, OGREnvelope *psExtent,
11164 : OGRSpatialReferenceH hCRS)
11165 : {
11166 10 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
11167 10 : VALIDATE_POINTER1(psExtent, __func__, CE_Failure);
11168 20 : return GDALDataset::FromHandle(hDS)->GetExtent(
11169 10 : psExtent, OGRSpatialReference::FromHandle(hCRS));
11170 : }
11171 :
11172 : /************************************************************************/
11173 : /* GetExtentWGS84LongLat() */
11174 : /************************************************************************/
11175 :
11176 : /** Return extent of dataset in WGS84 longitude/latitude
11177 : *
11178 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
11179 : *
11180 : * TestCapability(GDsCFastGetExtentWGS84LongLat) can be used to test if the execution
11181 : * time of this method is fast.
11182 : *
11183 : * This is the same as C function GDALGetExtentWGS84LongLat()
11184 : *
11185 : * @return extent (valid only if IsInit() method returns true)
11186 : * @since GDAL 3.12
11187 : */
11188 :
11189 6 : CPLErr GDALDataset::GetExtentWGS84LongLat(OGREnvelope *psExtent) const
11190 : {
11191 12 : OGRSpatialReference oSRS_WGS84;
11192 6 : oSRS_WGS84.SetFromUserInput("WGS84");
11193 6 : oSRS_WGS84.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
11194 12 : return GetExtent(psExtent, &oSRS_WGS84);
11195 : }
11196 :
11197 : /************************************************************************/
11198 : /* GDALGetExtentWGS84LongLat() */
11199 : /************************************************************************/
11200 :
11201 : /** Return extent of dataset in WGS84 longitude/latitude
11202 : *
11203 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
11204 : *
11205 : * TestCapability(GDsCFastGetExtentWGS84LongLat) can be used to test if the execution
11206 : * time of this method is fast.
11207 : *
11208 : * This is the same as C++ method GDALDataset::GetExtentWGS84LongLat()
11209 : *
11210 : * @param hDS Dataset handle. Must NOT be null.
11211 : * @param[out] psExtent Pointer to output extent. Must NOT be null.
11212 : * @return extent (valid only if IsInit() method returns true)
11213 : * @since GDAL 3.12
11214 : */
11215 :
11216 4 : CPLErr GDALGetExtentWGS84LongLat(GDALDatasetH hDS, OGREnvelope *psExtent)
11217 : {
11218 4 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
11219 4 : VALIDATE_POINTER1(psExtent, __func__, CE_Failure);
11220 4 : return GDALDataset::FromHandle(hDS)->GetExtentWGS84LongLat(psExtent);
11221 : }
11222 :
11223 : /************************************************************************/
11224 : /* ReportUpdateNotSupportedByDriver() */
11225 : /************************************************************************/
11226 :
11227 : //! @cond Doxygen_Suppress
11228 :
11229 : /* static */
11230 1 : void GDALDataset::ReportUpdateNotSupportedByDriver(const char *pszDriverName)
11231 : {
11232 1 : CPLError(CE_Failure, CPLE_NotSupported,
11233 : "The %s driver does not support update access to existing "
11234 : "datasets.",
11235 : pszDriverName);
11236 1 : }
11237 :
11238 : //! @endcond
11239 :
11240 : /************************************************************************/
11241 : /* BuildFilename() */
11242 : /************************************************************************/
11243 :
11244 : /** Generates a filename, potentially relative to another one.
11245 : *
11246 : * Given the path to a reference directory, and a path to a file
11247 : * referenced from it, build a path to the file that the current application
11248 : * can use. If the file path is already absolute, rather than relative, or if
11249 : * bRelativeToReferencePath is false, then the filename of interest will be
11250 : * returned unaltered.
11251 : *
11252 : * This is enhanced version of CPLProjectRelativeFilenameSafe() that takes
11253 : * into account the subdataset syntax.
11254 : *
11255 : * Examples:
11256 : * \code{.cpp}
11257 : * BuildFilename("tmp/abc.gif", "abc/def", true) == "abc/def/tmp/abc.gif"
11258 : * BuildFilename("../abc.gif", "/abc/def") == "/abc/abc.gif"
11259 : * BuildFilename("abc.gif", "C:\WIN", true) == "C:\WIN\abc.gif"
11260 : * BuildFilename("abc.gif", "C:\WIN", false) == "abc.gif"
11261 : * BuildFilename("/home/even/foo.tif", "/home/even/workdir", true) == "/home/even/foo.tif"
11262 : * \endcode
11263 : *
11264 : * @param pszFilename Filename of interest.
11265 : * @param pszReferencePath Path to a reference directory.
11266 : * @param bRelativeToReferencePath Whether pszFilename, if a relative path, is
11267 : * relative to pszReferencePath
11268 : * @since 3.11
11269 : */
11270 :
11271 : /* static */
11272 104245 : std::string GDALDataset::BuildFilename(const char *pszFilename,
11273 : const char *pszReferencePath,
11274 : bool bRelativeToReferencePath)
11275 : {
11276 104245 : std::string osSrcDSName;
11277 104245 : if (pszReferencePath != nullptr && bRelativeToReferencePath)
11278 : {
11279 : // Try subdatasetinfo API first
11280 : // Note: this will become the only branch when subdatasetinfo will become
11281 : // available for NITF_IM, RASTERLITE and TILEDB
11282 2584 : const auto oSubDSInfo{GDALGetSubdatasetInfo(pszFilename)};
11283 2584 : if (oSubDSInfo && !oSubDSInfo->GetPathComponent().empty())
11284 : {
11285 8 : auto path{oSubDSInfo->GetPathComponent()};
11286 12 : osSrcDSName = oSubDSInfo->ModifyPathComponent(
11287 8 : CPLProjectRelativeFilenameSafe(pszReferencePath, path.c_str())
11288 4 : .c_str());
11289 4 : GDALDestroySubdatasetInfo(oSubDSInfo);
11290 : }
11291 : else
11292 : {
11293 2580 : bool bDone = false;
11294 15470 : for (const char *pszSyntax : apszSpecialSubDatasetSyntax)
11295 : {
11296 12892 : CPLString osPrefix(pszSyntax);
11297 12892 : osPrefix.resize(strchr(pszSyntax, ':') - pszSyntax + 1);
11298 12892 : if (pszSyntax[osPrefix.size()] == '"')
11299 2578 : osPrefix += '"';
11300 12892 : if (EQUALN(pszFilename, osPrefix, osPrefix.size()))
11301 : {
11302 2 : if (STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}"))
11303 : {
11304 2 : const char *pszLastPart = strrchr(pszFilename, ':') + 1;
11305 : // CSV:z:/foo.xyz
11306 2 : if ((pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
11307 0 : pszLastPart - pszFilename >= 3 &&
11308 0 : pszLastPart[-3] == ':')
11309 : {
11310 0 : pszLastPart -= 2;
11311 : }
11312 2 : CPLString osPrefixFilename = pszFilename;
11313 2 : osPrefixFilename.resize(pszLastPart - pszFilename);
11314 4 : osSrcDSName = osPrefixFilename +
11315 4 : CPLProjectRelativeFilenameSafe(
11316 2 : pszReferencePath, pszLastPart);
11317 2 : bDone = true;
11318 : }
11319 0 : else if (STARTS_WITH_CI(pszSyntax + osPrefix.size(),
11320 : "{FILENAME}"))
11321 : {
11322 0 : CPLString osFilename(pszFilename + osPrefix.size());
11323 0 : size_t nPos = 0;
11324 0 : if (osFilename.size() >= 3 && osFilename[1] == ':' &&
11325 0 : (osFilename[2] == '\\' || osFilename[2] == '/'))
11326 0 : nPos = 2;
11327 0 : nPos = osFilename.find(
11328 0 : pszSyntax[osPrefix.size() + strlen("{FILENAME}")],
11329 : nPos);
11330 0 : if (nPos != std::string::npos)
11331 : {
11332 0 : const CPLString osSuffix = osFilename.substr(nPos);
11333 0 : osFilename.resize(nPos);
11334 0 : osSrcDSName = osPrefix +
11335 0 : CPLProjectRelativeFilenameSafe(
11336 0 : pszReferencePath, osFilename) +
11337 0 : osSuffix;
11338 0 : bDone = true;
11339 : }
11340 : }
11341 2 : break;
11342 : }
11343 : }
11344 2580 : if (!bDone)
11345 : {
11346 2578 : std::string osReferencePath = pszReferencePath;
11347 2578 : if (!CPLIsFilenameRelative(pszReferencePath))
11348 : {
11349 : // Simplify path by replacing "foo/a/../b" with "foo/b"
11350 2289 : while (STARTS_WITH(pszFilename, "../"))
11351 : {
11352 : osReferencePath =
11353 5 : CPLGetPathSafe(osReferencePath.c_str());
11354 5 : pszFilename += strlen("../");
11355 : }
11356 : }
11357 :
11358 5156 : osSrcDSName = CPLProjectRelativeFilenameSafe(
11359 2578 : osReferencePath.c_str(), pszFilename);
11360 : }
11361 2584 : }
11362 : }
11363 : else
11364 : {
11365 101661 : osSrcDSName = pszFilename;
11366 : }
11367 104245 : return osSrcDSName;
11368 : }
|