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 :
16 : #include <array>
17 : #include <cassert>
18 : #include <climits>
19 : #include <cstdarg>
20 : #include <cstdio>
21 : #include <cstdlib>
22 : #include <cstring>
23 : #include <algorithm>
24 : #include <map>
25 : #include <mutex>
26 : #include <new>
27 : #include <set>
28 : #include <string>
29 : #include <utility>
30 :
31 : #include "cpl_conv.h"
32 : #include "cpl_error.h"
33 : #include "cpl_hash_set.h"
34 : #include "cpl_multiproc.h"
35 : #include "cpl_progress.h"
36 : #include "cpl_string.h"
37 : #include "cpl_vsi.h"
38 : #include "cpl_vsi_error.h"
39 :
40 : #include "gdal.h"
41 : #include "gdal_alg.h"
42 : #include "gdal_abstractbandblockcache.h"
43 : #include "gdalantirecursion.h"
44 : #include "gdal_dataset.h"
45 : #include "gdalsubdatasetinfo.h"
46 :
47 : #include "ogr_api.h"
48 : #include "ogr_attrind.h"
49 : #include "ogr_core.h"
50 : #include "ogr_feature.h"
51 : #include "ogr_featurestyle.h"
52 : #include "ogr_gensql.h"
53 : #include "ogr_geometry.h"
54 : #include "ogr_p.h"
55 : #include "ogr_spatialref.h"
56 : #include "ogr_srs_api.h"
57 : #include "ograpispy.h"
58 : #include "ogrsf_frmts.h"
59 : #include "ogrunionlayer.h"
60 : #include "ogr_swq.h"
61 : #include "memmultidim.h"
62 : #include "gdalmultidim_priv.h"
63 :
64 : #include "../frmts/derived/derivedlist.h"
65 :
66 : #ifdef SQLITE_ENABLED
67 : #include "../sqlite/ogrsqliteexecutesql.h"
68 : #endif
69 :
70 : extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
71 :
72 : CPL_C_START
73 : GDALAsyncReader *GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff,
74 : int nYOff, int nXSize, int nYSize,
75 : void *pBuf, int nBufXSize,
76 : int nBufYSize, GDALDataType eBufType,
77 : int nBandCount, int *panBandMap,
78 : int nPixelSpace, int nLineSpace,
79 : int nBandSpace, char **papszOptions);
80 : CPL_C_END
81 :
82 : enum class GDALAllowReadWriteMutexState
83 : {
84 : RW_MUTEX_STATE_UNKNOWN,
85 : RW_MUTEX_STATE_ALLOWED,
86 : RW_MUTEX_STATE_DISABLED
87 : };
88 :
89 : const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
90 : const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
91 :
92 : class GDALDataset::Private
93 : {
94 : CPL_DISALLOW_COPY_ASSIGN(Private)
95 :
96 : public:
97 : CPLMutex *hMutex = nullptr;
98 : std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
99 : #ifdef DEBUG_EXTRA
100 : std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
101 : #endif
102 : GDALAllowReadWriteMutexState eStateReadWriteMutex =
103 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
104 : int nCurrentLayerIdx = 0;
105 : int nLayerCount = -1;
106 : GIntBig nFeatureReadInLayer = 0;
107 : GIntBig nFeatureReadInDataset = 0;
108 : GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
109 : GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
110 : OGRLayer *poCurrentLayer = nullptr;
111 :
112 : std::mutex m_oMutexWKT{};
113 :
114 : char *m_pszWKTCached = nullptr;
115 : OGRSpatialReference *m_poSRSCached = nullptr;
116 : char *m_pszWKTGCPCached = nullptr;
117 : OGRSpatialReference *m_poSRSGCPCached = nullptr;
118 :
119 : GDALDataset *poParentDataset = nullptr;
120 :
121 : bool m_bOverviewsEnabled = true;
122 :
123 : std::vector<int>
124 : m_anBandMap{}; // used by RasterIO(). Values are 1, 2, etc.
125 :
126 151969 : Private() = default;
127 : };
128 :
129 : struct SharedDatasetCtxt
130 : {
131 : // PID of the thread that mark the dataset as shared
132 : // This may not be the actual PID, but the responsiblePID.
133 : GIntBig nPID;
134 : char *pszDescription;
135 : char *pszConcatenatedOpenOptions;
136 : int nOpenFlags;
137 :
138 : GDALDataset *poDS;
139 : };
140 :
141 : // Set of datasets opened as shared datasets (with GDALOpenShared)
142 : // The values in the set are of type SharedDatasetCtxt.
143 : static CPLHashSet *phSharedDatasetSet = nullptr;
144 :
145 : // Set of all datasets created in the constructor of GDALDataset.
146 : // In the case of a shared dataset, memorize the PID of the thread
147 : // that marked the dataset as shared, so that we can remove it from
148 : // the phSharedDatasetSet in the destructor of the dataset, even
149 : // if GDALClose is called from a different thread.
150 : static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
151 :
152 : static CPLMutex *hDLMutex = nullptr;
153 :
154 : // Static array of all datasets. Used by GDALGetOpenDatasets.
155 : // Not thread-safe. See GDALGetOpenDatasets.
156 : static GDALDataset **ppDatasets = nullptr;
157 :
158 8402 : static unsigned long GDALSharedDatasetHashFunc(const void *elt)
159 : {
160 8402 : const SharedDatasetCtxt *psStruct =
161 : static_cast<const SharedDatasetCtxt *>(elt);
162 : return static_cast<unsigned long>(
163 8402 : CPLHashSetHashStr(psStruct->pszDescription) ^
164 8402 : CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^
165 8402 : psStruct->nOpenFlags ^ psStruct->nPID);
166 : }
167 :
168 6981 : static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)
169 : {
170 6981 : const SharedDatasetCtxt *psStruct1 =
171 : static_cast<const SharedDatasetCtxt *>(elt1);
172 6981 : const SharedDatasetCtxt *psStruct2 =
173 : static_cast<const SharedDatasetCtxt *>(elt2);
174 13908 : return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
175 6927 : strcmp(psStruct1->pszConcatenatedOpenOptions,
176 6927 : psStruct2->pszConcatenatedOpenOptions) == 0 &&
177 20835 : psStruct1->nPID == psStruct2->nPID &&
178 13908 : psStruct1->nOpenFlags == psStruct2->nOpenFlags;
179 : }
180 :
181 411 : static void GDALSharedDatasetFreeFunc(void *elt)
182 : {
183 411 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
184 411 : CPLFree(psStruct->pszDescription);
185 411 : CPLFree(psStruct->pszConcatenatedOpenOptions);
186 411 : CPLFree(psStruct);
187 411 : }
188 :
189 : static std::string
190 7049 : GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)
191 : {
192 7049 : std::string osStr;
193 7062 : for (const char *pszOption : cpl::Iterate(papszOpenOptions))
194 13 : osStr += pszOption;
195 7049 : return osStr;
196 : }
197 :
198 : /************************************************************************/
199 : /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
200 : /************************************************************************/
201 :
202 : // The open-shared mutex must be used by the ProxyPool too.
203 482607 : CPLMutex **GDALGetphDLMutex()
204 : {
205 482607 : return &hDLMutex;
206 : }
207 :
208 : // The current thread will act in the behalf of the thread of PID
209 : // responsiblePID.
210 472117 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
211 : {
212 : GIntBig *pResponsiblePID =
213 472117 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
214 472116 : if (pResponsiblePID == nullptr)
215 : {
216 220 : pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
217 219 : CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
218 : }
219 472115 : *pResponsiblePID = responsiblePID;
220 472115 : }
221 :
222 : // Get the PID of the thread that the current thread will act in the behalf of
223 : // By default : the current thread acts in the behalf of itself.
224 599439 : GIntBig GDALGetResponsiblePIDForCurrentThread()
225 : {
226 : GIntBig *pResponsiblePID =
227 599439 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
228 599431 : if (pResponsiblePID == nullptr)
229 43927 : return CPLGetPID();
230 555504 : return *pResponsiblePID;
231 : }
232 :
233 : /************************************************************************/
234 : /* ==================================================================== */
235 : /* GDALDataset */
236 : /* ==================================================================== */
237 : /************************************************************************/
238 :
239 : /**
240 : * \class GDALDataset "gdal_priv.h"
241 : *
242 : * A dataset encapsulating one or more raster bands. Details are further
243 : * discussed in the <a href="https://gdal.org/user/raster_data_model.html">GDAL
244 : * Raster Data Model</a>.
245 : *
246 : * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
247 : * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
248 : * dataset.
249 : */
250 :
251 : /************************************************************************/
252 : /* GDALDataset() */
253 : /************************************************************************/
254 :
255 : //! @cond Doxygen_Suppress
256 131294 : GDALDataset::GDALDataset()
257 131294 : : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
258 : {
259 131289 : }
260 :
261 151973 : GDALDataset::GDALDataset(int bForceCachedIOIn)
262 151964 : : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
263 151973 : m_poPrivate(new(std::nothrow) GDALDataset::Private)
264 : {
265 151962 : }
266 :
267 : //! @endcond
268 :
269 : /************************************************************************/
270 : /* ~GDALDataset() */
271 : /************************************************************************/
272 :
273 : /**
274 : * \brief Destroy an open GDALDataset.
275 : *
276 : * This is the accepted method of closing a GDAL dataset and deallocating
277 : * all resources associated with it.
278 : *
279 : * Equivalent of the C callable GDALClose(). Except that GDALClose() first
280 : * decrements the reference count, and then closes only if it has dropped to
281 : * zero.
282 : *
283 : * For Windows users, it is not recommended to use the delete operator on the
284 : * dataset object because of known issues when allocating and freeing memory
285 : * across module boundaries. Calling GDALClose() is then a better option.
286 : */
287 :
288 151954 : GDALDataset::~GDALDataset()
289 :
290 : {
291 : // we don't want to report destruction of datasets that
292 : // were never really open or meant as internal
293 151956 : if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))
294 : {
295 71263 : if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
296 209 : CPLDebug("GDAL",
297 : "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
298 209 : GetDescription(), this, static_cast<int>(CPLGetPID()),
299 209 : static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
300 : else
301 71054 : CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
302 : }
303 :
304 151957 : GDALDataset::Close();
305 :
306 : /* -------------------------------------------------------------------- */
307 : /* Remove dataset from the "open" dataset list. */
308 : /* -------------------------------------------------------------------- */
309 151952 : if (!bIsInternal)
310 : {
311 145181 : CPLMutexHolderD(&hDLMutex);
312 72593 : if (poAllDatasetMap)
313 : {
314 : std::map<GDALDataset *, GIntBig>::iterator oIter =
315 72593 : poAllDatasetMap->find(this);
316 72593 : CPLAssert(oIter != poAllDatasetMap->end());
317 :
318 72593 : UnregisterFromSharedDataset();
319 :
320 72593 : poAllDatasetMap->erase(oIter);
321 :
322 72593 : if (poAllDatasetMap->empty())
323 : {
324 31605 : delete poAllDatasetMap;
325 31605 : poAllDatasetMap = nullptr;
326 31605 : if (phSharedDatasetSet)
327 : {
328 289 : CPLHashSetDestroy(phSharedDatasetSet);
329 : }
330 31605 : phSharedDatasetSet = nullptr;
331 31605 : CPLFree(ppDatasets);
332 31605 : ppDatasets = nullptr;
333 : }
334 : }
335 : }
336 :
337 : /* -------------------------------------------------------------------- */
338 : /* Destroy the raster bands if they exist. */
339 : /* -------------------------------------------------------------------- */
340 1683700 : for (int i = 0; i < nBands && papoBands != nullptr; ++i)
341 : {
342 1531740 : if (papoBands[i] != nullptr)
343 1531750 : delete papoBands[i];
344 1531750 : papoBands[i] = nullptr;
345 : }
346 :
347 151962 : CPLFree(papoBands);
348 :
349 151956 : if (m_poStyleTable)
350 : {
351 23 : delete m_poStyleTable;
352 23 : m_poStyleTable = nullptr;
353 : }
354 :
355 151956 : if (m_poPrivate != nullptr)
356 : {
357 151952 : if (m_poPrivate->hMutex != nullptr)
358 20950 : CPLDestroyMutex(m_poPrivate->hMutex);
359 :
360 : #if defined(__COVERITY__) || defined(DEBUG)
361 : // Not needed since at destruction there is no risk of concurrent use.
362 303905 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
363 : #endif
364 151955 : CPLFree(m_poPrivate->m_pszWKTCached);
365 151954 : if (m_poPrivate->m_poSRSCached)
366 : {
367 0 : m_poPrivate->m_poSRSCached->Release();
368 : }
369 151954 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
370 151953 : if (m_poPrivate->m_poSRSGCPCached)
371 : {
372 0 : m_poPrivate->m_poSRSGCPCached->Release();
373 : }
374 : }
375 :
376 151956 : delete m_poPrivate;
377 :
378 151959 : CSLDestroy(papszOpenOptions);
379 151955 : }
380 :
381 : /************************************************************************/
382 : /* Close() */
383 : /************************************************************************/
384 :
385 : /** Do final cleanup before a dataset is destroyed.
386 : *
387 : * This method is typically called by GDALClose() or the destructor of a
388 : * GDALDataset subclass. It might also be called by C++ users before
389 : * destroying a dataset. It should not be called on a shared dataset whose
390 : * reference count is greater than one.
391 : *
392 : * It gives a last chance to the closing process to return an error code if
393 : * something goes wrong, in particular in creation / update scenarios where
394 : * file write or network communication might occur when finalizing the dataset.
395 : *
396 : * Implementations should be robust to this method to be called several times
397 : * (on subsequent calls, it should do nothing and return CE_None).
398 : * Once it has been called, no other method than Close() or the dataset
399 : * destructor should be called. RasterBand or OGRLayer owned by the dataset
400 : * should be assumed as no longer being valid.
401 : *
402 : * If a driver implements this method, it must also call it from its
403 : * dataset destructor.
404 : *
405 : * This is the equivalent of C function GDALDatasetRunCloseWithoutDestroying().
406 : *
407 : * A typical implementation might look as the following
408 : * \code{.cpp}
409 : *
410 : * MyDataset::~MyDataset()
411 : * {
412 : * try
413 : * {
414 : * MyDataset::Close();
415 : * }
416 : * catch (const std::exception &exc)
417 : * {
418 : * // If Close() can throw exception
419 : * CPLError(CE_Failure, CPLE_AppDefined,
420 : * "Exception thrown in MyDataset::Close(): %s",
421 : * exc.what());
422 : * }
423 : * catch (...)
424 : * {
425 : * // If Close() can throw exception
426 : * CPLError(CE_Failure, CPLE_AppDefined,
427 : * "Exception thrown in MyDataset::Close()");
428 : * }
429 : * }
430 : *
431 : * CPLErr MyDataset::Close()
432 : * {
433 : * CPLErr eErr = CE_None;
434 : * if( nOpenFlags != OPEN_FLAGS_CLOSED )
435 : * {
436 : * eErr = MyDataset::FlushCache(true);
437 : *
438 : * // Do something driver specific
439 : * if (m_fpImage)
440 : * {
441 : * if( VSIFCloseL(m_fpImage) != 0 )
442 : * {
443 : * CPLError(CE_Failure, CPLE_FileIO, "VSIFCloseL() failed");
444 : * eErr = CE_Failure;
445 : * }
446 : * }
447 : *
448 : * // Call parent Close() implementation.
449 : * eErr = GDAL::Combine(eErr, MyParentDatasetClass::Close());
450 : * }
451 : * return eErr;
452 : * }
453 : * \endcode
454 : *
455 : * @since GDAL 3.7
456 : */
457 265114 : CPLErr GDALDataset::Close()
458 : {
459 265114 : if (nOpenFlags != OPEN_FLAGS_CLOSED)
460 : {
461 : // Call UnregisterFromSharedDataset() before altering nOpenFlags
462 151955 : UnregisterFromSharedDataset();
463 :
464 151956 : nOpenFlags = OPEN_FLAGS_CLOSED;
465 : }
466 :
467 265115 : if (IsMarkedSuppressOnClose())
468 : {
469 3378 : if (poDriver == nullptr ||
470 : // Someone issuing Create("foo.tif") on a
471 : // memory driver doesn't expect files with those names to be deleted
472 : // on a file system...
473 : // This is somewhat messy. Ideally there should be a way for the
474 : // driver to overload the default behavior
475 1679 : (!EQUAL(poDriver->GetDescription(), "MEM") &&
476 1601 : !EQUAL(poDriver->GetDescription(), "Memory")))
477 : {
478 1621 : if (VSIUnlink(GetDescription()) == 0)
479 683 : UnMarkSuppressOnClose();
480 : }
481 : }
482 :
483 265108 : return CE_None;
484 : }
485 :
486 : /************************************************************************/
487 : /* GDALDatasetRunCloseWithoutDestroying() */
488 : /************************************************************************/
489 :
490 : /** Run the Close() method, without running destruction of the object.
491 : *
492 : * This ensures that content that should be written to file is written and
493 : * that all file descriptors are closed.
494 : *
495 : * Note that this is different from GDALClose() which also destroys
496 : * the underlying C++ object. GDALClose() or GDALReleaseDataset() are actually
497 : * the only functions that can be safely called on the dataset handle after
498 : * this function has been called.
499 : *
500 : * Most users want to use GDALClose() or GDALReleaseDataset() rather than
501 : * this function.
502 : *
503 : * This function is equivalent to the C++ method GDALDataset:Close()
504 : *
505 : * @param hDS dataset handle.
506 : * @return CE_None if no error
507 : *
508 : * @since GDAL 3.12
509 : * @see GDALClose()
510 : */
511 12 : CPLErr GDALDatasetRunCloseWithoutDestroying(GDALDatasetH hDS)
512 : {
513 12 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
514 12 : return GDALDataset::FromHandle(hDS)->Close();
515 : }
516 :
517 : /************************************************************************/
518 : /* UnregisterFromSharedDataset() */
519 : /************************************************************************/
520 :
521 224550 : void GDALDataset::UnregisterFromSharedDataset()
522 : {
523 224550 : if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))
524 224139 : return;
525 :
526 822 : CPLMutexHolderD(&hDLMutex);
527 :
528 : std::map<GDALDataset *, GIntBig>::iterator oIter =
529 411 : poAllDatasetMap->find(this);
530 411 : CPLAssert(oIter != poAllDatasetMap->end());
531 411 : const GIntBig nPIDCreatorForShared = oIter->second;
532 411 : bShared = false;
533 : SharedDatasetCtxt sStruct;
534 411 : sStruct.nPID = nPIDCreatorForShared;
535 411 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
536 411 : sStruct.pszDescription = const_cast<char *>(GetDescription());
537 : std::string osConcatenatedOpenOptions =
538 822 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
539 411 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
540 411 : sStruct.poDS = nullptr;
541 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
542 411 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
543 411 : if (psStruct && psStruct->poDS == this)
544 : {
545 410 : CPLHashSetRemove(phSharedDatasetSet, psStruct);
546 : }
547 : else
548 : {
549 1 : CPLDebug("GDAL",
550 : "Should not happen. Cannot find %s, "
551 : "this=%p in phSharedDatasetSet",
552 1 : GetDescription(), this);
553 : }
554 : }
555 :
556 : /************************************************************************/
557 : /* AddToDatasetOpenList() */
558 : /************************************************************************/
559 :
560 73915 : void GDALDataset::AddToDatasetOpenList()
561 : {
562 : /* -------------------------------------------------------------------- */
563 : /* Add this dataset to the open dataset list. */
564 : /* -------------------------------------------------------------------- */
565 73915 : bIsInternal = false;
566 :
567 73915 : CPLMutexHolderD(&hDLMutex);
568 :
569 73915 : if (poAllDatasetMap == nullptr)
570 31614 : poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
571 73915 : (*poAllDatasetMap)[this] = -1;
572 73915 : }
573 :
574 : /************************************************************************/
575 : /* FlushCache() */
576 : /************************************************************************/
577 :
578 : /**
579 : * \brief Flush all write cached data to disk.
580 : *
581 : * Any raster (or other GDAL) data written via GDAL calls, but buffered
582 : * internally will be written to disk.
583 : *
584 : * The default implementation of this method just calls the FlushCache() method
585 : * on each of the raster bands and the SyncToDisk() method
586 : * on each of the layers. Conceptually, calling FlushCache() on a dataset
587 : * should include any work that might be accomplished by calling SyncToDisk()
588 : * on layers in that dataset.
589 : *
590 : * Using this method does not prevent use from calling GDALClose()
591 : * to properly close a dataset and ensure that important data not addressed
592 : * by FlushCache() is written in the file.
593 : *
594 : * This method is the same as the C function GDALFlushCache().
595 : *
596 : * @param bAtClosing Whether this is called from a GDALDataset destructor
597 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
598 : */
599 :
600 119030 : CPLErr GDALDataset::FlushCache(bool bAtClosing)
601 :
602 : {
603 119030 : CPLErr eErr = CE_None;
604 : // This sometimes happens if a dataset is destroyed before completely
605 : // built.
606 :
607 119030 : if (papoBands)
608 : {
609 1931340 : for (int i = 0; i < nBands; ++i)
610 : {
611 1825940 : if (papoBands[i])
612 : {
613 1825950 : if (papoBands[i]->FlushCache(bAtClosing) != CE_None)
614 7 : eErr = CE_Failure;
615 : }
616 : }
617 : }
618 :
619 119028 : const int nLayers = GetLayerCount();
620 : // cppcheck-suppress knownConditionTrueFalse
621 119028 : if (nLayers > 0)
622 : {
623 16348 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
624 25746 : for (int i = 0; i < nLayers; ++i)
625 : {
626 17572 : OGRLayer *poLayer = GetLayer(i);
627 :
628 17572 : if (poLayer)
629 : {
630 17572 : if (poLayer->SyncToDisk() != OGRERR_NONE)
631 1 : eErr = CE_Failure;
632 : }
633 : }
634 : }
635 :
636 119028 : return eErr;
637 : }
638 :
639 : /************************************************************************/
640 : /* GDALFlushCache() */
641 : /************************************************************************/
642 :
643 : /**
644 : * \brief Flush all write cached data to disk.
645 : *
646 : * @see GDALDataset::FlushCache().
647 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
648 : */
649 :
650 4858 : CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)
651 :
652 : {
653 4858 : VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);
654 :
655 4858 : return GDALDataset::FromHandle(hDS)->FlushCache(false);
656 : }
657 :
658 : /************************************************************************/
659 : /* DropCache() */
660 : /************************************************************************/
661 :
662 : /**
663 : * \brief Drop all write cached data
664 : *
665 : * This method is the same as the C function GDALDropCache().
666 : *
667 : * @return CE_None in case of success
668 : * @since 3.9
669 : */
670 :
671 1 : CPLErr GDALDataset::DropCache()
672 :
673 : {
674 1 : CPLErr eErr = CE_None;
675 :
676 1 : if (papoBands)
677 : {
678 2 : for (int i = 0; i < nBands; ++i)
679 : {
680 1 : if (papoBands[i])
681 : {
682 1 : if (papoBands[i]->DropCache() != CE_None)
683 0 : eErr = CE_Failure;
684 : }
685 : }
686 : }
687 :
688 1 : return eErr;
689 : }
690 :
691 : /************************************************************************/
692 : /* GDALDropCache() */
693 : /************************************************************************/
694 :
695 : /**
696 : * \brief Drop all write cached data
697 : *
698 : * @see GDALDataset::DropCache().
699 : * @return CE_None in case of success
700 : * @since 3.9
701 : */
702 :
703 0 : CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS)
704 :
705 : {
706 0 : VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure);
707 :
708 0 : return GDALDataset::FromHandle(hDS)->DropCache();
709 : }
710 :
711 : /************************************************************************/
712 : /* GetEstimatedRAMUsage() */
713 : /************************************************************************/
714 :
715 : /**
716 : * \brief Return the intrinsic RAM usage of this dataset.
717 : *
718 : * The returned value should take into account caches in the underlying driver
719 : * and decoding library, but not the usage related to the GDAL block cache.
720 : *
721 : * At time of writing, this method is only implemented in the JP2OpenJPEG
722 : * driver. For single-tiled JPEG2000 images, the decoding of the image,
723 : * even partially, involves allocating at least
724 : * width * height * number_of_bands * sizeof(uint32_t) bytes inside the libopenjp2
725 : * library.
726 : *
727 : * This method is used by the GDALDatasetPool class, itself used by the GDAL VRT
728 : * driver, to determine how long a dataset in the pool must be kept open, given
729 : * the RAM usage of the dataset with respect to the usable total RAM.
730 : *
731 : * @since GDAL 3.7
732 : * @return RAM usage in bytes, or -1 if unknown (the default implementation
733 : * returns -1)
734 : */
735 :
736 3324 : GIntBig GDALDataset::GetEstimatedRAMUsage()
737 : {
738 3324 : return -1;
739 : }
740 :
741 : /************************************************************************/
742 : /* BlockBasedFlushCache() */
743 : /* */
744 : /* This helper method can be called by the */
745 : /* GDALDataset::FlushCache() for particular drivers to ensure */
746 : /* that buffers will be flushed in a manner suitable for pixel */
747 : /* interleaved (by block) IO. That is, if all the bands have */
748 : /* the same size blocks then a given block will be flushed for */
749 : /* all bands before proceeding to the next block. */
750 : /************************************************************************/
751 :
752 : //! @cond Doxygen_Suppress
753 350 : CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)
754 :
755 : {
756 350 : GDALRasterBand *poBand1 = GetRasterBand(1);
757 350 : if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))
758 : {
759 7 : return GDALDataset::FlushCache(bAtClosing);
760 : }
761 :
762 343 : int nBlockXSize = 0;
763 343 : int nBlockYSize = 0;
764 343 : poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
765 :
766 : /* -------------------------------------------------------------------- */
767 : /* Verify that all bands match. */
768 : /* -------------------------------------------------------------------- */
769 1108 : for (int iBand = 1; iBand < nBands; ++iBand)
770 : {
771 765 : GDALRasterBand *poBand = GetRasterBand(iBand + 1);
772 :
773 : int nThisBlockXSize, nThisBlockYSize;
774 765 : poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
775 765 : if (nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize)
776 : {
777 0 : return GDALDataset::FlushCache(bAtClosing);
778 : }
779 : }
780 :
781 : /* -------------------------------------------------------------------- */
782 : /* Now flush writable data. */
783 : /* -------------------------------------------------------------------- */
784 794 : for (int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY)
785 : {
786 991 : for (int iX = 0; iX < poBand1->nBlocksPerRow; ++iX)
787 : {
788 1690 : for (int iBand = 0; iBand < nBands; ++iBand)
789 : {
790 1150 : const CPLErr eErr = papoBands[iBand]->FlushBlock(iX, iY);
791 :
792 1150 : if (eErr != CE_None)
793 0 : return CE_Failure;
794 : }
795 : }
796 : }
797 343 : return CE_None;
798 : }
799 :
800 : /************************************************************************/
801 : /* RasterInitialize() */
802 : /* */
803 : /* Initialize raster size */
804 : /************************************************************************/
805 :
806 0 : void GDALDataset::RasterInitialize(int nXSize, int nYSize)
807 :
808 : {
809 0 : CPLAssert(nXSize > 0 && nYSize > 0);
810 :
811 0 : nRasterXSize = nXSize;
812 0 : nRasterYSize = nYSize;
813 0 : }
814 :
815 : //! @endcond
816 :
817 : /************************************************************************/
818 : /* AddBand() */
819 : /************************************************************************/
820 :
821 : /**
822 : * \fn GDALDataset::AddBand(GDALDataType, char**)
823 : * \brief Add a band to a dataset.
824 : *
825 : * This method will add a new band to the dataset if the underlying format
826 : * supports this action. Most formats do not.
827 : *
828 : * Note that the new GDALRasterBand is not returned. It may be fetched
829 : * after successful completion of the method by calling
830 : * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
831 : * band will always be the last band.
832 : *
833 : * @param eType the data type of the pixels in the new band.
834 : *
835 : * @param papszOptions a list of NAME=VALUE option strings. The supported
836 : * options are format specific. NULL may be passed by default.
837 : *
838 : * @return CE_None on success or CE_Failure on failure.
839 : */
840 :
841 0 : CPLErr GDALDataset::AddBand(CPL_UNUSED GDALDataType eType,
842 : CPL_UNUSED char **papszOptions)
843 :
844 : {
845 0 : ReportError(CE_Failure, CPLE_NotSupported,
846 : "Dataset does not support the AddBand() method.");
847 :
848 0 : return CE_Failure;
849 : }
850 :
851 : /************************************************************************/
852 : /* GDALAddBand() */
853 : /************************************************************************/
854 :
855 : /**
856 : * \brief Add a band to a dataset.
857 : *
858 : * @see GDALDataset::AddBand().
859 : */
860 :
861 32 : CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,
862 : CSLConstList papszOptions)
863 :
864 : {
865 32 : VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
866 :
867 64 : return GDALDataset::FromHandle(hDataset)->AddBand(
868 32 : eType, const_cast<char **>(papszOptions));
869 : }
870 :
871 : /************************************************************************/
872 : /* SetBand() */
873 : /************************************************************************/
874 :
875 : //! @cond Doxygen_Suppress
876 : /** Set a band in the band array, updating the band count, and array size
877 : * appropriately.
878 : *
879 : * @param nNewBand new band number (indexing starts at 1)
880 : * @param poBand band object.
881 : */
882 :
883 1677070 : void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)
884 :
885 : {
886 : /* -------------------------------------------------------------------- */
887 : /* Do we need to grow the bands list? */
888 : /* -------------------------------------------------------------------- */
889 1677070 : if (nBands < nNewBand || papoBands == nullptr)
890 : {
891 942414 : GDALRasterBand **papoNewBands = nullptr;
892 :
893 942414 : if (papoBands == nullptr)
894 96632 : papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
895 96620 : sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
896 : else
897 : papoNewBands = static_cast<GDALRasterBand **>(
898 845787 : VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
899 845794 : std::max(nNewBand, nBands)));
900 942419 : if (papoNewBands == nullptr)
901 : {
902 0 : ReportError(CE_Failure, CPLE_OutOfMemory,
903 : "Cannot allocate band array");
904 0 : return;
905 : }
906 :
907 942419 : papoBands = papoNewBands;
908 :
909 1834140 : for (int i = nBands; i < nNewBand; ++i)
910 891717 : papoBands[i] = nullptr;
911 :
912 942419 : nBands = std::max(nBands, nNewBand);
913 :
914 942416 : if (m_poPrivate)
915 : {
916 942461 : for (int i = static_cast<int>(m_poPrivate->m_anBandMap.size());
917 2619470 : i < nBands; ++i)
918 : {
919 1677040 : m_poPrivate->m_anBandMap.push_back(i + 1);
920 : }
921 : }
922 : }
923 :
924 : /* -------------------------------------------------------------------- */
925 : /* Set the band. Resetting the band is currently not permitted. */
926 : /* -------------------------------------------------------------------- */
927 1677040 : if (papoBands[nNewBand - 1] != nullptr)
928 : {
929 0 : ReportError(CE_Failure, CPLE_NotSupported,
930 : "Cannot set band %d as it is already set", nNewBand);
931 0 : return;
932 : }
933 :
934 1677040 : papoBands[nNewBand - 1] = poBand;
935 :
936 : /* -------------------------------------------------------------------- */
937 : /* Set back reference information on the raster band. Note */
938 : /* that the GDALDataset is a friend of the GDALRasterBand */
939 : /* specifically to allow this. */
940 : /* -------------------------------------------------------------------- */
941 1677040 : poBand->nBand = nNewBand;
942 1677040 : poBand->poDS = this;
943 1677040 : poBand->nRasterXSize = nRasterXSize;
944 1677040 : poBand->nRasterYSize = nRasterYSize;
945 1677040 : poBand->eAccess = eAccess; // Default access to be same as dataset.
946 : }
947 :
948 : //! @endcond
949 :
950 : /************************************************************************/
951 : /* SetBand() */
952 : /************************************************************************/
953 :
954 : //! @cond Doxygen_Suppress
955 : /** Set a band in the band array, updating the band count, and array size
956 : * appropriately.
957 : *
958 : * @param nNewBand new band number (indexing starts at 1)
959 : * @param poBand band object.
960 : */
961 :
962 76611 : void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)
963 : {
964 76611 : SetBand(nNewBand, poBand.release());
965 76611 : }
966 :
967 : //! @endcond
968 :
969 : /************************************************************************/
970 : /* GetRasterXSize() */
971 : /************************************************************************/
972 :
973 : /**
974 :
975 : \brief Fetch raster width in pixels.
976 :
977 : Equivalent of the C function GDALGetRasterXSize().
978 :
979 : @return the width in pixels of raster bands in this GDALDataset.
980 :
981 : */
982 :
983 709565 : int GDALDataset::GetRasterXSize() const
984 : {
985 709565 : return nRasterXSize;
986 : }
987 :
988 : /************************************************************************/
989 : /* GDALGetRasterXSize() */
990 : /************************************************************************/
991 :
992 : /**
993 : * \brief Fetch raster width in pixels.
994 : *
995 : * @see GDALDataset::GetRasterXSize().
996 : */
997 :
998 37461 : int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)
999 :
1000 : {
1001 37461 : VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
1002 :
1003 37461 : return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
1004 : }
1005 :
1006 : /************************************************************************/
1007 : /* GetRasterYSize() */
1008 : /************************************************************************/
1009 :
1010 : /**
1011 :
1012 : \brief Fetch raster height in pixels.
1013 :
1014 : Equivalent of the C function GDALGetRasterYSize().
1015 :
1016 : @return the height in pixels of raster bands in this GDALDataset.
1017 :
1018 : */
1019 :
1020 590865 : int GDALDataset::GetRasterYSize() const
1021 : {
1022 590865 : return nRasterYSize;
1023 : }
1024 :
1025 : /************************************************************************/
1026 : /* GDALGetRasterYSize() */
1027 : /************************************************************************/
1028 :
1029 : /**
1030 : * \brief Fetch raster height in pixels.
1031 : *
1032 : * @see GDALDataset::GetRasterYSize().
1033 : */
1034 :
1035 37080 : int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)
1036 :
1037 : {
1038 37080 : VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
1039 :
1040 37080 : return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
1041 : }
1042 :
1043 : /************************************************************************/
1044 : /* GetRasterBand() */
1045 : /************************************************************************/
1046 :
1047 : /**
1048 :
1049 : \brief Fetch a band object for a dataset.
1050 :
1051 : See GetBands() for a C++ iterator version of this method.
1052 :
1053 : Equivalent of the C function GDALGetRasterBand().
1054 :
1055 : @param nBandId the index number of the band to fetch, from 1 to
1056 : GetRasterCount().
1057 :
1058 : @return the nBandId th band object
1059 :
1060 : */
1061 :
1062 12516200 : GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)
1063 :
1064 : {
1065 12516200 : if (papoBands)
1066 : {
1067 12514300 : if (nBandId < 1 || nBandId > nBands)
1068 : {
1069 6144 : ReportError(CE_Failure, CPLE_IllegalArg,
1070 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1071 : nBandId);
1072 12 : return nullptr;
1073 : }
1074 :
1075 12508200 : return papoBands[nBandId - 1];
1076 : }
1077 1856 : return nullptr;
1078 : }
1079 :
1080 : /************************************************************************/
1081 : /* GetRasterBand() */
1082 : /************************************************************************/
1083 :
1084 : /**
1085 :
1086 : \brief Fetch a band object for a dataset.
1087 :
1088 : See GetBands() for a C++ iterator version of this method.
1089 :
1090 : Equivalent of the C function GDALGetRasterBand().
1091 :
1092 : @param nBandId the index number of the band to fetch, from 1 to
1093 : GetRasterCount().
1094 :
1095 : @return the nBandId th band object
1096 :
1097 : */
1098 :
1099 594 : const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const
1100 :
1101 : {
1102 594 : if (papoBands)
1103 : {
1104 594 : if (nBandId < 1 || nBandId > nBands)
1105 : {
1106 0 : ReportError(CE_Failure, CPLE_IllegalArg,
1107 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1108 : nBandId);
1109 0 : return nullptr;
1110 : }
1111 :
1112 594 : return papoBands[nBandId - 1];
1113 : }
1114 0 : return nullptr;
1115 : }
1116 :
1117 : /************************************************************************/
1118 : /* GDALGetRasterBand() */
1119 : /************************************************************************/
1120 :
1121 : /**
1122 : * \brief Fetch a band object for a dataset.
1123 : * @see GDALDataset::GetRasterBand().
1124 : */
1125 :
1126 402245 : GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)
1127 :
1128 : {
1129 402245 : VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
1130 :
1131 402245 : return GDALRasterBand::ToHandle(
1132 402245 : GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
1133 : }
1134 :
1135 : /************************************************************************/
1136 : /* GetRasterCount() */
1137 : /************************************************************************/
1138 :
1139 : /**
1140 : * \brief Fetch the number of raster bands on this dataset.
1141 : *
1142 : * Same as the C function GDALGetRasterCount().
1143 : *
1144 : * @return the number of raster bands.
1145 : */
1146 :
1147 6386940 : int GDALDataset::GetRasterCount() const
1148 : {
1149 6386940 : return papoBands ? nBands : 0;
1150 : }
1151 :
1152 : /************************************************************************/
1153 : /* GDALGetRasterCount() */
1154 : /************************************************************************/
1155 :
1156 : /**
1157 : * \brief Fetch the number of raster bands on this dataset.
1158 : *
1159 : * @see GDALDataset::GetRasterCount().
1160 : */
1161 :
1162 382841 : int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)
1163 :
1164 : {
1165 382841 : VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
1166 :
1167 382841 : return GDALDataset::FromHandle(hDS)->GetRasterCount();
1168 : }
1169 :
1170 : /************************************************************************/
1171 : /* GetProjectionRef() */
1172 : /************************************************************************/
1173 :
1174 : /**
1175 : * \brief Fetch the projection definition string for this dataset.
1176 : *
1177 : * Same as the C function GDALGetProjectionRef().
1178 : *
1179 : * The returned string defines the projection coordinate system of the
1180 : * image in OpenGIS WKT format. It should be suitable for use with the
1181 : * OGRSpatialReference class.
1182 : *
1183 : * When a projection definition is not available an empty (but not NULL)
1184 : * string is returned.
1185 : *
1186 : * \note Starting with GDAL 3.0, this is a compatibility layer around
1187 : * GetSpatialRef()
1188 : *
1189 : * @return a pointer to an internal projection reference string. It should
1190 : * not be altered, freed or expected to last for long.
1191 : *
1192 : * @see https://gdal.org/tutorials/osr_api_tut.html
1193 : */
1194 :
1195 5376 : const char *GDALDataset::GetProjectionRef() const
1196 : {
1197 5376 : const auto poSRS = GetSpatialRef();
1198 5377 : if (!poSRS || !m_poPrivate)
1199 : {
1200 2425 : return "";
1201 : }
1202 2952 : char *pszWKT = nullptr;
1203 2952 : poSRS->exportToWkt(&pszWKT);
1204 2953 : if (!pszWKT)
1205 : {
1206 0 : return "";
1207 : }
1208 :
1209 : // If called on a thread-safe dataset, we might be called by several
1210 : // threads, so make sure our accesses to m_pszWKTCached are protected
1211 : // by a mutex.
1212 5906 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1213 2953 : if (m_poPrivate->m_pszWKTCached &&
1214 793 : strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)
1215 : {
1216 792 : CPLFree(pszWKT);
1217 792 : return m_poPrivate->m_pszWKTCached;
1218 : }
1219 2161 : CPLFree(m_poPrivate->m_pszWKTCached);
1220 2161 : m_poPrivate->m_pszWKTCached = pszWKT;
1221 2161 : return m_poPrivate->m_pszWKTCached;
1222 : }
1223 :
1224 : /************************************************************************/
1225 : /* GetSpatialRef() */
1226 : /************************************************************************/
1227 :
1228 : static thread_local int tlsEnableLayersInGetSpatialRefCounter = 0;
1229 :
1230 : /**
1231 : * \brief Fetch the spatial reference for this dataset.
1232 : *
1233 : * Same as the C function GDALGetSpatialRef().
1234 : *
1235 : * When a projection definition is not available, null is returned. If used on
1236 : * a dataset where there are GCPs and not a geotransform, this method returns
1237 : * null. Use GetGCPSpatialRef() instead.
1238 : *
1239 : * Since GDAL 3.12, the default implementation of this method will iterate over
1240 : * vector layers and return their SRS if all geometry columns of all layers use
1241 : * the same SRS, or nullptr otherwise.
1242 : *
1243 : * @since GDAL 3.0
1244 : *
1245 : * @return a pointer to an internal object. It should not be altered or freed.
1246 : * Its lifetime will be the one of the dataset object.
1247 : *
1248 : * @see https://gdal.org/tutorials/osr_api_tut.html
1249 : */
1250 :
1251 17306 : const OGRSpatialReference *GDALDataset::GetSpatialRef() const
1252 : {
1253 17306 : if (tlsEnableLayersInGetSpatialRefCounter == 0)
1254 17274 : return GetSpatialRefVectorOnly();
1255 32 : return nullptr;
1256 : }
1257 :
1258 : /************************************************************************/
1259 : /* GetSpatialRefVectorOnly() */
1260 : /************************************************************************/
1261 :
1262 : /**
1263 : * \brief Fetch the spatial reference for this dataset (only for vector layers)
1264 : *
1265 : * The default implementation of this method will iterate over
1266 : * vector layers and return their SRS if all geometry columns of all layers use
1267 : * the same SRS, or nullptr otherwise.
1268 : *
1269 : * @since GDAL 3.12
1270 : *
1271 : * @return a pointer to an internal object. It should not be altered or freed.
1272 : * Its lifetime will be the one of the dataset object.
1273 : */
1274 :
1275 17274 : const OGRSpatialReference *GDALDataset::GetSpatialRefVectorOnly() const
1276 : {
1277 17274 : bool bInit = false;
1278 17274 : const OGRSpatialReference *poGlobalSRS = nullptr;
1279 33437 : for (const OGRLayer *poLayer : GetLayers())
1280 : {
1281 16164 : for (const auto *poGeomFieldDefn :
1282 48494 : poLayer->GetLayerDefn()->GetGeomFields())
1283 : {
1284 16167 : const auto *poSRS = poGeomFieldDefn->GetSpatialRef();
1285 16167 : if (!bInit)
1286 : {
1287 207 : bInit = true;
1288 207 : poGlobalSRS = poSRS;
1289 : }
1290 31918 : else if ((poSRS && !poGlobalSRS) || (!poSRS && poGlobalSRS) ||
1291 15958 : (poSRS && poGlobalSRS && !poSRS->IsSame(poGlobalSRS)))
1292 : {
1293 3 : CPLDebug("GDAL",
1294 : "Not all geometry fields or layers have the same CRS");
1295 3 : return nullptr;
1296 : }
1297 : }
1298 : }
1299 17270 : return poGlobalSRS;
1300 : }
1301 :
1302 : /************************************************************************/
1303 : /* GetSpatialRefRasterOnly() */
1304 : /************************************************************************/
1305 :
1306 : /**
1307 : * \brief Fetch the spatial reference for this dataset (ignoring vector layers)
1308 : *
1309 : * @since GDAL 3.12
1310 : *
1311 : * @return a pointer to an internal object. It should not be altered or freed.
1312 : * Its lifetime will be the one of the dataset object.
1313 : */
1314 :
1315 846 : const OGRSpatialReference *GDALDataset::GetSpatialRefRasterOnly() const
1316 : {
1317 846 : ++tlsEnableLayersInGetSpatialRefCounter;
1318 846 : const auto poRet = GetSpatialRef();
1319 846 : --tlsEnableLayersInGetSpatialRefCounter;
1320 846 : return poRet;
1321 : }
1322 :
1323 : /************************************************************************/
1324 : /* GDALGetSpatialRef() */
1325 : /************************************************************************/
1326 :
1327 : /**
1328 : * \brief Fetch the spatial reference for this dataset.
1329 : *
1330 : * Same as the C++ method GDALDataset::GetSpatialRef()
1331 : *
1332 : * @since GDAL 3.0
1333 : *
1334 : * @see GDALDataset::GetSpatialRef()
1335 : */
1336 :
1337 6984 : OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)
1338 :
1339 : {
1340 6984 : VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
1341 :
1342 6984 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1343 6984 : GDALDataset::FromHandle(hDS)->GetSpatialRef()));
1344 : }
1345 :
1346 : /************************************************************************/
1347 : /* GDALGetProjectionRef() */
1348 : /************************************************************************/
1349 :
1350 : /**
1351 : * \brief Fetch the projection definition string for this dataset.
1352 : *
1353 : * @see GDALDataset::GetProjectionRef()
1354 : */
1355 :
1356 1495 : const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)
1357 :
1358 : {
1359 1495 : VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
1360 :
1361 1495 : return GDALDataset::FromHandle(hDS)->GetProjectionRef();
1362 : }
1363 :
1364 : /************************************************************************/
1365 : /* SetProjection() */
1366 : /************************************************************************/
1367 :
1368 : /**
1369 : * \brief Set the projection reference string for this dataset.
1370 : *
1371 : * The string should be in OGC WKT or PROJ.4 format. An error may occur
1372 : * because of incorrectly specified projection strings, because the dataset
1373 : * is not writable, or because the dataset does not support the indicated
1374 : * projection. Many formats do not support writing projections.
1375 : *
1376 : * This method is the same as the C GDALSetProjection() function.
1377 : *
1378 : * \note Startig with GDAL 3.0, this is a compatibility layer around
1379 : * SetSpatialRef()
1380 :
1381 : * @param pszProjection projection reference string.
1382 : *
1383 : * @return CE_Failure if an error occurs, otherwise CE_None.
1384 : */
1385 :
1386 2415 : CPLErr GDALDataset::SetProjection(const char *pszProjection)
1387 : {
1388 2415 : if (pszProjection && pszProjection[0] != '\0')
1389 : {
1390 4464 : OGRSpatialReference oSRS;
1391 2232 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1392 2232 : if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)
1393 : {
1394 2 : return CE_Failure;
1395 : }
1396 2230 : return SetSpatialRef(&oSRS);
1397 : }
1398 : else
1399 : {
1400 183 : return SetSpatialRef(nullptr);
1401 : }
1402 : }
1403 :
1404 : /************************************************************************/
1405 : /* SetSpatialRef() */
1406 : /************************************************************************/
1407 :
1408 : /**
1409 : * \brief Set the spatial reference system for this dataset.
1410 : *
1411 : * An error may occur because the dataset
1412 : * is not writable, or because the dataset does not support the indicated
1413 : * projection. Many formats do not support writing projections.
1414 : *
1415 : * This method is the same as the C GDALSetSpatialRef() function.
1416 : *
1417 : * @since GDAL 3.0
1418 :
1419 : * @param poSRS spatial reference system object. nullptr can potentially be
1420 : * passed for drivers that support unsetting the SRS.
1421 : *
1422 : * @return CE_Failure if an error occurs, otherwise CE_None.
1423 : */
1424 :
1425 0 : CPLErr GDALDataset::SetSpatialRef(CPL_UNUSED const OGRSpatialReference *poSRS)
1426 : {
1427 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1428 0 : ReportError(CE_Failure, CPLE_NotSupported,
1429 : "Dataset does not support the SetSpatialRef() method.");
1430 0 : return CE_Failure;
1431 : }
1432 :
1433 : /************************************************************************/
1434 : /* GDALSetSpatialRef() */
1435 : /************************************************************************/
1436 :
1437 : /**
1438 : * \brief Set the spatial reference system for this dataset.
1439 : *
1440 : * @since GDAL 3.0
1441 : *
1442 : * @see GDALDataset::SetSpatialRef()
1443 : */
1444 :
1445 1191 : CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)
1446 :
1447 : {
1448 1191 : VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1449 :
1450 2382 : return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1451 1191 : OGRSpatialReference::FromHandle(hSRS));
1452 : }
1453 :
1454 : /************************************************************************/
1455 : /* GDALSetProjection() */
1456 : /************************************************************************/
1457 :
1458 : /**
1459 : * \brief Set the projection reference string for this dataset.
1460 : *
1461 : * @see GDALDataset::SetProjection()
1462 : */
1463 :
1464 1796 : CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,
1465 : const char *pszProjection)
1466 :
1467 : {
1468 1796 : VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1469 :
1470 1796 : return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
1471 : }
1472 :
1473 : /************************************************************************/
1474 : /* GetGeoTransform() */
1475 : /************************************************************************/
1476 :
1477 : /**
1478 : * \brief Fetch the affine transformation coefficients.
1479 : *
1480 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
1481 : * space, and projection coordinates (Xp,Yp) space.
1482 : *
1483 : * \code
1484 : * Xp = gt[0] + P*gt[1] + L*gt[2];
1485 : * Yp = gt[3] + P*padfTransform[4] + L*gt[5];
1486 : * \endcode
1487 : *
1488 : * In a north up image, gt[1] is the pixel width, and
1489 : * gt[5] is the pixel height. The upper left corner of the
1490 : * upper left pixel is at position (gt[0],gt[3]).
1491 : *
1492 : * The default transform is (0,1,0,0,0,1) and should be returned even when
1493 : * a CE_Failure error is returned, such as for formats that don't support
1494 : * transformation to projection coordinates.
1495 : *
1496 : * This method does the same thing as the C GDALGetGeoTransform() function.
1497 : *
1498 : * @param gt an existing six double buffer into which the
1499 : * transformation will be placed.
1500 : *
1501 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
1502 : *
1503 : * @since 3.12
1504 : */
1505 :
1506 15792 : CPLErr GDALDataset::GetGeoTransform(GDALGeoTransform >) const
1507 :
1508 : {
1509 15792 : gt = GDALGeoTransform();
1510 :
1511 15792 : return CE_Failure;
1512 : }
1513 :
1514 : /************************************************************************/
1515 : /* GetGeoTransform() */
1516 : /************************************************************************/
1517 :
1518 : /**
1519 : * \brief Fetch the affine transformation coefficients.
1520 : *
1521 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
1522 : * space, and projection coordinates (Xp,Yp) space.
1523 : *
1524 : * \code
1525 : * Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
1526 : * Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
1527 : * \endcode
1528 : *
1529 : * In a north up image, padfTransform[1] is the pixel width, and
1530 : * padfTransform[5] is the pixel height. The upper left corner of the
1531 : * upper left pixel is at position (padfTransform[0],padfTransform[3]).
1532 : *
1533 : * The default transform is (0,1,0,0,0,1) and should be returned even when
1534 : * a CE_Failure error is returned, such as for formats that don't support
1535 : * transformation to projection coordinates.
1536 : *
1537 : * This method does the same thing as the C GDALGetGeoTransform() function.
1538 : *
1539 : * @param padfTransform an existing six double buffer into which the
1540 : * transformation will be placed.
1541 : *
1542 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
1543 : *
1544 : * @deprecated since 3.12. Use GetGeoTransform(GDALGeoTransform&) instead
1545 : */
1546 :
1547 2 : CPLErr GDALDataset::GetGeoTransform(double *padfTransform) const
1548 :
1549 : {
1550 2 : return GetGeoTransform(
1551 2 : *reinterpret_cast<GDALGeoTransform *>(padfTransform));
1552 : }
1553 :
1554 : /************************************************************************/
1555 : /* GDALGetGeoTransform() */
1556 : /************************************************************************/
1557 :
1558 : /**
1559 : * \brief Fetch the affine transformation coefficients.
1560 : *
1561 : * @see GDALDataset::GetGeoTransform()
1562 : */
1563 :
1564 9077 : CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1565 :
1566 : {
1567 9077 : VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1568 :
1569 18154 : return GDALDataset::FromHandle(hDS)->GetGeoTransform(
1570 9077 : *reinterpret_cast<GDALGeoTransform *>(padfTransform));
1571 : }
1572 :
1573 : /************************************************************************/
1574 : /* SetGeoTransform() */
1575 : /************************************************************************/
1576 :
1577 : /**
1578 : * \fn GDALDataset::SetGeoTransform(const GDALGeoTransform&)
1579 : * \brief Set the affine transformation coefficients.
1580 : *
1581 : * See GetGeoTransform() for details on the meaning of the padfTransform
1582 : * coefficients.
1583 : *
1584 : * This method does the same thing as the C GDALSetGeoTransform() function.
1585 : *
1586 : * @param gt the transformation coefficients to be written with the dataset.
1587 : *
1588 : * @return CE_None on success, or CE_Failure if this transform cannot be
1589 : * written.
1590 : *
1591 : * @since 3.12
1592 : */
1593 :
1594 0 : CPLErr GDALDataset::SetGeoTransform(CPL_UNUSED const GDALGeoTransform >)
1595 :
1596 : {
1597 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1598 0 : ReportError(CE_Failure, CPLE_NotSupported,
1599 : "SetGeoTransform() not supported for this dataset.");
1600 :
1601 0 : return CE_Failure;
1602 : }
1603 :
1604 : /************************************************************************/
1605 : /* SetGeoTransform() */
1606 : /************************************************************************/
1607 :
1608 : /**
1609 : * \brief Set the affine transformation coefficients.
1610 : *
1611 : * See GetGeoTransform() for details on the meaning of the padfTransform
1612 : * coefficients.
1613 : *
1614 : * This method does the same thing as the C GDALSetGeoTransform() function.
1615 : *
1616 : * @param padfTransform a six double buffer containing the transformation
1617 : * coefficients to be written with the dataset.
1618 : *
1619 : * @return CE_None on success, or CE_Failure if this transform cannot be
1620 : * written.
1621 : *
1622 : * @deprecated since 3.12. Use SetGeoTransform(const GDALGeoTransform&) instead
1623 : */
1624 30 : CPLErr GDALDataset::SetGeoTransform(const double *padfTransform)
1625 :
1626 : {
1627 30 : return SetGeoTransform(
1628 30 : *reinterpret_cast<const GDALGeoTransform *>(padfTransform));
1629 : }
1630 :
1631 : /************************************************************************/
1632 : /* GDALSetGeoTransform() */
1633 : /************************************************************************/
1634 :
1635 : /**
1636 : * \brief Set the affine transformation coefficients.
1637 : *
1638 : * @see GDALDataset::SetGeoTransform()
1639 : */
1640 :
1641 4145 : CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS,
1642 : const double *padfTransform)
1643 :
1644 : {
1645 4145 : VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1646 4145 : VALIDATE_POINTER1(padfTransform, "GDALSetGeoTransform", CE_Failure);
1647 :
1648 8290 : return GDALDataset::FromHandle(hDS)->SetGeoTransform(
1649 4145 : *reinterpret_cast<const GDALGeoTransform *>(padfTransform));
1650 : }
1651 :
1652 : /************************************************************************/
1653 : /* GetInternalHandle() */
1654 : /************************************************************************/
1655 :
1656 : /**
1657 : * \fn GDALDataset::GetInternalHandle(const char*)
1658 : * \brief Fetch a format specific internally meaningful handle.
1659 : *
1660 : * This method is the same as the C GDALGetInternalHandle() method.
1661 : *
1662 : * @param pszHandleName the handle name desired. The meaningful names
1663 : * will be specific to the file format.
1664 : *
1665 : * @return the desired handle value, or NULL if not recognized/supported.
1666 : */
1667 :
1668 191 : void *GDALDataset::GetInternalHandle(CPL_UNUSED const char *pszHandleName)
1669 :
1670 : {
1671 191 : return nullptr;
1672 : }
1673 :
1674 : /************************************************************************/
1675 : /* GDALGetInternalHandle() */
1676 : /************************************************************************/
1677 :
1678 : /**
1679 : * \brief Fetch a format specific internally meaningful handle.
1680 : *
1681 : * @see GDALDataset::GetInternalHandle()
1682 : */
1683 :
1684 61 : void *CPL_STDCALL GDALGetInternalHandle(GDALDatasetH hDS,
1685 : const char *pszRequest)
1686 :
1687 : {
1688 61 : VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
1689 :
1690 61 : return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
1691 : }
1692 :
1693 : /************************************************************************/
1694 : /* GetDriver() */
1695 : /************************************************************************/
1696 :
1697 : /**
1698 : * \brief Fetch the driver to which this dataset relates.
1699 : *
1700 : * This method is the same as the C GDALGetDatasetDriver() function.
1701 : *
1702 : * @return the driver on which the dataset was created with GDALOpen() or
1703 : * GDALCreate().
1704 : */
1705 :
1706 32079 : GDALDriver *GDALDataset::GetDriver()
1707 : {
1708 32079 : return poDriver;
1709 : }
1710 :
1711 : /************************************************************************/
1712 : /* GDALGetDatasetDriver() */
1713 : /************************************************************************/
1714 :
1715 : /**
1716 : * \brief Fetch the driver to which this dataset relates.
1717 : *
1718 : * @see GDALDataset::GetDriver()
1719 : */
1720 :
1721 2695 : GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)
1722 :
1723 : {
1724 2695 : VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1725 :
1726 : return static_cast<GDALDriverH>(
1727 2695 : GDALDataset::FromHandle(hDataset)->GetDriver());
1728 : }
1729 :
1730 : /************************************************************************/
1731 : /* Reference() */
1732 : /************************************************************************/
1733 :
1734 : /**
1735 : * \brief Add one to dataset reference count.
1736 : *
1737 : * The reference is one after instantiation.
1738 : *
1739 : * This method is the same as the C GDALReferenceDataset() function.
1740 : *
1741 : * @return the post-increment reference count.
1742 : */
1743 :
1744 258874 : int GDALDataset::Reference()
1745 : {
1746 258874 : return ++nRefCount;
1747 : }
1748 :
1749 : /************************************************************************/
1750 : /* GDALReferenceDataset() */
1751 : /************************************************************************/
1752 :
1753 : /**
1754 : * \brief Add one to dataset reference count.
1755 : *
1756 : * @see GDALDataset::Reference()
1757 : */
1758 :
1759 1277 : int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)
1760 :
1761 : {
1762 1277 : VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1763 :
1764 1277 : return GDALDataset::FromHandle(hDataset)->Reference();
1765 : }
1766 :
1767 : /************************************************************************/
1768 : /* Dereference() */
1769 : /************************************************************************/
1770 :
1771 : /**
1772 : * \brief Subtract one from dataset reference count.
1773 : *
1774 : * The reference is one after instantiation. Generally when the reference
1775 : * count has dropped to zero the dataset may be safely deleted (closed).
1776 : *
1777 : * This method is the same as the C GDALDereferenceDataset() function.
1778 : *
1779 : * @return the post-decrement reference count.
1780 : */
1781 :
1782 318449 : int GDALDataset::Dereference()
1783 : {
1784 318449 : return --nRefCount;
1785 : }
1786 :
1787 : /************************************************************************/
1788 : /* GDALDereferenceDataset() */
1789 : /************************************************************************/
1790 :
1791 : /**
1792 : * \brief Subtract one from dataset reference count.
1793 : *
1794 : * @see GDALDataset::Dereference()
1795 : */
1796 :
1797 57953 : int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)
1798 :
1799 : {
1800 57953 : VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1801 :
1802 57953 : return GDALDataset::FromHandle(hDataset)->Dereference();
1803 : }
1804 :
1805 : /************************************************************************/
1806 : /* ReleaseRef() */
1807 : /************************************************************************/
1808 :
1809 : /**
1810 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1811 : * @return TRUE if the object has been destroyed.
1812 : */
1813 :
1814 251566 : int GDALDataset::ReleaseRef()
1815 :
1816 : {
1817 251566 : if (Dereference() <= 0)
1818 : {
1819 7390 : nRefCount = 1;
1820 7390 : delete this;
1821 7390 : return TRUE;
1822 : }
1823 244176 : return FALSE;
1824 : }
1825 :
1826 : /************************************************************************/
1827 : /* GDALReleaseDataset() */
1828 : /************************************************************************/
1829 :
1830 : /**
1831 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1832 : *
1833 : * @see GDALDataset::ReleaseRef()
1834 : */
1835 :
1836 1514 : int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)
1837 :
1838 : {
1839 1514 : VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1840 :
1841 1514 : return GDALDataset::FromHandle(hDataset)->ReleaseRef();
1842 : }
1843 :
1844 : /************************************************************************/
1845 : /* GetShared() */
1846 : /************************************************************************/
1847 :
1848 : /**
1849 : * \brief Returns shared flag.
1850 : *
1851 : * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1852 : */
1853 :
1854 308420 : int GDALDataset::GetShared() const
1855 : {
1856 308420 : return bShared;
1857 : }
1858 :
1859 : /************************************************************************/
1860 : /* MarkAsShared() */
1861 : /************************************************************************/
1862 :
1863 : /**
1864 : * \brief Mark this dataset as available for sharing.
1865 : */
1866 :
1867 435 : void GDALDataset::MarkAsShared()
1868 :
1869 : {
1870 435 : CPLAssert(!bShared);
1871 :
1872 435 : bShared = true;
1873 435 : if (bIsInternal)
1874 23 : return;
1875 :
1876 412 : GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1877 :
1878 : // Insert the dataset in the set of shared opened datasets.
1879 824 : CPLMutexHolderD(&hDLMutex);
1880 412 : if (phSharedDatasetSet == nullptr)
1881 290 : phSharedDatasetSet =
1882 290 : CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1883 : GDALSharedDatasetFreeFunc);
1884 :
1885 : SharedDatasetCtxt *psStruct =
1886 412 : static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1887 412 : psStruct->poDS = this;
1888 412 : psStruct->nPID = nPID;
1889 412 : psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
1890 412 : psStruct->pszDescription = CPLStrdup(GetDescription());
1891 : std::string osConcatenatedOpenOptions =
1892 824 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
1893 412 : psStruct->pszConcatenatedOpenOptions =
1894 412 : CPLStrdup(osConcatenatedOpenOptions.c_str());
1895 412 : if (CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
1896 : {
1897 1 : GDALSharedDatasetFreeFunc(psStruct);
1898 1 : ReportError(CE_Failure, CPLE_AppDefined,
1899 : "An existing shared dataset already has this description. "
1900 : "This should not happen.");
1901 : }
1902 : else
1903 : {
1904 411 : CPLHashSetInsert(phSharedDatasetSet, psStruct);
1905 :
1906 411 : (*poAllDatasetMap)[this] = nPID;
1907 : }
1908 : }
1909 :
1910 : /************************************************************************/
1911 : /* MarkSuppressOnClose() */
1912 : /************************************************************************/
1913 :
1914 : /** Set that the dataset must be deleted on close.
1915 : *
1916 : * This is the same as C function GDALDatasetMarkSuppressOnClose()
1917 : */
1918 1195 : void GDALDataset::MarkSuppressOnClose()
1919 : {
1920 1195 : bSuppressOnClose = true;
1921 1195 : }
1922 :
1923 : /************************************************************************/
1924 : /* GDALDatasetMarkSuppressOnClose() */
1925 : /************************************************************************/
1926 :
1927 : /** Set that the dataset must be deleted on close.
1928 : *
1929 : * This is the same as C++ method GDALDataset::MarkSuppressOnClose()
1930 : *
1931 : * @since GDAL 3.12
1932 : */
1933 :
1934 4 : void GDALDatasetMarkSuppressOnClose(GDALDatasetH hDS)
1935 : {
1936 4 : VALIDATE_POINTER0(hDS, "GDALDatasetMarkSuppressOnClose");
1937 :
1938 4 : return GDALDataset::FromHandle(hDS)->MarkSuppressOnClose();
1939 : }
1940 :
1941 : /************************************************************************/
1942 : /* UnMarkSuppressOnClose() */
1943 : /************************************************************************/
1944 :
1945 : /** Remove the flag requesting the dataset to be deleted on close. */
1946 684 : void GDALDataset::UnMarkSuppressOnClose()
1947 : {
1948 684 : bSuppressOnClose = false;
1949 684 : }
1950 :
1951 : /************************************************************************/
1952 : /* CleanupPostFileClosing() */
1953 : /************************************************************************/
1954 :
1955 : /** This method should be called by driver implementations in their destructor,
1956 : * after having closed all files, but before having freed resources that
1957 : * are needed for their GetFileList() implementation.
1958 : * This is used to implement MarkSuppressOnClose behavior.
1959 : */
1960 259 : void GDALDataset::CleanupPostFileClosing()
1961 : {
1962 259 : if (IsMarkedSuppressOnClose())
1963 : {
1964 1 : char **papszFileList = GetFileList();
1965 3 : for (int i = 0; papszFileList && papszFileList[i]; ++i)
1966 2 : VSIUnlink(papszFileList[i]);
1967 1 : CSLDestroy(papszFileList);
1968 : }
1969 259 : }
1970 :
1971 : /************************************************************************/
1972 : /* GetGCPCount() */
1973 : /************************************************************************/
1974 :
1975 : /**
1976 : * \brief Get number of GCPs.
1977 : *
1978 : * This method is the same as the C function GDALGetGCPCount().
1979 : *
1980 : * @return number of GCPs for this dataset. Zero if there are none.
1981 : */
1982 :
1983 16331 : int GDALDataset::GetGCPCount()
1984 : {
1985 16331 : return 0;
1986 : }
1987 :
1988 : /************************************************************************/
1989 : /* GDALGetGCPCount() */
1990 : /************************************************************************/
1991 :
1992 : /**
1993 : * \brief Get number of GCPs.
1994 : *
1995 : * @see GDALDataset::GetGCPCount()
1996 : */
1997 :
1998 2141 : int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)
1999 :
2000 : {
2001 2141 : VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
2002 :
2003 2141 : return GDALDataset::FromHandle(hDS)->GetGCPCount();
2004 : }
2005 :
2006 : /************************************************************************/
2007 : /* GetGCPProjection() */
2008 : /************************************************************************/
2009 :
2010 : /**
2011 : * \brief Get output projection for GCPs.
2012 : *
2013 : * This method is the same as the C function GDALGetGCPProjection().
2014 : *
2015 : * The projection string follows the normal rules from GetProjectionRef().
2016 : *
2017 : * \note Starting with GDAL 3.0, this is a compatibility layer around
2018 : * GetGCPSpatialRef()
2019 : *
2020 : * @return internal projection string or "" if there are no GCPs.
2021 : * It should not be altered, freed or expected to last for long.
2022 : */
2023 :
2024 918 : const char *GDALDataset::GetGCPProjection() const
2025 : {
2026 918 : const auto poSRS = GetGCPSpatialRef();
2027 918 : if (!poSRS || !m_poPrivate)
2028 : {
2029 582 : return "";
2030 : }
2031 336 : char *pszWKT = nullptr;
2032 336 : poSRS->exportToWkt(&pszWKT);
2033 336 : if (!pszWKT)
2034 : {
2035 0 : return "";
2036 : }
2037 :
2038 : // If called on a thread-safe dataset, we might be called by several
2039 : // threads, so make sure our accesses to m_pszWKTCached are protected
2040 : // by a mutex.
2041 672 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
2042 336 : if (m_poPrivate->m_pszWKTGCPCached &&
2043 256 : strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0)
2044 : {
2045 256 : CPLFree(pszWKT);
2046 256 : return m_poPrivate->m_pszWKTGCPCached;
2047 : }
2048 80 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
2049 80 : m_poPrivate->m_pszWKTGCPCached = pszWKT;
2050 80 : return m_poPrivate->m_pszWKTGCPCached;
2051 : }
2052 :
2053 : /************************************************************************/
2054 : /* GetGCPSpatialRef() */
2055 : /************************************************************************/
2056 :
2057 : /**
2058 : * \brief Get output spatial reference system for GCPs.
2059 : *
2060 : * Same as the C function GDALGetGCPSpatialRef().
2061 : *
2062 : * When a SRS is not available, null is returned. If used on
2063 : * a dataset where there is a geotransform, and not GCPs, this method returns
2064 : * null. Use GetSpatialRef() instead.
2065 : *
2066 : * @since GDAL 3.0
2067 : *
2068 : * @return a pointer to an internal object. It should not be altered or freed.
2069 : * Its lifetime will be the one of the dataset object, or until the next
2070 : * call to this method.
2071 : */
2072 :
2073 39 : const OGRSpatialReference *GDALDataset::GetGCPSpatialRef() const
2074 : {
2075 39 : return nullptr;
2076 : }
2077 :
2078 : /************************************************************************/
2079 : /* GDALGetGCPSpatialRef() */
2080 : /************************************************************************/
2081 :
2082 : /**
2083 : * \brief Get output spatial reference system for GCPs.
2084 : *
2085 : * @since GDAL 3.0
2086 : *
2087 : * @see GDALDataset::GetGCPSpatialRef()
2088 : */
2089 :
2090 468 : OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)
2091 :
2092 : {
2093 468 : VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
2094 :
2095 468 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
2096 468 : GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
2097 : }
2098 :
2099 : /************************************************************************/
2100 : /* GDALGetGCPProjection() */
2101 : /************************************************************************/
2102 :
2103 : /**
2104 : * \brief Get output projection for GCPs.
2105 : *
2106 : * @see GDALDataset::GetGCPProjection()
2107 : */
2108 :
2109 848 : const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)
2110 :
2111 : {
2112 848 : VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
2113 :
2114 848 : return GDALDataset::FromHandle(hDS)->GetGCPProjection();
2115 : }
2116 :
2117 : /************************************************************************/
2118 : /* GetGCPs() */
2119 : /************************************************************************/
2120 :
2121 : /**
2122 : * \brief Fetch GCPs.
2123 : *
2124 : * This method is the same as the C function GDALGetGCPs().
2125 : *
2126 : * @return pointer to internal GCP structure list. It should not be modified,
2127 : * and may change on the next GDAL call.
2128 : */
2129 :
2130 10 : const GDAL_GCP *GDALDataset::GetGCPs()
2131 : {
2132 10 : return nullptr;
2133 : }
2134 :
2135 : /************************************************************************/
2136 : /* GDALGetGCPs() */
2137 : /************************************************************************/
2138 :
2139 : /**
2140 : * \brief Fetch GCPs.
2141 : *
2142 : * @see GDALDataset::GetGCPs()
2143 : */
2144 :
2145 578 : const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)
2146 :
2147 : {
2148 578 : VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
2149 :
2150 578 : return GDALDataset::FromHandle(hDS)->GetGCPs();
2151 : }
2152 :
2153 : /************************************************************************/
2154 : /* SetGCPs() */
2155 : /************************************************************************/
2156 :
2157 : /**
2158 : * \brief Assign GCPs.
2159 : *
2160 : * This method is the same as the C function GDALSetGCPs().
2161 : *
2162 : * This method assigns the passed set of GCPs to this dataset, as well as
2163 : * setting their coordinate system. Internally copies are made of the
2164 : * coordinate system and list of points, so the caller remains responsible for
2165 : * deallocating these arguments if appropriate.
2166 : *
2167 : * Most formats do not support setting of GCPs, even formats that can
2168 : * handle GCPs. These formats will return CE_Failure.
2169 : *
2170 : * \note Startig with GDAL 3.0, this is a compatibility layer around
2171 : * SetGCPs(int, const GDAL_GCP*, const char*)
2172 : *
2173 : * @param nGCPCount number of GCPs being assigned.
2174 : *
2175 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2176 : *
2177 : * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
2178 : * GCP output coordinates. This parameter should be "" if no output coordinate
2179 : * system is known.
2180 : *
2181 : * @return CE_None on success, CE_Failure on failure (including if action is
2182 : * not supported for this format).
2183 : */
2184 :
2185 52 : CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,
2186 : const char *pszGCPProjection)
2187 :
2188 : {
2189 52 : if (pszGCPProjection && pszGCPProjection[0] != '\0')
2190 : {
2191 66 : OGRSpatialReference oSRS;
2192 33 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
2193 33 : if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)
2194 : {
2195 0 : return CE_Failure;
2196 : }
2197 33 : return SetGCPs(nGCPCount, pasGCPList, &oSRS);
2198 : }
2199 : else
2200 : {
2201 19 : return SetGCPs(nGCPCount, pasGCPList,
2202 19 : static_cast<const OGRSpatialReference *>(nullptr));
2203 : }
2204 : }
2205 :
2206 : /************************************************************************/
2207 : /* SetGCPs() */
2208 : /************************************************************************/
2209 :
2210 : /**
2211 : * \brief Assign GCPs.
2212 : *
2213 : * This method is the same as the C function GDALSetGCPs().
2214 : *
2215 : * This method assigns the passed set of GCPs to this dataset, as well as
2216 : * setting their coordinate system. Internally copies are made of the
2217 : * coordinate system and list of points, so the caller remains responsible for
2218 : * deallocating these arguments if appropriate.
2219 : *
2220 : * Most formats do not support setting of GCPs, even formats that can
2221 : * handle GCPs. These formats will return CE_Failure.
2222 : *
2223 : * @since GDAL 3.0
2224 : *
2225 : * @param nGCPCount number of GCPs being assigned.
2226 : *
2227 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2228 : *
2229 : * @param poGCP_SRS the new coordinate reference system to assign for the
2230 : * GCP output coordinates. This parameter should be null if no output
2231 : * coordinate system is known.
2232 : *
2233 : * @return CE_None on success, CE_Failure on failure (including if action is
2234 : * not supported for this format).
2235 : */
2236 :
2237 1 : CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,
2238 : CPL_UNUSED const GDAL_GCP *pasGCPList,
2239 : CPL_UNUSED const OGRSpatialReference *poGCP_SRS)
2240 :
2241 : {
2242 1 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
2243 1 : ReportError(CE_Failure, CPLE_NotSupported,
2244 : "Dataset does not support the SetGCPs() method.");
2245 :
2246 1 : return CE_Failure;
2247 : }
2248 :
2249 : /************************************************************************/
2250 : /* GDALSetGCPs() */
2251 : /************************************************************************/
2252 :
2253 : /**
2254 : * \brief Assign GCPs.
2255 : *
2256 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
2257 : */
2258 :
2259 29 : CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,
2260 : const GDAL_GCP *pasGCPList,
2261 : const char *pszGCPProjection)
2262 :
2263 : {
2264 29 : VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
2265 :
2266 29 : return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,
2267 29 : pszGCPProjection);
2268 : }
2269 :
2270 : /************************************************************************/
2271 : /* GDALSetGCPs2() */
2272 : /************************************************************************/
2273 :
2274 : /**
2275 : * \brief Assign GCPs.
2276 : *
2277 : * @since GDAL 3.0
2278 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
2279 : */
2280 :
2281 9 : CPLErr GDALSetGCPs2(GDALDatasetH hDS, int nGCPCount, const GDAL_GCP *pasGCPList,
2282 : OGRSpatialReferenceH hSRS)
2283 :
2284 : {
2285 9 : VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
2286 :
2287 18 : return GDALDataset::FromHandle(hDS)->SetGCPs(
2288 9 : nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
2289 : }
2290 :
2291 : /************************************************************************/
2292 : /* BuildOverviews() */
2293 : /************************************************************************/
2294 :
2295 : /**
2296 : * \brief Build raster overview(s)
2297 : *
2298 : * If the operation is not supported for the indicated dataset, then
2299 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
2300 : * CPLE_NotSupported.
2301 : *
2302 : * Depending on the actual file format, all overviews level can be also
2303 : * deleted by specifying nOverviews == 0. This works at least for external
2304 : * overviews (.ovr), TIFF internal overviews, etc.
2305 : *
2306 : * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
2307 : * to "ALL_CPUS" or a integer value to specify the number of threads to use for
2308 : * overview computation.
2309 : *
2310 : * This method is the same as the C function GDALBuildOverviewsEx().
2311 : *
2312 : * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
2313 : * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
2314 : * or "NONE" controlling the downsampling method applied.
2315 : * @param nOverviews number of overviews to build, or 0 to clean overviews.
2316 : * @param panOverviewList the list of overview decimation factors (positive
2317 : * integers, normally larger or equal to 2) to build, or
2318 : * NULL if nOverviews == 0.
2319 : * @param nListBands number of bands to build overviews for in panBandList.
2320 : * Build for all bands if this is 0.
2321 : * @param panBandList list of band numbers.
2322 : * @param pfnProgress a function to call to report progress, or NULL.
2323 : * @param pProgressData application data to pass to the progress function.
2324 : * @param papszOptions (GDAL >= 3.6) NULL terminated list of options as
2325 : * key=value pairs, or NULL.
2326 : * Possible keys are the ones returned by
2327 : * GetDriver()->GetMetadataItem(GDAL_DMD_OVERVIEW_CREATIONOPTIONLIST)
2328 : *
2329 : * @return CE_None on success or CE_Failure if the operation doesn't work.
2330 : *
2331 : * For example, to build overview level 2, 4 and 8 on all bands the following
2332 : * call could be made:
2333 : * \code{.cpp}
2334 : * int anOverviewList[3] = { 2, 4, 8 };
2335 : *
2336 : * poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
2337 : * GDALDummyProgress, nullptr );
2338 : * \endcode
2339 : *
2340 : * @see GDALRegenerateOverviewsEx()
2341 : */
2342 :
2343 744 : CPLErr GDALDataset::BuildOverviews(const char *pszResampling, int nOverviews,
2344 : const int *panOverviewList, int nListBands,
2345 : const int *panBandList,
2346 : GDALProgressFunc pfnProgress,
2347 : void *pProgressData,
2348 : CSLConstList papszOptions)
2349 : {
2350 744 : int *panAllBandList = nullptr;
2351 :
2352 1488 : CPLStringList aosOptions(papszOptions);
2353 744 : if (poDriver && !aosOptions.empty())
2354 : {
2355 : const char *pszOptionList =
2356 28 : poDriver->GetMetadataItem(GDAL_DMD_OVERVIEW_CREATIONOPTIONLIST);
2357 28 : if (pszOptionList)
2358 : {
2359 : // For backwards compatibility
2360 28 : if (const char *opt = aosOptions.FetchNameValue("USE_RRD"))
2361 : {
2362 4 : if (strstr(pszOptionList, "<Value>RRD</Value>") &&
2363 2 : aosOptions.FetchNameValue("LOCATION") == nullptr)
2364 : {
2365 2 : if (CPLTestBool(opt))
2366 2 : aosOptions.SetNameValue("LOCATION", "RRD");
2367 2 : aosOptions.SetNameValue("USE_RRD", nullptr);
2368 : }
2369 : }
2370 28 : if (const char *opt =
2371 28 : aosOptions.FetchNameValue("VRT_VIRTUAL_OVERVIEWS"))
2372 : {
2373 3 : if (strstr(pszOptionList, "VIRTUAL"))
2374 : {
2375 3 : aosOptions.SetNameValue("VIRTUAL", opt);
2376 3 : aosOptions.SetNameValue("VRT_VIRTUAL_OVERVIEWS", nullptr);
2377 : }
2378 : }
2379 :
2380 76 : for (const auto &[pszKey, pszValue] :
2381 104 : cpl::IterateNameValue(papszOptions))
2382 : {
2383 38 : if (cpl::ends_with(std::string_view(pszKey), "_OVERVIEW"))
2384 : {
2385 : aosOptions.SetNameValue(
2386 16 : std::string(pszKey)
2387 16 : .substr(0, strlen(pszKey) - strlen("_OVERVIEW"))
2388 : .c_str(),
2389 16 : pszValue);
2390 8 : aosOptions.SetNameValue(pszKey, nullptr);
2391 : }
2392 : }
2393 :
2394 56 : CPLString osDriver;
2395 28 : osDriver.Printf("driver %s", poDriver->GetDescription());
2396 28 : GDALValidateOptions(pszOptionList, aosOptions.List(),
2397 : "overview creation option", osDriver);
2398 : }
2399 : }
2400 :
2401 744 : if (nListBands == 0)
2402 : {
2403 732 : nListBands = GetRasterCount();
2404 : panAllBandList =
2405 732 : static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
2406 67458 : for (int i = 0; i < nListBands; ++i)
2407 66726 : panAllBandList[i] = i + 1;
2408 :
2409 732 : panBandList = panAllBandList;
2410 : }
2411 :
2412 744 : if (pfnProgress == nullptr)
2413 709 : pfnProgress = GDALDummyProgress;
2414 :
2415 1819 : for (int i = 0; i < nOverviews; ++i)
2416 : {
2417 1076 : if (panOverviewList[i] <= 0)
2418 : {
2419 1 : CPLError(CE_Failure, CPLE_IllegalArg,
2420 : "panOverviewList[%d] = %d is invalid. It must be a "
2421 : "positive value",
2422 1 : i, panOverviewList[i]);
2423 1 : CPLFree(panAllBandList);
2424 1 : return CE_Failure;
2425 : }
2426 : }
2427 :
2428 743 : const CPLErr eErr = IBuildOverviews(
2429 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2430 743 : pfnProgress, pProgressData, aosOptions.List());
2431 :
2432 743 : if (panAllBandList != nullptr)
2433 730 : CPLFree(panAllBandList);
2434 :
2435 743 : return eErr;
2436 : }
2437 :
2438 : /************************************************************************/
2439 : /* GDALBuildOverviews() */
2440 : /************************************************************************/
2441 :
2442 : /**
2443 : * \brief Build raster overview(s)
2444 : *
2445 : * @see GDALDataset::BuildOverviews() and GDALBuildOverviews()
2446 : */
2447 :
2448 27 : CPLErr CPL_STDCALL GDALBuildOverviews(GDALDatasetH hDataset,
2449 : const char *pszResampling, int nOverviews,
2450 : const int *panOverviewList,
2451 : int nListBands, const int *panBandList,
2452 : GDALProgressFunc pfnProgress,
2453 : void *pProgressData)
2454 :
2455 : {
2456 27 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2457 :
2458 27 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2459 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2460 27 : pfnProgress, pProgressData, nullptr);
2461 : }
2462 :
2463 : /************************************************************************/
2464 : /* GDALBuildOverviews() */
2465 : /************************************************************************/
2466 :
2467 : /**
2468 : * \brief Build raster overview(s)
2469 : *
2470 : * @see GDALDataset::BuildOverviews()
2471 : * @since GDAL 3.6
2472 : */
2473 :
2474 : CPLErr CPL_STDCALL
2475 696 : GDALBuildOverviewsEx(GDALDatasetH hDataset, const char *pszResampling,
2476 : int nOverviews, const int *panOverviewList, int nListBands,
2477 : const int *panBandList, GDALProgressFunc pfnProgress,
2478 : void *pProgressData, CSLConstList papszOptions)
2479 :
2480 : {
2481 696 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2482 :
2483 696 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2484 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2485 696 : pfnProgress, pProgressData, papszOptions);
2486 : }
2487 :
2488 : /************************************************************************/
2489 : /* IBuildOverviews() */
2490 : /* */
2491 : /* Default implementation. */
2492 : /************************************************************************/
2493 :
2494 : //! @cond Doxygen_Suppress
2495 196 : CPLErr GDALDataset::IBuildOverviews(const char *pszResampling, int nOverviews,
2496 : const int *panOverviewList, int nListBands,
2497 : const int *panBandList,
2498 : GDALProgressFunc pfnProgress,
2499 : void *pProgressData,
2500 : CSLConstList papszOptions)
2501 :
2502 : {
2503 196 : if (oOvManager.IsInitialized())
2504 195 : return oOvManager.BuildOverviews(
2505 : nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2506 195 : panBandList, pfnProgress, pProgressData, papszOptions);
2507 : else
2508 : {
2509 1 : ReportError(CE_Failure, CPLE_NotSupported,
2510 : "BuildOverviews() not supported for this dataset.");
2511 :
2512 1 : return CE_Failure;
2513 : }
2514 : }
2515 :
2516 : //! @endcond
2517 :
2518 : /************************************************************************/
2519 : /* AddOverviews() */
2520 : /* */
2521 : /* Default implementation. */
2522 : /************************************************************************/
2523 :
2524 : /**
2525 : * \brief Add overview from existing dataset(s)
2526 : *
2527 : * This function creates new overview levels or refresh existing one from
2528 : * the list of provided overview datasets.
2529 : * Source overviews may come from any GDAL supported format, provided they
2530 : * have the same number of bands and geospatial extent than the target
2531 : * dataset.
2532 : *
2533 : * If the operation is not supported for the indicated dataset, then
2534 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
2535 : * CPLE_NotSupported.
2536 : *
2537 : * At time of writing, this method is only implemented for internal overviews
2538 : * of GeoTIFF datasets and external overviews in GeoTIFF format.
2539 : *
2540 : * @param apoSrcOvrDS Vector of source overviews.
2541 : * @param pfnProgress a function to call to report progress, or NULL.
2542 : * @param pProgressData application data to pass to the progress function.
2543 : * @param papszOptions NULL terminated list of options as
2544 : * key=value pairs, or NULL. Possible keys are the
2545 : * ones returned by
2546 : * GetDriver()->GetMetadataItem(GDAL_DMD_OVERVIEW_CREATIONOPTIONLIST)
2547 : *
2548 : * @return CE_None on success or CE_Failure if the operation doesn't work.
2549 : * @since 3.12
2550 : */
2551 5 : CPLErr GDALDataset::AddOverviews(const std::vector<GDALDataset *> &apoSrcOvrDS,
2552 : GDALProgressFunc pfnProgress,
2553 : void *pProgressData, CSLConstList papszOptions)
2554 : {
2555 5 : if (oOvManager.IsInitialized())
2556 : {
2557 4 : return oOvManager.AddOverviews(nullptr, apoSrcOvrDS, pfnProgress,
2558 4 : pProgressData, papszOptions);
2559 : }
2560 : else
2561 : {
2562 1 : ReportError(CE_Failure, CPLE_NotSupported,
2563 : "AddOverviews() not supported for this dataset.");
2564 1 : return CE_Failure;
2565 : }
2566 : }
2567 :
2568 : /************************************************************************/
2569 : /* IRasterIO() */
2570 : /* */
2571 : /* The default implementation of IRasterIO() is, in the general */
2572 : /* case to pass the request off to each band objects rasterio */
2573 : /* methods with appropriate arguments. In some cases, it might */
2574 : /* choose instead the BlockBasedRasterIO() implementation. */
2575 : /************************************************************************/
2576 :
2577 : //! @cond Doxygen_Suppress
2578 444590 : CPLErr GDALDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2579 : int nXSize, int nYSize, void *pData,
2580 : int nBufXSize, int nBufYSize,
2581 : GDALDataType eBufType, int nBandCount,
2582 : BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,
2583 : GSpacing nLineSpace, GSpacing nBandSpace,
2584 : GDALRasterIOExtraArg *psExtraArg)
2585 :
2586 : {
2587 444590 : const char *pszInterleave = nullptr;
2588 :
2589 444590 : CPLAssert(nullptr != pData);
2590 :
2591 444590 : const bool bHasSubpixelShift =
2592 446846 : psExtraArg->bFloatingPointWindowValidity &&
2593 445361 : psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2594 771 : (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2595 :
2596 444476 : if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&
2597 70375 : nBandCount > 1 &&
2598 70374 : (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2599 889067 : nullptr &&
2600 67305 : EQUAL(pszInterleave, "PIXEL"))
2601 : {
2602 64073 : return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2603 : nBufXSize, nBufYSize, eBufType, nBandCount,
2604 : panBandMap, nPixelSpace, nLineSpace,
2605 64072 : nBandSpace, psExtraArg);
2606 : }
2607 :
2608 380519 : if (eRWFlag == GF_Read &&
2609 200984 : (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2610 200220 : psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2611 200219 : psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2612 200984 : psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2613 927 : !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)
2614 : {
2615 906 : if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())
2616 : {
2617 698 : int bTried = FALSE;
2618 698 : const CPLErr eErr = TryOverviewRasterIO(
2619 : eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
2620 : nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
2621 : nLineSpace, nBandSpace, psExtraArg, &bTried);
2622 698 : if (bTried)
2623 1 : return eErr;
2624 : }
2625 :
2626 905 : GDALDataType eFirstBandDT = GDT_Unknown;
2627 905 : int nFirstMaskFlags = 0;
2628 905 : GDALRasterBand *poFirstMaskBand = nullptr;
2629 905 : int nOKBands = 0;
2630 :
2631 : // Check if bands share the same mask band
2632 2831 : for (int i = 0; i < nBandCount; ++i)
2633 : {
2634 2560 : GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2635 4455 : if ((nBufXSize < nXSize || nBufYSize < nYSize) &&
2636 1893 : poBand->GetOverviewCount())
2637 : {
2638 : // Could be improved to select the appropriate overview.
2639 3 : break;
2640 : }
2641 2559 : if (poBand->GetColorTable() != nullptr)
2642 : {
2643 0 : break;
2644 : }
2645 2562 : const GDALDataType eDT = poBand->GetRasterDataType();
2646 2561 : if (GDALDataTypeIsComplex(eDT))
2647 : {
2648 30 : break;
2649 : }
2650 2529 : if (i == 0)
2651 : {
2652 871 : eFirstBandDT = eDT;
2653 871 : nFirstMaskFlags = poBand->GetMaskFlags();
2654 875 : if (nFirstMaskFlags == GMF_NODATA)
2655 : {
2656 : // The dataset-level resampling code is not ready for nodata
2657 : // Fallback to band-level resampling
2658 10 : break;
2659 : }
2660 865 : poFirstMaskBand = poBand->GetMaskBand();
2661 : }
2662 : else
2663 : {
2664 1658 : if (eDT != eFirstBandDT)
2665 : {
2666 0 : break;
2667 : }
2668 1658 : int nMaskFlags = poBand->GetMaskFlags();
2669 1660 : if (nMaskFlags == GMF_NODATA)
2670 : {
2671 : // The dataset-level resampling code is not ready for nodata
2672 : // Fallback to band-level resampling
2673 0 : break;
2674 : }
2675 1660 : GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2676 1660 : if (nFirstMaskFlags == GMF_ALL_VALID &&
2677 : nMaskFlags == GMF_ALL_VALID)
2678 : {
2679 : // Ok.
2680 : }
2681 1015 : else if (poFirstMaskBand == poMaskBand)
2682 : {
2683 : // Ok.
2684 : }
2685 : else
2686 : {
2687 596 : break;
2688 : }
2689 : }
2690 :
2691 1926 : ++nOKBands;
2692 : }
2693 :
2694 910 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2695 910 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2696 :
2697 910 : CPLErr eErr = CE_None;
2698 910 : if (nOKBands > 0)
2699 : {
2700 865 : if (nOKBands < nBandCount)
2701 : {
2702 596 : psExtraArg->pfnProgress = GDALScaledProgress;
2703 1192 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2704 596 : 0.0, static_cast<double>(nOKBands) / nBandCount,
2705 : pfnProgressGlobal, pProgressDataGlobal);
2706 596 : if (psExtraArg->pProgressData == nullptr)
2707 207 : psExtraArg->pfnProgress = nullptr;
2708 : }
2709 :
2710 865 : eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2711 : pData, nBufXSize, nBufYSize, eBufType,
2712 : nOKBands, panBandMap, nPixelSpace,
2713 : nLineSpace, nBandSpace, psExtraArg);
2714 :
2715 865 : if (nOKBands < nBandCount)
2716 : {
2717 596 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2718 : }
2719 : }
2720 910 : if (eErr == CE_None && nOKBands < nBandCount)
2721 : {
2722 636 : if (nOKBands > 0)
2723 : {
2724 593 : psExtraArg->pfnProgress = GDALScaledProgress;
2725 1186 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2726 593 : static_cast<double>(nOKBands) / nBandCount, 1.0,
2727 : pfnProgressGlobal, pProgressDataGlobal);
2728 593 : if (psExtraArg->pProgressData == nullptr)
2729 204 : psExtraArg->pfnProgress = nullptr;
2730 : }
2731 1272 : eErr = BandBasedRasterIO(
2732 : eRWFlag, nXOff, nYOff, nXSize, nYSize,
2733 636 : static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,
2734 : nBufYSize, eBufType, nBandCount - nOKBands,
2735 636 : panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,
2736 : psExtraArg);
2737 636 : if (nOKBands > 0)
2738 : {
2739 593 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2740 : }
2741 : }
2742 :
2743 908 : psExtraArg->pfnProgress = pfnProgressGlobal;
2744 908 : psExtraArg->pProgressData = pProgressDataGlobal;
2745 :
2746 908 : return eErr;
2747 : }
2748 :
2749 379613 : return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2750 : nBufXSize, nBufYSize, eBufType, nBandCount,
2751 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2752 379610 : psExtraArg);
2753 : }
2754 :
2755 : //! @endcond
2756 :
2757 : /************************************************************************/
2758 : /* BandBasedRasterIO() */
2759 : /* */
2760 : /* Pass the request off to each band objects rasterio methods with */
2761 : /* appropriate arguments. */
2762 : /************************************************************************/
2763 :
2764 : //! @cond Doxygen_Suppress
2765 646961 : CPLErr GDALDataset::BandBasedRasterIO(
2766 : GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
2767 : void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
2768 : int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
2769 : GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
2770 :
2771 : {
2772 : int iBandIndex;
2773 646961 : CPLErr eErr = CE_None;
2774 :
2775 646961 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2776 646961 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2777 :
2778 1667940 : for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
2779 : ++iBandIndex)
2780 : {
2781 1020980 : GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2782 :
2783 1020980 : if (poBand == nullptr)
2784 : {
2785 0 : eErr = CE_Failure;
2786 0 : break;
2787 : }
2788 :
2789 1020980 : GByte *pabyBandData =
2790 1020980 : static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2791 :
2792 1020980 : if (nBandCount > 1)
2793 : {
2794 551564 : psExtraArg->pfnProgress = GDALScaledProgress;
2795 1103120 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2796 : 1.0 * iBandIndex / nBandCount,
2797 551564 : 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2798 : pProgressDataGlobal);
2799 551559 : if (psExtraArg->pProgressData == nullptr)
2800 548543 : psExtraArg->pfnProgress = nullptr;
2801 : }
2802 :
2803 2041950 : eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2804 : pabyBandData, nBufXSize, nBufYSize, eBufType,
2805 1020970 : nPixelSpace, nLineSpace, psExtraArg);
2806 :
2807 1020980 : if (nBandCount > 1)
2808 551568 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2809 : }
2810 :
2811 646959 : psExtraArg->pfnProgress = pfnProgressGlobal;
2812 646959 : psExtraArg->pProgressData = pProgressDataGlobal;
2813 :
2814 646959 : return eErr;
2815 : }
2816 :
2817 : //! @endcond
2818 :
2819 : /************************************************************************/
2820 : /* ValidateRasterIOOrAdviseReadParameters() */
2821 : /************************************************************************/
2822 :
2823 : //! @cond Doxygen_Suppress
2824 743986 : CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
2825 : const char *pszCallingFunc, int *pbStopProcessingOnCENone, int nXOff,
2826 : int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize,
2827 : int nBandCount, const int *panBandMap)
2828 : {
2829 :
2830 : /* -------------------------------------------------------------------- */
2831 : /* Some size values are "noop". Lets just return to avoid */
2832 : /* stressing lower level functions. */
2833 : /* -------------------------------------------------------------------- */
2834 743986 : if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)
2835 : {
2836 27 : CPLDebug("GDAL",
2837 : "%s skipped for odd window or buffer size.\n"
2838 : " Window = (%d,%d)x%dx%d\n"
2839 : " Buffer = %dx%d",
2840 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2841 : nBufYSize);
2842 :
2843 24 : *pbStopProcessingOnCENone = TRUE;
2844 24 : return CE_None;
2845 : }
2846 :
2847 743959 : CPLErr eErr = CE_None;
2848 743959 : *pbStopProcessingOnCENone = FALSE;
2849 :
2850 743959 : if (nXOff < 0 || nXOff > INT_MAX - nXSize ||
2851 743956 : nXOff + nXSize > nRasterXSize || nYOff < 0 ||
2852 743958 : nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)
2853 : {
2854 2 : ReportError(CE_Failure, CPLE_IllegalArg,
2855 : "Access window out of range in %s. Requested "
2856 : "(%d,%d) of size %dx%d on raster of %dx%d.",
2857 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
2858 : nRasterYSize);
2859 2 : eErr = CE_Failure;
2860 : }
2861 :
2862 743959 : if (panBandMap == nullptr && nBandCount > GetRasterCount())
2863 : {
2864 0 : ReportError(CE_Failure, CPLE_IllegalArg,
2865 : "%s: nBandCount cannot be greater than %d", pszCallingFunc,
2866 : GetRasterCount());
2867 0 : eErr = CE_Failure;
2868 : }
2869 :
2870 2224230 : for (int i = 0; i < nBandCount && eErr == CE_None; ++i)
2871 : {
2872 1480270 : int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2873 1480270 : if (iBand < 1 || iBand > GetRasterCount())
2874 : {
2875 3 : ReportError(
2876 : CE_Failure, CPLE_IllegalArg,
2877 : "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
2878 : pszCallingFunc, i, iBand);
2879 3 : eErr = CE_Failure;
2880 : }
2881 :
2882 1480270 : if (eErr == CE_None && GetRasterBand(iBand) == nullptr)
2883 : {
2884 0 : ReportError(
2885 : CE_Failure, CPLE_IllegalArg,
2886 : "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
2887 : pszCallingFunc, i, iBand);
2888 0 : eErr = CE_Failure;
2889 : }
2890 : }
2891 :
2892 743958 : return eErr;
2893 : }
2894 :
2895 : //! @endcond
2896 :
2897 : /************************************************************************/
2898 : /* RasterIO() */
2899 : /************************************************************************/
2900 :
2901 : /**
2902 : * \brief Read/write a region of image data from multiple bands.
2903 : *
2904 : * This method allows reading a region of one or more GDALRasterBands from
2905 : * this dataset into a buffer, or writing data from a buffer into a region
2906 : * of the GDALRasterBands. It automatically takes care of data type
2907 : * translation if the data type (eBufType) of the buffer is different than
2908 : * that of the GDALRasterBand.
2909 : * The method also takes care of image decimation / replication if the
2910 : * buffer size (nBufXSize x nBufYSize) is different than the size of the
2911 : * region being accessed (nXSize x nYSize).
2912 : *
2913 : * The window of interest expressed by (nXOff, nYOff, nXSize, nYSize) should be
2914 : * fully within the raster space, that is nXOff >= 0, nYOff >= 0,
2915 : * nXOff + nXSize <= GetRasterXSize() and nYOff + nYSize <= GetRasterYSize().
2916 : * If reads larger than the raster space are wished, GDALTranslate() might be used.
2917 : * Or use nLineSpace and a possibly shifted pData value.
2918 : *
2919 : * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
2920 : * writing from various organization of buffers.
2921 : *
2922 : * Some formats may efficiently implement decimation into a buffer by
2923 : * reading from lower resolution overview images. The logic of the default
2924 : * implementation in the base class GDALRasterBand is the following one. It
2925 : * computes a target_downscaling_factor from the window of interest and buffer
2926 : * size which is min(nXSize/nBufXSize, nYSize/nBufYSize).
2927 : * It then walks through overviews and will select the first one whose
2928 : * downscaling factor is greater than target_downscaling_factor / 1.2.
2929 : *
2930 : * Let's assume we have overviews at downscaling factors 2, 4 and 8.
2931 : * The relationship between target_downscaling_factor and the select overview
2932 : * level is the following one:
2933 : *
2934 : * target_downscaling_factor | selected_overview
2935 : * ------------------------- | -----------------
2936 : * ]0, 2 / 1.2] | full resolution band
2937 : * ]2 / 1.2, 4 / 1.2] | 2x downsampled band
2938 : * ]4 / 1.2, 8 / 1.2] | 4x downsampled band
2939 : * ]8 / 1.2, infinity[ | 8x downsampled band
2940 : *
2941 : * Note that starting with GDAL 3.9, this 1.2 oversampling factor can be
2942 : * modified by setting the GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD configuration
2943 : * option. Also note that starting with GDAL 3.9, when the resampling algorithm
2944 : * specified in psExtraArg->eResampleAlg is different from GRIORA_NearestNeighbour,
2945 : * this oversampling threshold defaults to 1. Consequently if there are overviews
2946 : * of downscaling factor 2, 4 and 8, and the desired downscaling factor is
2947 : * 7.99, the overview of factor 4 will be selected for a non nearest resampling.
2948 : *
2949 : * For highest performance full resolution data access, read and write
2950 : * on "block boundaries" as returned by GetBlockSize(), or use the
2951 : * ReadBlock() and WriteBlock() methods.
2952 : *
2953 : * This method is the same as the C GDALDatasetRasterIO() or
2954 : * GDALDatasetRasterIOEx() functions.
2955 : *
2956 : * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
2957 : * write a region of data.
2958 : *
2959 : * @param nXOff The pixel offset to the top left corner of the region
2960 : * of the band to be accessed. This would be zero to start from the left side.
2961 : *
2962 : * @param nYOff The line offset to the top left corner of the region
2963 : * of the band to be accessed. This would be zero to start from the top.
2964 : *
2965 : * @param nXSize The width of the region of the band to be accessed in pixels.
2966 : *
2967 : * @param nYSize The height of the region of the band to be accessed in lines.
2968 : *
2969 : * @param pData The buffer into which the data should be read, or from which
2970 : * it should be written. This buffer must contain at least
2971 : * nBufXSize * nBufYSize * nBandCount words of type eBufType. It is organized
2972 : * in left to right,top to bottom pixel order. Spacing is controlled by the
2973 : * nPixelSpace, and nLineSpace parameters.
2974 : * Note that even with eRWFlag==GF_Write, the content of the buffer might be
2975 : * temporarily modified during the execution of this method (and eventually
2976 : * restored back to its original content), so it is not safe to use a buffer
2977 : * stored in a read-only section of the calling program.
2978 : *
2979 : * @param nBufXSize the width of the buffer image into which the desired region
2980 : * is to be read, or from which it is to be written.
2981 : *
2982 : * @param nBufYSize the height of the buffer image into which the desired
2983 : * region is to be read, or from which it is to be written.
2984 : *
2985 : * @param eBufType the type of the pixel values in the pData data buffer. The
2986 : * pixel values will automatically be translated to/from the GDALRasterBand
2987 : * data type as needed. Most driver implementations will use GDALCopyWords64()
2988 : * to perform data type translation.
2989 : *
2990 : * @param nBandCount the number of bands being read or written.
2991 : *
2992 : * @param panBandMap the list of nBandCount band numbers being read/written.
2993 : * Note band numbers are 1 based. This may be NULL to select the first
2994 : * nBandCount bands. (Note: before GDAL 3.10, argument type was "int*", and
2995 : * not "const int*")
2996 : *
2997 : * @param nPixelSpace The byte offset from the start of one pixel value in
2998 : * pData to the start of the next pixel value within a scanline. If defaulted
2999 : * (0) the size of the datatype eBufType is used.
3000 : *
3001 : * @param nLineSpace The byte offset from the start of one scanline in
3002 : * pData to the start of the next. If defaulted (0) the size of the datatype
3003 : * eBufType * nBufXSize is used.
3004 : *
3005 : * @param nBandSpace the byte offset from the start of one bands data to the
3006 : * start of the next. If defaulted (0) the value will be
3007 : * nLineSpace * nBufYSize implying band sequential organization
3008 : * of the data buffer.
3009 : *
3010 : * @param psExtraArg pointer to a GDALRasterIOExtraArg
3011 : * structure with additional arguments to specify resampling and progress
3012 : * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
3013 : * configuration option can also be defined to override the default resampling
3014 : * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
3015 : *
3016 : * @return CE_Failure if the access fails, otherwise CE_None.
3017 : */
3018 :
3019 729064 : CPLErr GDALDataset::RasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
3020 : int nXSize, int nYSize, void *pData, int nBufXSize,
3021 : int nBufYSize, GDALDataType eBufType,
3022 : int nBandCount, const int *panBandMap,
3023 : GSpacing nPixelSpace, GSpacing nLineSpace,
3024 : GSpacing nBandSpace,
3025 : GDALRasterIOExtraArg *psExtraArg)
3026 :
3027 : {
3028 : GDALRasterIOExtraArg sExtraArg;
3029 729064 : if (psExtraArg == nullptr)
3030 : {
3031 536148 : INIT_RASTERIO_EXTRA_ARG(sExtraArg);
3032 :
3033 : // 4 below inits are not strictly needed but make Coverity Scan
3034 : // happy
3035 536148 : sExtraArg.dfXOff = nXOff;
3036 536148 : sExtraArg.dfYOff = nYOff;
3037 536148 : sExtraArg.dfXSize = nXSize;
3038 536148 : sExtraArg.dfYSize = nYSize;
3039 :
3040 536148 : psExtraArg = &sExtraArg;
3041 : }
3042 192916 : else if (CPL_UNLIKELY(psExtraArg->nVersion >
3043 : RASTERIO_EXTRA_ARG_CURRENT_VERSION))
3044 : {
3045 0 : ReportError(CE_Failure, CPLE_AppDefined,
3046 : "Unhandled version of GDALRasterIOExtraArg");
3047 0 : return CE_Failure;
3048 : }
3049 :
3050 729064 : GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
3051 : nBufYSize);
3052 :
3053 729062 : if (CPL_UNLIKELY(nullptr == pData))
3054 : {
3055 0 : ReportError(CE_Failure, CPLE_AppDefined,
3056 : "The buffer into which the data should be read is null");
3057 0 : return CE_Failure;
3058 : }
3059 :
3060 : /* -------------------------------------------------------------------- */
3061 : /* Do some validation of parameters. */
3062 : /* -------------------------------------------------------------------- */
3063 :
3064 729062 : if (CPL_UNLIKELY(eRWFlag != GF_Read && eRWFlag != GF_Write))
3065 : {
3066 0 : ReportError(
3067 : CE_Failure, CPLE_IllegalArg,
3068 : "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
3069 : eRWFlag);
3070 0 : return CE_Failure;
3071 : }
3072 :
3073 729062 : if (eRWFlag == GF_Write)
3074 : {
3075 216549 : if (CPL_UNLIKELY(eAccess != GA_Update))
3076 : {
3077 2 : ReportError(CE_Failure, CPLE_AppDefined,
3078 : "Write operation not permitted on dataset opened "
3079 : "in read-only mode");
3080 2 : return CE_Failure;
3081 : }
3082 : }
3083 :
3084 729060 : int bStopProcessing = FALSE;
3085 729060 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3086 : "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
3087 : nBufYSize, nBandCount, panBandMap);
3088 729062 : if (eErr != CE_None || bStopProcessing)
3089 11 : return eErr;
3090 729051 : if (CPL_UNLIKELY(eBufType == GDT_Unknown || eBufType == GDT_TypeCount))
3091 : {
3092 2 : ReportError(CE_Failure, CPLE_AppDefined,
3093 : "Illegal GDT_Unknown/GDT_TypeCount argument");
3094 2 : return CE_Failure;
3095 : }
3096 :
3097 : /* -------------------------------------------------------------------- */
3098 : /* If pixel and line spacing are defaulted assign reasonable */
3099 : /* value assuming a packed buffer. */
3100 : /* -------------------------------------------------------------------- */
3101 729049 : if (nPixelSpace == 0)
3102 424139 : nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
3103 :
3104 729047 : if (nLineSpace == 0)
3105 : {
3106 480957 : nLineSpace = nPixelSpace * nBufXSize;
3107 : }
3108 :
3109 729047 : if (nBandSpace == 0 && nBandCount > 1)
3110 : {
3111 66818 : nBandSpace = nLineSpace * nBufYSize;
3112 : }
3113 :
3114 729047 : if (panBandMap == nullptr)
3115 : {
3116 353218 : if (!m_poPrivate)
3117 0 : return CE_Failure;
3118 353218 : CPLAssert(static_cast<int>(m_poPrivate->m_anBandMap.size()) == nBands);
3119 353218 : panBandMap = m_poPrivate->m_anBandMap.data();
3120 : }
3121 :
3122 729046 : int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
3123 :
3124 : /* -------------------------------------------------------------------- */
3125 : /* We are being forced to use cached IO instead of a driver */
3126 : /* specific implementation. */
3127 : /* -------------------------------------------------------------------- */
3128 729051 : if (bForceCachedIO)
3129 : {
3130 21 : eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3131 : nBufXSize, nBufYSize, eBufType, nBandCount,
3132 : panBandMap, nPixelSpace, nLineSpace,
3133 21 : nBandSpace, psExtraArg);
3134 : }
3135 :
3136 : /* -------------------------------------------------------------------- */
3137 : /* Call the format specific function. */
3138 : /* -------------------------------------------------------------------- */
3139 : else
3140 : {
3141 729031 : eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3142 : nBufXSize, nBufYSize, eBufType, nBandCount,
3143 : // TODO: remove this const_cast once IRasterIO()
3144 : // takes a const int*
3145 : const_cast<int *>(panBandMap), nPixelSpace, nLineSpace,
3146 729030 : nBandSpace, psExtraArg);
3147 : }
3148 :
3149 729052 : if (bCallLeaveReadWrite)
3150 407577 : LeaveReadWrite();
3151 :
3152 729051 : return eErr;
3153 : }
3154 :
3155 : /************************************************************************/
3156 : /* GDALDatasetRasterIO() */
3157 : /************************************************************************/
3158 :
3159 : /**
3160 : * \brief Read/write a region of image data from multiple bands.
3161 : *
3162 : * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
3163 : * resolution, progress callback, etc. are needed)
3164 : *
3165 : * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
3166 : *
3167 : * @see GDALDataset::RasterIO()
3168 : */
3169 :
3170 4762 : CPLErr CPL_STDCALL GDALDatasetRasterIO(GDALDatasetH hDS, GDALRWFlag eRWFlag,
3171 : int nXOff, int nYOff, int nXSize,
3172 : int nYSize, void *pData, int nBufXSize,
3173 : int nBufYSize, GDALDataType eBufType,
3174 : int nBandCount, const int *panBandMap,
3175 : int nPixelSpace, int nLineSpace,
3176 : int nBandSpace)
3177 :
3178 : {
3179 4762 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
3180 :
3181 4762 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
3182 :
3183 4762 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3184 : nBufXSize, nBufYSize, eBufType, nBandCount,
3185 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
3186 4762 : nullptr);
3187 : }
3188 :
3189 : /************************************************************************/
3190 : /* GDALDatasetRasterIOEx() */
3191 : /************************************************************************/
3192 :
3193 : /**
3194 : * \brief Read/write a region of image data from multiple bands.
3195 : *
3196 : * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
3197 : *
3198 : * @see GDALDataset::RasterIO()
3199 : */
3200 :
3201 353268 : CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
3202 : GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
3203 : int nYSize, void *pData, int nBufXSize, int nBufYSize,
3204 : GDALDataType eBufType, int nBandCount, const int *panBandMap,
3205 : GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
3206 : GDALRasterIOExtraArg *psExtraArg)
3207 :
3208 : {
3209 353268 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
3210 :
3211 353268 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
3212 :
3213 353268 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3214 : nBufXSize, nBufYSize, eBufType, nBandCount,
3215 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
3216 353268 : psExtraArg);
3217 : }
3218 :
3219 : /************************************************************************/
3220 : /* GetOpenDatasets() */
3221 : /************************************************************************/
3222 :
3223 : /**
3224 : * \brief Fetch all open GDAL dataset handles.
3225 : *
3226 : * This method is the same as the C function GDALGetOpenDatasets().
3227 : *
3228 : * NOTE: This method is not thread safe. The returned list may change
3229 : * at any time and it should not be freed.
3230 : *
3231 : * @param pnCount integer into which to place the count of dataset pointers
3232 : * being returned.
3233 : *
3234 : * @return a pointer to an array of dataset handles.
3235 : */
3236 :
3237 2261 : GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)
3238 :
3239 : {
3240 4522 : CPLMutexHolderD(&hDLMutex);
3241 :
3242 2261 : if (poAllDatasetMap == nullptr)
3243 : {
3244 2240 : *pnCount = 0;
3245 2240 : return nullptr;
3246 : }
3247 :
3248 21 : *pnCount = static_cast<int>(poAllDatasetMap->size());
3249 21 : ppDatasets = static_cast<GDALDataset **>(
3250 21 : CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
3251 21 : std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();
3252 576 : for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)
3253 555 : ppDatasets[i] = oIter->first;
3254 21 : return ppDatasets;
3255 : }
3256 :
3257 : /************************************************************************/
3258 : /* GDALGetOpenDatasets() */
3259 : /************************************************************************/
3260 :
3261 : /**
3262 : * \brief Fetch all open GDAL dataset handles.
3263 : *
3264 : * @see GDALDataset::GetOpenDatasets()
3265 : */
3266 :
3267 0 : void CPL_STDCALL GDALGetOpenDatasets(GDALDatasetH **ppahDSList, int *pnCount)
3268 :
3269 : {
3270 0 : VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
3271 0 : VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
3272 :
3273 0 : *ppahDSList =
3274 0 : reinterpret_cast<GDALDatasetH *>(GDALDataset::GetOpenDatasets(pnCount));
3275 : }
3276 :
3277 : /************************************************************************/
3278 : /* GDALCleanOpenDatasetsList() */
3279 : /************************************************************************/
3280 :
3281 : // Useful when called from the child of a fork(), to avoid closing
3282 : // the datasets of the parent at the child termination.
3283 0 : void GDALNullifyOpenDatasetsList()
3284 : {
3285 0 : poAllDatasetMap = nullptr;
3286 0 : phSharedDatasetSet = nullptr;
3287 0 : ppDatasets = nullptr;
3288 0 : hDLMutex = nullptr;
3289 0 : }
3290 :
3291 : /************************************************************************/
3292 : /* GDALGetAccess() */
3293 : /************************************************************************/
3294 :
3295 : /**
3296 : * \brief Return access flag
3297 : *
3298 : * @see GDALDataset::GetAccess()
3299 : */
3300 :
3301 0 : int CPL_STDCALL GDALGetAccess(GDALDatasetH hDS)
3302 : {
3303 0 : VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
3304 :
3305 0 : return GDALDataset::FromHandle(hDS)->GetAccess();
3306 : }
3307 :
3308 : /************************************************************************/
3309 : /* AdviseRead() */
3310 : /************************************************************************/
3311 :
3312 : /**
3313 : * \brief Advise driver of upcoming read requests.
3314 : *
3315 : * Some GDAL drivers operate more efficiently if they know in advance what
3316 : * set of upcoming read requests will be made. The AdviseRead() method allows
3317 : * an application to notify the driver of the region and bands of interest,
3318 : * and at what resolution the region will be read.
3319 : *
3320 : * Many drivers just ignore the AdviseRead() call, but it can dramatically
3321 : * accelerate access via some drivers.
3322 : *
3323 : * Depending on call paths, drivers might receive several calls to
3324 : * AdviseRead() with the same parameters.
3325 : *
3326 : * @param nXOff The pixel offset to the top left corner of the region
3327 : * of the band to be accessed. This would be zero to start from the left side.
3328 : *
3329 : * @param nYOff The line offset to the top left corner of the region
3330 : * of the band to be accessed. This would be zero to start from the top.
3331 : *
3332 : * @param nXSize The width of the region of the band to be accessed in pixels.
3333 : *
3334 : * @param nYSize The height of the region of the band to be accessed in lines.
3335 : *
3336 : * @param nBufXSize the width of the buffer image into which the desired region
3337 : * is to be read, or from which it is to be written.
3338 : *
3339 : * @param nBufYSize the height of the buffer image into which the desired
3340 : * region is to be read, or from which it is to be written.
3341 : *
3342 : * @param eBufType the type of the pixel values in the pData data buffer. The
3343 : * pixel values will automatically be translated to/from the GDALRasterBand
3344 : * data type as needed.
3345 : *
3346 : * @param nBandCount the number of bands being read or written.
3347 : *
3348 : * @param panBandMap the list of nBandCount band numbers being read/written.
3349 : * Note band numbers are 1 based. This may be NULL to select the first
3350 : * nBandCount bands.
3351 : *
3352 : * @param papszOptions a list of name=value strings with special control
3353 : * options. Normally this is NULL.
3354 : *
3355 : * @return CE_Failure if the request is invalid and CE_None if it works or
3356 : * is ignored.
3357 : */
3358 :
3359 14674 : CPLErr GDALDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
3360 : int nBufXSize, int nBufYSize,
3361 : GDALDataType eBufType, int nBandCount,
3362 : int *panBandMap, char **papszOptions)
3363 :
3364 : {
3365 : /* -------------------------------------------------------------------- */
3366 : /* Do some validation of parameters. */
3367 : /* -------------------------------------------------------------------- */
3368 14674 : int bStopProcessing = FALSE;
3369 14674 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3370 : "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
3371 : nBufXSize, nBufYSize, nBandCount, panBandMap);
3372 14674 : if (eErr != CE_None || bStopProcessing)
3373 20 : return eErr;
3374 :
3375 128353 : for (int iBand = 0; iBand < nBandCount; ++iBand)
3376 : {
3377 113699 : GDALRasterBand *poBand = nullptr;
3378 :
3379 113699 : if (panBandMap == nullptr)
3380 112348 : poBand = GetRasterBand(iBand + 1);
3381 : else
3382 1351 : poBand = GetRasterBand(panBandMap[iBand]);
3383 :
3384 113699 : if (poBand == nullptr)
3385 0 : return CE_Failure;
3386 :
3387 227398 : eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
3388 113699 : nBufYSize, eBufType, papszOptions);
3389 :
3390 113699 : if (eErr != CE_None)
3391 0 : return eErr;
3392 : }
3393 :
3394 14654 : return CE_None;
3395 : }
3396 :
3397 : /************************************************************************/
3398 : /* GDALDatasetAdviseRead() */
3399 : /************************************************************************/
3400 :
3401 : /**
3402 : * \brief Advise driver of upcoming read requests.
3403 : *
3404 : * @see GDALDataset::AdviseRead()
3405 : */
3406 1 : CPLErr CPL_STDCALL GDALDatasetAdviseRead(GDALDatasetH hDS, int nXOff, int nYOff,
3407 : int nXSize, int nYSize, int nBufXSize,
3408 : int nBufYSize, GDALDataType eDT,
3409 : int nBandCount, int *panBandMap,
3410 : CSLConstList papszOptions)
3411 :
3412 : {
3413 1 : VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
3414 :
3415 2 : return GDALDataset::FromHandle(hDS)->AdviseRead(
3416 : nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount,
3417 1 : panBandMap, const_cast<char **>(papszOptions));
3418 : }
3419 :
3420 : /************************************************************************/
3421 : /* GDALAntiRecursionStruct */
3422 : /************************************************************************/
3423 :
3424 : // Prevent infinite recursion.
3425 : struct GDALAntiRecursionStruct
3426 : {
3427 : struct DatasetContext
3428 : {
3429 : std::string osFilename;
3430 : int nOpenFlags;
3431 : std::string osAllowedDrivers;
3432 :
3433 81100 : DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,
3434 : const std::string &osAllowedDriversIn)
3435 81100 : : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),
3436 81100 : osAllowedDrivers(osAllowedDriversIn)
3437 : {
3438 81100 : }
3439 : };
3440 :
3441 : struct DatasetContextCompare
3442 : {
3443 952423 : bool operator()(const DatasetContext &lhs,
3444 : const DatasetContext &rhs) const
3445 : {
3446 2784350 : return lhs.osFilename < rhs.osFilename ||
3447 922664 : (lhs.osFilename == rhs.osFilename &&
3448 909289 : (lhs.nOpenFlags < rhs.nOpenFlags ||
3449 1818360 : (lhs.nOpenFlags == rhs.nOpenFlags &&
3450 1862330 : lhs.osAllowedDrivers < rhs.osAllowedDrivers)));
3451 : }
3452 : };
3453 :
3454 1337 : ~GDALAntiRecursionStruct()
3455 1337 : {
3456 1337 : CPLAssert(aosDatasetNamesWithFlags.empty());
3457 1337 : CPLAssert(nRecLevel == 0);
3458 1337 : CPLAssert(m_oMapDepth.empty());
3459 1337 : }
3460 :
3461 : std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
3462 : int nRecLevel = 0;
3463 : std::map<std::string, int> m_oMapDepth{};
3464 : };
3465 :
3466 : #ifdef _WIN32
3467 : // Currently thread_local and C++ objects don't work well with DLL on Windows
3468 : static void FreeAntiRecursionOpen(void *pData)
3469 : {
3470 : delete static_cast<GDALAntiRecursionStruct *>(pData);
3471 : }
3472 :
3473 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3474 : {
3475 : static GDALAntiRecursionStruct dummy;
3476 : int bMemoryErrorOccurred = false;
3477 : void *pData =
3478 : CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
3479 : if (bMemoryErrorOccurred)
3480 : {
3481 : return dummy;
3482 : }
3483 : if (pData == nullptr)
3484 : {
3485 : auto pAntiRecursion = new GDALAntiRecursionStruct();
3486 : CPLSetTLSWithFreeFuncEx(CTLS_GDALOPEN_ANTIRECURSION, pAntiRecursion,
3487 : FreeAntiRecursionOpen, &bMemoryErrorOccurred);
3488 : if (bMemoryErrorOccurred)
3489 : {
3490 : delete pAntiRecursion;
3491 : return dummy;
3492 : }
3493 : return *pAntiRecursion;
3494 : }
3495 : return *static_cast<GDALAntiRecursionStruct *>(pData);
3496 : }
3497 : #else
3498 : static thread_local GDALAntiRecursionStruct g_tls_antiRecursion;
3499 :
3500 345568 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3501 : {
3502 345568 : return g_tls_antiRecursion;
3503 : }
3504 : #endif
3505 :
3506 : //! @cond Doxygen_Suppress
3507 264470 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)
3508 264470 : : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),
3509 : m_osIdentifier(osIdentifier),
3510 264470 : m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3511 : {
3512 264470 : CPLAssert(!osIdentifier.empty());
3513 264469 : }
3514 :
3515 264470 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(
3516 264470 : const GDALAntiRecursionGuard &other, const std::string &osIdentifier)
3517 264470 : : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),
3518 264470 : m_osIdentifier(osIdentifier.empty()
3519 : ? osIdentifier
3520 30485 : : other.m_osIdentifier + osIdentifier),
3521 264470 : m_nDepth(m_osIdentifier.empty()
3522 264469 : ? 0
3523 294955 : : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3524 : {
3525 264470 : }
3526 :
3527 528940 : GDALAntiRecursionGuard::~GDALAntiRecursionGuard()
3528 : {
3529 528940 : if (!m_osIdentifier.empty())
3530 : {
3531 294956 : auto oIter = m_psAntiRecursionStruct->m_oMapDepth.find(m_osIdentifier);
3532 294956 : CPLAssert(oIter != m_psAntiRecursionStruct->m_oMapDepth.end());
3533 294956 : if (--(oIter->second) == 0)
3534 290504 : m_psAntiRecursionStruct->m_oMapDepth.erase(oIter);
3535 : }
3536 528940 : }
3537 :
3538 : //! @endcond
3539 :
3540 : /************************************************************************/
3541 : /* GetFileList() */
3542 : /************************************************************************/
3543 :
3544 : /**
3545 : * \brief Fetch files forming dataset.
3546 : *
3547 : * Returns a list of files believed to be part of this dataset. If it returns
3548 : * an empty list of files it means there is believed to be no local file
3549 : * system files associated with the dataset (for instance a virtual dataset).
3550 : * The returned file list is owned by the caller and should be deallocated
3551 : * with CSLDestroy().
3552 : *
3553 : * The returned filenames will normally be relative or absolute paths
3554 : * depending on the path used to originally open the dataset. The strings
3555 : * will be UTF-8 encoded.
3556 : *
3557 : * This method is the same as the C GDALGetFileList() function.
3558 : *
3559 : * @return NULL or a NULL terminated array of file names.
3560 : */
3561 :
3562 4635 : char **GDALDataset::GetFileList()
3563 :
3564 : {
3565 9270 : CPLString osMainFilename = GetDescription();
3566 : VSIStatBufL sStat;
3567 :
3568 4635 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3569 : GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,
3570 9270 : std::string());
3571 4635 : auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
3572 4635 : if (cpl::contains(aosDatasetList, datasetCtxt))
3573 0 : return nullptr;
3574 :
3575 : /* -------------------------------------------------------------------- */
3576 : /* Is the main filename even a real filesystem object? */
3577 : /* -------------------------------------------------------------------- */
3578 : int bMainFileReal =
3579 4635 : VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
3580 :
3581 : /* -------------------------------------------------------------------- */
3582 : /* Form new list. */
3583 : /* -------------------------------------------------------------------- */
3584 4635 : char **papszList = nullptr;
3585 :
3586 4635 : if (bMainFileReal)
3587 4560 : papszList = CSLAddString(papszList, osMainFilename);
3588 :
3589 4635 : if (sAntiRecursion.nRecLevel == 100)
3590 : {
3591 0 : CPLError(CE_Failure, CPLE_AppDefined,
3592 : "GetFileList() called with too many recursion levels");
3593 0 : return papszList;
3594 : }
3595 4635 : ++sAntiRecursion.nRecLevel;
3596 :
3597 : /* -------------------------------------------------------------------- */
3598 : /* Do we have a known overview file? */
3599 : /* -------------------------------------------------------------------- */
3600 4635 : if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
3601 : {
3602 60 : auto iter = aosDatasetList.insert(datasetCtxt).first;
3603 60 : char **papszOvrList = oOvManager.poODS->GetFileList();
3604 60 : papszList = CSLInsertStrings(papszList, -1, papszOvrList);
3605 60 : CSLDestroy(papszOvrList);
3606 60 : aosDatasetList.erase(iter);
3607 : }
3608 :
3609 : /* -------------------------------------------------------------------- */
3610 : /* Do we have a known mask file? */
3611 : /* -------------------------------------------------------------------- */
3612 4635 : if (oOvManager.HaveMaskFile())
3613 : {
3614 9 : auto iter = aosDatasetList.insert(std::move(datasetCtxt)).first;
3615 9 : for (const char *pszFile :
3616 18 : CPLStringList(oOvManager.poMaskDS->GetFileList()))
3617 : {
3618 9 : if (CSLFindString(papszList, pszFile) < 0)
3619 9 : papszList = CSLAddString(papszList, pszFile);
3620 : }
3621 9 : aosDatasetList.erase(iter);
3622 : }
3623 :
3624 4635 : --sAntiRecursion.nRecLevel;
3625 :
3626 4635 : return papszList;
3627 : }
3628 :
3629 : /************************************************************************/
3630 : /* GDALGetFileList() */
3631 : /************************************************************************/
3632 :
3633 : /**
3634 : * \brief Fetch files forming dataset.
3635 : *
3636 : * @see GDALDataset::GetFileList()
3637 : */
3638 :
3639 3835 : char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)
3640 :
3641 : {
3642 3835 : VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3643 :
3644 3835 : return GDALDataset::FromHandle(hDS)->GetFileList();
3645 : }
3646 :
3647 : /************************************************************************/
3648 : /* CreateMaskBand() */
3649 : /************************************************************************/
3650 :
3651 : /**
3652 : * \brief Adds a mask band to the dataset
3653 : *
3654 : * The default implementation of the CreateMaskBand() method is implemented
3655 : * based on similar rules to the .ovr handling implemented using the
3656 : * GDALDefaultOverviews object. A TIFF file with the extension .msk will
3657 : * be created with the same basename as the original file, and it will have
3658 : * one band.
3659 : * The mask images will be deflate compressed tiled images with the same
3660 : * block size as the original image if possible.
3661 : * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
3662 : * level, where xx matches the band number of a band of the main dataset. The
3663 : * value of those items will be the one of the nFlagsIn parameter.
3664 : *
3665 : * Note that if you got a mask band with a previous call to GetMaskBand(), it
3666 : * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
3667 : * again.
3668 : *
3669 : *
3670 : * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
3671 : * GMF_PER_DATASET will be always set, even if not explicitly
3672 : * specified.
3673 : * @return CE_None on success or CE_Failure on an error.
3674 : *
3675 : * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
3676 : * @see GDALRasterBand::CreateMaskBand()
3677 : *
3678 : */
3679 17 : CPLErr GDALDataset::CreateMaskBand(int nFlagsIn)
3680 :
3681 : {
3682 17 : if (oOvManager.IsInitialized())
3683 : {
3684 17 : CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
3685 17 : if (eErr != CE_None)
3686 0 : return eErr;
3687 :
3688 : // Invalidate existing raster band masks.
3689 45 : for (int i = 0; i < nBands; ++i)
3690 : {
3691 28 : GDALRasterBand *poBand = papoBands[i];
3692 28 : poBand->poMask.reset();
3693 : }
3694 :
3695 17 : return CE_None;
3696 : }
3697 :
3698 0 : ReportError(CE_Failure, CPLE_NotSupported,
3699 : "CreateMaskBand() not supported for this dataset.");
3700 :
3701 0 : return CE_Failure;
3702 : }
3703 :
3704 : /************************************************************************/
3705 : /* GDALCreateDatasetMaskBand() */
3706 : /************************************************************************/
3707 :
3708 : /**
3709 : * \brief Adds a mask band to the dataset
3710 : * @see GDALDataset::CreateMaskBand()
3711 : */
3712 95 : CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)
3713 :
3714 : {
3715 95 : VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3716 :
3717 95 : return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
3718 : }
3719 :
3720 : /************************************************************************/
3721 : /* GDALOpen() */
3722 : /************************************************************************/
3723 :
3724 : /**
3725 : * \brief Open a raster file as a GDALDataset.
3726 : *
3727 : * This function will try to open the passed file, or virtual dataset
3728 : * name by invoking the Open method of each registered GDALDriver in turn.
3729 : * The first successful open will result in a returned dataset. If all
3730 : * drivers fail then NULL is returned and an error is issued.
3731 : *
3732 : * Several recommendations :
3733 : * <ul>
3734 : * <li>If you open a dataset object with GA_Update access, it is not recommended
3735 : * to open a new dataset on the same underlying file.</li>
3736 : * <li>The returned dataset should only be accessed by one thread at a time. If
3737 : * you want to use it from different threads, you must add all necessary code
3738 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3739 : * as GeoTIFF, maintain internal state variables that are updated each time a
3740 : * new block is read, thus preventing concurrent use.) </li>
3741 : * </ul>
3742 : *
3743 : * For drivers supporting the VSI virtual file API, it is possible to open a
3744 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3745 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3746 : * server (see VSIInstallCurlFileHandler())
3747 : *
3748 : * \sa GDALOpenShared()
3749 : * \sa GDALOpenEx()
3750 : *
3751 : * @param pszFilename the name of the file to access. In the case of
3752 : * exotic drivers this may not refer to a physical file, but instead contain
3753 : * information for the driver on how to access a dataset. It should be in UTF-8
3754 : * encoding.
3755 : *
3756 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
3757 : * drivers support only read only access.
3758 : *
3759 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3760 : * this handle can be cast to a GDALDataset *.
3761 : */
3762 :
3763 25369 : GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)
3764 :
3765 : {
3766 25369 : const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3767 25369 : const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3768 : GDALDatasetH hDataset =
3769 25369 : GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3770 25368 : return hDataset;
3771 : }
3772 :
3773 : /************************************************************************/
3774 : /* GetSharedDS() */
3775 : /************************************************************************/
3776 :
3777 6485 : static GDALDataset *GetSharedDS(const char *pszFilename,
3778 : unsigned int nOpenFlags,
3779 : const char *const *papszOpenOptions)
3780 : {
3781 12970 : CPLMutexHolderD(&hDLMutex);
3782 :
3783 6485 : if (phSharedDatasetSet != nullptr)
3784 : {
3785 6226 : const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3786 : SharedDatasetCtxt sStruct;
3787 :
3788 6226 : sStruct.nPID = nThisPID;
3789 6226 : sStruct.pszDescription = const_cast<char *>(pszFilename);
3790 6226 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
3791 : std::string osConcatenatedOpenOptions =
3792 6226 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
3793 6226 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
3794 6226 : sStruct.poDS = nullptr;
3795 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3796 6226 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3797 6226 : if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3798 : {
3799 121 : sStruct.nOpenFlags |= GDAL_OF_UPDATE;
3800 : psStruct = static_cast<SharedDatasetCtxt *>(
3801 121 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3802 : }
3803 6226 : if (psStruct)
3804 : {
3805 6106 : return psStruct->poDS;
3806 : }
3807 : }
3808 379 : return nullptr;
3809 : }
3810 :
3811 : /************************************************************************/
3812 : /* GDALOpenEx() */
3813 : /************************************************************************/
3814 :
3815 : /**
3816 : * \brief Open a raster or vector file as a GDALDataset.
3817 : *
3818 : * This function will try to open the passed file, or virtual dataset
3819 : * name by invoking the Open method of each registered GDALDriver in turn.
3820 : * The first successful open will result in a returned dataset. If all
3821 : * drivers fail then NULL is returned and an error is issued.
3822 : *
3823 : * Several recommendations :
3824 : * <ul>
3825 : * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
3826 : * recommended to open a new dataset on the same underlying file.</li>
3827 : * <li>The returned dataset should only be accessed by one thread at a time. If
3828 : * you want to use it from different threads, you must add all necessary code
3829 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3830 : * as GeoTIFF, maintain internal state variables that are updated each time a
3831 : * new block is read, thus preventing concurrent use.) </li>
3832 : * </ul>
3833 : *
3834 : * For drivers supporting the VSI virtual file API, it is possible to open a
3835 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3836 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3837 : * server (see VSIInstallCurlFileHandler())
3838 : *
3839 : * In order to reduce the need for searches through the operating system
3840 : * file system machinery, it is possible to give an optional list of files with
3841 : * the papszSiblingFiles parameter.
3842 : * This is the list of all files at the same level in the file system as the
3843 : * target file, including the target file. The filenames must not include any
3844 : * path components, are essentially just the output of VSIReadDir() on the
3845 : * parent directory. If the target object does not have filesystem semantics
3846 : * then the file list should be NULL.
3847 : *
3848 : * @param pszFilename the name of the file to access. In the case of
3849 : * exotic drivers this may not refer to a physical file, but instead contain
3850 : * information for the driver on how to access a dataset. It should be in UTF-8
3851 : * encoding.
3852 : *
3853 : * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
3854 : * through logical or operator.
3855 : * <ul>
3856 : * <li>Driver kind:
3857 : * <ul>
3858 : * <li>GDAL_OF_RASTER for raster drivers,</li>
3859 : * <li>GDAL_OF_MULTIDIM_RASTER for multidimensional raster drivers,</li>
3860 : * <li>GDAL_OF_VECTOR for vector drivers,</li>
3861 : * <li>GDAL_OF_GNM for Geographic Network Model drivers.</li>
3862 : * </ul>
3863 : * GDAL_OF_RASTER and GDAL_OF_MULTIDIM_RASTER are generally mutually
3864 : * exclusive. If none of the value is specified, GDAL_OF_RASTER | GDAL_OF_VECTOR
3865 : * | GDAL_OF_GNM is implied.
3866 : * </li>
3867 : * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.
3868 : * </li>
3869 : * <li>Shared mode: GDAL_OF_SHARED. If set,
3870 : * it allows the sharing of GDALDataset handles for a dataset with other callers
3871 : * that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will first consult
3872 : * its list of currently open and shared GDALDataset's, and if the
3873 : * GetDescription() name for one exactly matches the pszFilename passed to
3874 : * GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called
3875 : * from the same thread.
3876 : * </li>
3877 : * <li>Thread safe mode: GDAL_OF_THREAD_SAFE (added in 3.10).
3878 : * This must be use in combination with GDAL_OF_RASTER, and is mutually
3879 : * exclusive with GDAL_OF_UPDATE, GDAL_OF_VECTOR, GDAL_OF_MULTIDIM_RASTER or
3880 : * GDAL_OF_GNM.
3881 : * </li>
3882 : * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set,
3883 : * a failed attempt to open the file will lead to an error message to be
3884 : * reported.
3885 : * </li>
3886 : * </ul>
3887 : *
3888 : * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
3889 : * terminated list of strings with the driver short names that must be
3890 : * considered.
3891 : *
3892 : * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
3893 : * options passed to candidate drivers. An option exists for all drivers,
3894 : * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
3895 : * The level index starts at 0. The level number can be suffixed by "only" to
3896 : * specify that only this overview level must be visible, and not sub-levels.
3897 : * Open options are validated by default, and a warning is emitted in case the
3898 : * option is not recognized. In some scenarios, it might be not desirable (e.g.
3899 : * when not knowing which driver will open the file), so the special open option
3900 : * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
3901 : * that it may not cause a warning if the driver doesn't declare this option.
3902 : * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
3903 : * no overviews should be exposed.
3904 : *
3905 : * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
3906 : * filenames that are auxiliary to the main filename. If NULL is passed, a
3907 : * probing of the file system will be done.
3908 : *
3909 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3910 : * this handle can be cast to a GDALDataset *.
3911 : *
3912 : */
3913 :
3914 82574 : 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 82574 : 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 82565 : std::unique_ptr<CPLConfigOptionSetter> poVSIKERCHUNK_USE_CACHESetter;
3925 82574 : 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 82573 : 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 82569 : if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)
3960 7484 : 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 82569 : 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 76463 : GDALDriverManager *poDM = GetGDALDriverManager();
3985 : // CPLLocaleC oLocaleForcer;
3986 :
3987 76465 : CPLErrorReset();
3988 76462 : VSIErrorReset();
3989 76464 : 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 152916 : const_cast<char **>(papszSiblingFiles));
3995 76465 : oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3996 :
3997 76465 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3998 76465 : 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 152925 : std::string osAllowedDrivers;
4006 167542 : for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
4007 91077 : osAllowedDrivers += pszDriverName;
4008 : auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(
4009 229389 : std::string(pszFilename), nOpenFlags, osAllowedDrivers);
4010 76464 : 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 76464 : CSLDuplicate(const_cast<char **>(papszOpenOptions));
4020 82091 : for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
4021 : ++papszIter)
4022 : {
4023 5626 : char *pszOption = *papszIter;
4024 5626 : if (pszOption[0] == '@')
4025 212 : memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
4026 : }
4027 :
4028 76465 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4029 76465 : oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;
4030 :
4031 : #ifdef OGRAPISPY_ENABLED
4032 76465 : const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
4033 : const int iSnapshot =
4034 19033 : (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0
4035 95498 : ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)
4036 76465 : : INT_MIN;
4037 : #endif
4038 :
4039 76465 : const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);
4040 76464 : GDALDriver *poMissingPluginDriver = nullptr;
4041 152922 : 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 76464 : int iPass = 1;
4060 76474 : retry:
4061 7876010 : for (int iDriver = 0;
4062 7876040 : iDriver < (iPass == 1 ? nDriverCount
4063 30 : : static_cast<int>(apoSecondPassDrivers.size()));
4064 : ++iDriver)
4065 : {
4066 : GDALDriver *poDriver =
4067 7859410 : iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
4068 0 : : apoSecondPassDrivers[iDriver];
4069 11471600 : if (papszAllowedDrivers != nullptr &&
4070 3610770 : CSLFindString(papszAllowedDrivers,
4071 : GDALGetDriverShortName(poDriver)) == -1)
4072 : {
4073 7405330 : continue;
4074 : }
4075 :
4076 4336190 : if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)
4077 42548 : continue;
4078 :
4079 11410500 : if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&
4080 6223620 : (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
4081 1931750 : poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
4082 462296 : continue;
4083 11211600 : if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&
4084 5609330 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
4085 1779750 : poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
4086 1340810 : continue;
4087 5271710 : if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
4088 2637140 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
4089 148378 : poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)
4090 139603 : 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 2349160 : char **papszTmpOpenOptions = nullptr;
4095 2349160 : char **papszTmpOpenOptionsToValidate = nullptr;
4096 2349160 : char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
4097 2349160 : if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
4098 2347800 : 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 2347650 : poDriver->pfnIdentifyEx
4114 4693750 : ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)
4115 2347640 : : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)
4116 2346110 : : GDAL_IDENTIFY_UNKNOWN;
4117 2346110 : if (nIdentifyRes == FALSE)
4118 : {
4119 1895130 : CSLDestroy(papszTmpOpenOptions);
4120 1893640 : CSLDestroy(papszTmpOpenOptionsToValidate);
4121 1895290 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4122 1895290 : continue;
4123 : }
4124 454668 : else if (iPass == 1 && nIdentifyRes < 0 &&
4125 905755 : 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 450880 : const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;
4137 450880 : if (bIdentifyRes)
4138 : {
4139 56755 : 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 450879 : sAntiRecursion.nRecLevel++;
4148 450879 : sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
4149 :
4150 454468 : GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
4151 :
4152 454586 : sAntiRecursion.nRecLevel--;
4153 454586 : sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
4154 :
4155 454542 : 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 454550 : if (poDS != nullptr &&
4160 56675 : (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&
4161 56113 : !bIdentifyRes)
4162 : {
4163 810 : 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 454542 : CSLDestroy(papszTmpOpenOptions);
4188 454472 : CSLDestroy(papszTmpOpenOptionsToValidate);
4189 454458 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4190 :
4191 454458 : if (poDS != nullptr)
4192 : {
4193 56671 : if (poDS->papszOpenOptions == nullptr)
4194 : {
4195 56411 : poDS->papszOpenOptions = papszOpenOptionsCleaned;
4196 56411 : papszOpenOptionsCleaned = nullptr;
4197 : }
4198 :
4199 : // Deal with generic OVERVIEW_LEVEL open option, unless it is
4200 : // driver specific.
4201 56671 : if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
4202 56717 : 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 56639 : 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 56678 : VSIErrorReset();
4283 :
4284 56671 : CSLDestroy(papszOpenOptionsCleaned);
4285 :
4286 : #ifdef OGRAPISPY_ENABLED
4287 56674 : if (iSnapshot != INT_MIN)
4288 : {
4289 11313 : GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
4290 11313 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4291 11313 : poDS = GDALDataset::FromHandle(hDS);
4292 : }
4293 : #endif
4294 :
4295 56674 : if (poDS)
4296 : {
4297 56672 : poDS->m_bCanBeReopened = true;
4298 :
4299 56672 : 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 57695 : 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 397787 : if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
4331 : {
4332 3562 : CSLDestroy(papszOpenOptionsCleaned);
4333 :
4334 : #ifdef OGRAPISPY_ENABLED
4335 1020 : if (iSnapshot != INT_MIN)
4336 : {
4337 193 : GDALDatasetH hDS = nullptr;
4338 193 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4339 : }
4340 : #endif
4341 1020 : return nullptr;
4342 : }
4343 : #endif
4344 : }
4345 :
4346 : // cppcheck-suppress knownConditionTrueFalse
4347 16624 : if (iPass == 1 && !apoSecondPassDrivers.empty())
4348 : {
4349 11 : CPLDebugOnly("GDAL", "GDALOpen(): Second pass");
4350 10 : iPass = 2;
4351 10 : goto retry;
4352 : }
4353 :
4354 16611 : CSLDestroy(papszOpenOptionsCleaned);
4355 :
4356 : #ifdef OGRAPISPY_ENABLED
4357 18761 : if (iSnapshot != INT_MIN)
4358 : {
4359 654 : GDALDatasetH hDS = nullptr;
4360 654 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4361 : }
4362 : #endif
4363 :
4364 18761 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4365 : {
4366 5714 : if (nDriverCount == 0)
4367 : {
4368 0 : CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");
4369 : }
4370 5714 : 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 5714 : 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 18763 : 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 : * 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 5204 : GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,
4450 : GDALAccess eAccess)
4451 : {
4452 5204 : VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
4453 5204 : return GDALOpenEx(pszFilename,
4454 : GDAL_OF_RASTER |
4455 : (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
4456 : GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
4457 5204 : 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 76352 : CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)
4479 :
4480 : {
4481 76352 : if (!hDS)
4482 399 : return CE_None;
4483 :
4484 : #ifdef OGRAPISPY_ENABLED
4485 75953 : if (bOGRAPISpyEnabled)
4486 11 : OGRAPISpyPreClose(hDS);
4487 : #endif
4488 :
4489 75953 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
4490 :
4491 75953 : 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 236 : if (poDS->Dereference() > 0)
4501 15 : return CE_None;
4502 :
4503 221 : CPLErr eErr = poDS->Close();
4504 221 : delete poDS;
4505 :
4506 : #ifdef OGRAPISPY_ENABLED
4507 221 : if (bOGRAPISpyEnabled)
4508 0 : OGRAPISpyPostClose();
4509 : #endif
4510 :
4511 221 : return eErr;
4512 : }
4513 :
4514 : /* -------------------------------------------------------------------- */
4515 : /* This is not shared dataset, so directly delete it. */
4516 : /* -------------------------------------------------------------------- */
4517 75717 : CPLErr eErr = poDS->Close();
4518 75717 : delete poDS;
4519 :
4520 : #ifdef OGRAPISPY_ENABLED
4521 75717 : if (bOGRAPISpyEnabled)
4522 11 : OGRAPISpyPostClose();
4523 : #endif
4524 75717 : 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 18759 : int GDALDataset::CloseDependentDatasets()
4869 : {
4870 18759 : 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 : */
4892 :
4893 101 : void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4894 : const char *fmt, ...) const
4895 : {
4896 : va_list args;
4897 101 : va_start(args, fmt);
4898 101 : ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4899 101 : va_end(args);
4900 101 : }
4901 :
4902 : /**
4903 : * \brief Emits an error related to a dataset (static method)
4904 : *
4905 : * This function is a wrapper for regular CPLError(). The only difference
4906 : * with CPLError() is that it prepends the error message with the dataset
4907 : * name.
4908 : *
4909 : * @param pszDSName dataset name.
4910 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4911 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4912 : * @param fmt a printf() style format string. Any additional arguments
4913 : * will be treated as arguments to fill in this format in a manner
4914 : * similar to printf().
4915 : *
4916 : * @since GDAL 3.2.0
4917 : */
4918 :
4919 123 : void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,
4920 : CPLErrorNum err_no, const char *fmt, ...)
4921 : {
4922 : va_list args;
4923 123 : va_start(args, fmt);
4924 123 : ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4925 123 : va_end(args);
4926 123 : }
4927 :
4928 224 : void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,
4929 : CPLErrorNum err_no, const char *fmt,
4930 : va_list args)
4931 : {
4932 224 : pszDSName = CPLGetFilename(pszDSName);
4933 224 : if (pszDSName[0] != '\0')
4934 : {
4935 208 : CPLError(eErrClass, err_no, "%s",
4936 416 : std::string(pszDSName)
4937 208 : .append(": ")
4938 416 : .append(CPLString().vPrintf(fmt, args))
4939 : .c_str());
4940 : }
4941 : else
4942 : {
4943 16 : CPLErrorV(eErrClass, err_no, fmt, args);
4944 : }
4945 224 : }
4946 : #endif
4947 :
4948 : /************************************************************************/
4949 : /* GetMetadata() */
4950 : /************************************************************************/
4951 71348 : char **GDALDataset::GetMetadata(const char *pszDomain)
4952 : {
4953 : #ifndef WITHOUT_DERIVED
4954 71348 : if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
4955 : {
4956 10 : oDerivedMetadataList.Clear();
4957 :
4958 : // First condition: at least one raster band.
4959 10 : if (GetRasterCount() > 0)
4960 : {
4961 : // Check if there is at least one complex band.
4962 10 : bool hasAComplexBand = false;
4963 :
4964 19 : for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4965 : {
4966 11 : if (GDALDataTypeIsComplex(
4967 11 : GetRasterBand(rasterId)->GetRasterDataType()))
4968 : {
4969 2 : hasAComplexBand = true;
4970 2 : break;
4971 : }
4972 : }
4973 :
4974 10 : unsigned int nbSupportedDerivedDS = 0;
4975 : const DerivedDatasetDescription *poDDSDesc =
4976 10 : GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4977 :
4978 10 : int nNumDataset = 1;
4979 80 : for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4980 : ++derivedId)
4981 : {
4982 126 : if (hasAComplexBand ||
4983 126 : CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4984 : "complex")
4985 : {
4986 : oDerivedMetadataList.SetNameValue(
4987 : CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4988 : CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4989 22 : poDDSDesc[derivedId].pszDatasetName,
4990 22 : GetDescription()));
4991 :
4992 : CPLString osDesc(
4993 : CPLSPrintf("%s from %s",
4994 22 : poDDSDesc[derivedId].pszDatasetDescription,
4995 22 : GetDescription()));
4996 : oDerivedMetadataList.SetNameValue(
4997 : CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4998 22 : osDesc.c_str());
4999 :
5000 22 : nNumDataset++;
5001 : }
5002 : }
5003 : }
5004 10 : return oDerivedMetadataList.List();
5005 : }
5006 : #endif
5007 :
5008 71338 : return GDALMajorObject::GetMetadata(pszDomain);
5009 : }
5010 :
5011 : // clang-format off
5012 :
5013 : /**
5014 : * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
5015 : * \brief Set metadata.
5016 : *
5017 : * CAUTION: depending on the format, older values of the updated information
5018 : * might still be found in the file in a "ghost" state, even if no longer
5019 : * accessible through the GDAL API. This is for example the case of the GTiff
5020 : * format (this is not a exhaustive list)
5021 : *
5022 : * The C function GDALSetMetadata() does the same thing as this method.
5023 : *
5024 : * @param papszMetadata the metadata in name=value string list format to
5025 : * apply.
5026 : * @param pszDomain the domain of interest. Use "" or NULL for the default
5027 : * domain.
5028 : * @return CE_None on success, CE_Failure on failure and CE_Warning if the
5029 : * metadata has been accepted, but is likely not maintained persistently
5030 : * by the underlying object between sessions.
5031 : */
5032 :
5033 : /**
5034 : * \fn GDALDataset::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
5035 : * \brief Set single metadata item.
5036 : *
5037 : * CAUTION: depending on the format, older values of the updated information
5038 : * might still be found in the file in a "ghost" state, even if no longer
5039 : * accessible through the GDAL API. This is for example the case of the GTiff
5040 : * format (this is not a exhaustive list)
5041 : *
5042 : * The C function GDALSetMetadataItem() does the same thing as this method.
5043 : *
5044 : * @param pszName the key for the metadata item to fetch.
5045 : * @param pszValue the value to assign to the key.
5046 : * @param pszDomain the domain to set within, use NULL for the default domain.
5047 : *
5048 : * @return CE_None on success, or an error code on failure.
5049 : */
5050 :
5051 : // clang-format on
5052 :
5053 : /************************************************************************/
5054 : /* GetMetadataDomainList() */
5055 : /************************************************************************/
5056 :
5057 1035 : char **GDALDataset::GetMetadataDomainList()
5058 : {
5059 1035 : char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
5060 :
5061 : // Ensure that we do not duplicate DERIVED domain.
5062 1178 : if (GetRasterCount() > 0 &&
5063 143 : CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
5064 : {
5065 : currentDomainList =
5066 143 : CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
5067 : }
5068 1035 : return currentDomainList;
5069 : }
5070 :
5071 : /************************************************************************/
5072 : /* GetDriverName() */
5073 : /************************************************************************/
5074 :
5075 : /** Return driver name.
5076 : * @return driver name.
5077 : */
5078 2057 : const char *GDALDataset::GetDriverName() const
5079 : {
5080 2057 : if (poDriver)
5081 2045 : return poDriver->GetDescription();
5082 12 : return "";
5083 : }
5084 :
5085 : /************************************************************************/
5086 : /* GDALDatasetReleaseResultSet() */
5087 : /************************************************************************/
5088 :
5089 : /**
5090 : \brief Release results of ExecuteSQL().
5091 :
5092 : This function should only be used to deallocate OGRLayers resulting from
5093 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
5094 : results set before destroying the GDALDataset may cause errors.
5095 :
5096 : This function is the same as the C++ method GDALDataset::ReleaseResultSet()
5097 :
5098 :
5099 : @param hDS the dataset handle.
5100 : @param hLayer the result of a previous ExecuteSQL() call.
5101 :
5102 : */
5103 3420 : void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)
5104 :
5105 : {
5106 3420 : VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
5107 :
5108 : #ifdef OGRAPISPY_ENABLED
5109 3420 : if (bOGRAPISpyEnabled)
5110 6 : OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
5111 : #endif
5112 :
5113 6840 : GDALDataset::FromHandle(hDS)->ReleaseResultSet(
5114 3420 : OGRLayer::FromHandle(hLayer));
5115 : }
5116 :
5117 : /************************************************************************/
5118 : /* GDALDatasetGetLayerCount() */
5119 : /************************************************************************/
5120 :
5121 : /**
5122 : \brief Get the number of layers in this dataset.
5123 :
5124 : This function is the same as the C++ method GDALDataset::GetLayerCount()
5125 :
5126 :
5127 : @param hDS the dataset handle.
5128 : @return layer count.
5129 : */
5130 :
5131 1474 : int GDALDatasetGetLayerCount(GDALDatasetH hDS)
5132 :
5133 : {
5134 1474 : VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
5135 :
5136 : #ifdef OGRAPISPY_ENABLED
5137 1474 : if (bOGRAPISpyEnabled)
5138 2 : OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
5139 : #endif
5140 :
5141 1474 : return GDALDataset::FromHandle(hDS)->GetLayerCount();
5142 : }
5143 :
5144 : /************************************************************************/
5145 : /* GDALDatasetGetLayer() */
5146 : /************************************************************************/
5147 :
5148 : /**
5149 : \brief Fetch a layer by index.
5150 :
5151 : The returned layer remains owned by the
5152 : GDALDataset and should not be deleted by the application.
5153 :
5154 : This function is the same as the C++ method GDALDataset::GetLayer()
5155 :
5156 :
5157 : @param hDS the dataset handle.
5158 : @param iLayer a layer number between 0 and GetLayerCount()-1.
5159 :
5160 : @return the layer, or NULL if iLayer is out of range or an error occurs.
5161 : */
5162 :
5163 9585 : OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)
5164 :
5165 : {
5166 9585 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
5167 :
5168 : OGRLayerH hLayer =
5169 9585 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
5170 :
5171 : #ifdef OGRAPISPY_ENABLED
5172 9585 : if (bOGRAPISpyEnabled)
5173 3 : OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
5174 : #endif
5175 :
5176 9585 : return hLayer;
5177 : }
5178 :
5179 : /************************************************************************/
5180 : /* GDALDatasetGetLayerByName() */
5181 : /************************************************************************/
5182 :
5183 : /**
5184 : \brief Fetch a layer by name.
5185 :
5186 : The returned layer remains owned by the
5187 : GDALDataset and should not be deleted by the application.
5188 :
5189 : This function is the same as the C++ method GDALDataset::GetLayerByName()
5190 :
5191 :
5192 : @param hDS the dataset handle.
5193 : @param pszName the layer name of the layer to fetch.
5194 :
5195 : @return the layer, or NULL if Layer is not found or an error occurs.
5196 : */
5197 :
5198 3403 : OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)
5199 :
5200 : {
5201 3403 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
5202 :
5203 3403 : OGRLayerH hLayer = OGRLayer::ToHandle(
5204 3403 : GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
5205 :
5206 : #ifdef OGRAPISPY_ENABLED
5207 3403 : if (bOGRAPISpyEnabled)
5208 4 : OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
5209 : #endif
5210 :
5211 3403 : return hLayer;
5212 : }
5213 :
5214 : /************************************************************************/
5215 : /* GDALDatasetIsLayerPrivate() */
5216 : /************************************************************************/
5217 :
5218 : /**
5219 : \brief Returns true if the layer at the specified index is deemed a private or
5220 : system table, or an internal detail only.
5221 :
5222 : This function is the same as the C++ method GDALDataset::IsLayerPrivate()
5223 :
5224 : @since GDAL 3.4
5225 :
5226 : @param hDS the dataset handle.
5227 : @param iLayer a layer number between 0 and GetLayerCount()-1.
5228 :
5229 : @return true if the layer is a private or system table.
5230 : */
5231 :
5232 91 : int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)
5233 :
5234 : {
5235 91 : VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);
5236 :
5237 91 : const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);
5238 :
5239 91 : return res ? 1 : 0;
5240 : }
5241 :
5242 : /************************************************************************/
5243 : /* GetLayerIndex() */
5244 : /************************************************************************/
5245 :
5246 : /**
5247 : \brief Returns the index of the layer specified by name.
5248 :
5249 : @since GDAL 3.12
5250 :
5251 : @param pszName layer name (not NULL)
5252 :
5253 : @return an index >= 0, or -1 if not found.
5254 : */
5255 :
5256 3 : int GDALDataset::GetLayerIndex(const char *pszName) const
5257 : {
5258 3 : const int nLayerCount = GetLayerCount();
5259 3 : int iMatch = -1;
5260 6 : for (int i = 0; i < nLayerCount; ++i)
5261 : {
5262 5 : if (const auto poLayer = GetLayer(i))
5263 : {
5264 5 : const char *pszLayerName = poLayer->GetDescription();
5265 5 : if (strcmp(pszName, pszLayerName) == 0)
5266 : {
5267 2 : iMatch = i;
5268 2 : break;
5269 : }
5270 3 : else if (EQUAL(pszName, pszLayerName))
5271 : {
5272 0 : iMatch = i;
5273 : }
5274 : }
5275 : }
5276 3 : return iMatch;
5277 : }
5278 :
5279 : /************************************************************************/
5280 : /* GDALDatasetDeleteLayer() */
5281 : /************************************************************************/
5282 :
5283 : /**
5284 : \brief Delete the indicated layer from the datasource.
5285 :
5286 : If this function is supported
5287 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
5288 :
5289 : This method is the same as the C++ method GDALDataset::DeleteLayer().
5290 :
5291 :
5292 : @param hDS the dataset handle.
5293 : @param iLayer the index of the layer to delete.
5294 :
5295 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
5296 : layers is not supported for this datasource.
5297 :
5298 : */
5299 41 : OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)
5300 :
5301 : {
5302 41 : VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
5303 :
5304 : #ifdef OGRAPISPY_ENABLED
5305 41 : if (bOGRAPISpyEnabled)
5306 2 : OGRAPISpy_DS_DeleteLayer(hDS, iLayer);
5307 : #endif
5308 :
5309 41 : return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
5310 : }
5311 :
5312 : /************************************************************************/
5313 : /* CreateLayer() */
5314 : /************************************************************************/
5315 :
5316 : /**
5317 : \brief This method attempts to create a new layer on the dataset with the
5318 : indicated name, coordinate system, geometry type.
5319 :
5320 : The papszOptions argument
5321 : can be used to control driver specific creation options. These options are
5322 : normally documented in the format specific documentation.
5323 : That function will try to validate the creation option list passed to the
5324 : driver with the GDALValidateCreationOptions() method. This check can be
5325 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5326 : to NO.
5327 :
5328 : Drivers should extend the ICreateLayer() method and not
5329 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5330 : delegating the actual work to ICreateLayer().
5331 :
5332 : This method is the same as the C function GDALDatasetCreateLayer() and the
5333 : deprecated OGR_DS_CreateLayer().
5334 :
5335 : Example:
5336 :
5337 : \code{.cpp}
5338 : #include "gdal.h"
5339 : #include "cpl_string.h"
5340 :
5341 : ...
5342 :
5343 : OGRLayer *poLayer;
5344 : char **papszOptions;
5345 :
5346 : if( !poDS->TestCapability( ODsCCreateLayer ) )
5347 : {
5348 : ...
5349 : }
5350 :
5351 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5352 : poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
5353 : papszOptions );
5354 : CSLDestroy( papszOptions );
5355 :
5356 : if( poLayer == NULL )
5357 : {
5358 : ...
5359 : }
5360 : \endcode
5361 :
5362 : @param pszName the name for the new layer. This should ideally not
5363 : match any existing layer on the datasource.
5364 : @param poSpatialRef the coordinate system to use for the new layer, or NULL if
5365 : no coordinate system is available.
5366 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5367 : are no constraints on the types geometry to be written.
5368 : @param papszOptions a StringList of name=value options. Options are driver
5369 : specific.
5370 :
5371 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5372 :
5373 : */
5374 :
5375 8097 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5376 : const OGRSpatialReference *poSpatialRef,
5377 : OGRwkbGeometryType eGType,
5378 : CSLConstList papszOptions)
5379 :
5380 : {
5381 8097 : if (eGType == wkbNone)
5382 : {
5383 512 : return CreateLayer(pszName, nullptr, papszOptions);
5384 : }
5385 : else
5386 : {
5387 15170 : OGRGeomFieldDefn oGeomFieldDefn("", eGType);
5388 7585 : oGeomFieldDefn.SetSpatialRef(poSpatialRef);
5389 7585 : return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5390 : }
5391 : }
5392 :
5393 : /**
5394 : \brief This method attempts to create a new layer on the dataset with the
5395 : indicated name and geometry field definition.
5396 :
5397 : When poGeomFieldDefn is not null, most drivers should honor
5398 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5399 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5400 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5401 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5402 : very few currently.
5403 :
5404 : Note that even if a geometry coordinate precision is set and a driver honors the
5405 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5406 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5407 : with the coordinate precision. That is they are assumed to be valid once their
5408 : coordinates are rounded to it. If it might not be the case, the user may set
5409 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5410 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5411 : the passed geometries.
5412 :
5413 : The papszOptions argument
5414 : can be used to control driver specific creation options. These options are
5415 : normally documented in the format specific documentation.
5416 : This function will try to validate the creation option list passed to the
5417 : driver with the GDALValidateCreationOptions() method. This check can be
5418 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5419 : to NO.
5420 :
5421 : Drivers should extend the ICreateLayer() method and not
5422 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5423 : delegating the actual work to ICreateLayer().
5424 :
5425 : This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().
5426 :
5427 : @param pszName the name for the new layer. This should ideally not
5428 : match any existing layer on the datasource.
5429 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5430 : or NULL if there is no geometry field.
5431 : @param papszOptions a StringList of name=value options. Options are driver
5432 : specific.
5433 :
5434 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5435 : @since 3.9
5436 :
5437 : */
5438 :
5439 9432 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5440 : const OGRGeomFieldDefn *poGeomFieldDefn,
5441 : CSLConstList papszOptions)
5442 :
5443 : {
5444 9432 : if (CPLTestBool(
5445 : CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
5446 : {
5447 9432 : ValidateLayerCreationOptions(papszOptions);
5448 : }
5449 :
5450 : OGRLayer *poLayer;
5451 9432 : if (poGeomFieldDefn)
5452 : {
5453 8534 : OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);
5454 8628 : if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&
5455 94 : !TestCapability(ODsCCurveGeometries))
5456 : {
5457 23 : oGeomFieldDefn.SetType(
5458 : OGR_GT_GetLinear(poGeomFieldDefn->GetType()));
5459 : }
5460 :
5461 8534 : poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5462 : }
5463 : else
5464 : {
5465 898 : poLayer = ICreateLayer(pszName, nullptr, papszOptions);
5466 : }
5467 : #ifdef DEBUG
5468 9503 : if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
5469 71 : !poLayer->TestCapability(OLCCurveGeometries))
5470 : {
5471 0 : CPLError(CE_Warning, CPLE_AppDefined,
5472 : "Inconsistent driver: Layer geometry type is non-linear, but "
5473 : "TestCapability(OLCCurveGeometries) returns FALSE.");
5474 : }
5475 : #endif
5476 :
5477 9432 : return poLayer;
5478 : }
5479 :
5480 : //! @cond Doxygen_Suppress
5481 :
5482 : // Technical override to avoid ambiguous choice between the old and new
5483 : // new CreateLayer() signatures.
5484 11 : OGRLayer *GDALDataset::CreateLayer(const char *pszName)
5485 : {
5486 22 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5487 22 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5488 : }
5489 :
5490 : // Technical override to avoid ambiguous choice between the old and new
5491 : // new CreateLayer() signatures.
5492 1 : OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)
5493 : {
5494 2 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5495 2 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5496 : }
5497 :
5498 : //!@endcond
5499 :
5500 : /************************************************************************/
5501 : /* GDALDatasetCreateLayer() */
5502 : /************************************************************************/
5503 :
5504 : /**
5505 : \brief This function attempts to create a new layer on the dataset with the
5506 : indicated name, coordinate system, geometry type.
5507 :
5508 : The papszOptions argument can be used to control driver specific creation
5509 : options. These options are normally documented in the format specific
5510 : documentation.
5511 :
5512 : This method is the same as the C++ method GDALDataset::CreateLayer().
5513 :
5514 : Example:
5515 :
5516 : \code{.c}
5517 : #include "gdal.h"
5518 : #include "cpl_string.h"
5519 :
5520 : ...
5521 :
5522 : OGRLayerH hLayer;
5523 : char **papszOptions;
5524 :
5525 : if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
5526 : {
5527 : ...
5528 : }
5529 :
5530 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5531 : hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
5532 : papszOptions );
5533 : CSLDestroy( papszOptions );
5534 :
5535 : if( hLayer == NULL )
5536 : {
5537 : ...
5538 : }
5539 : \endcode
5540 :
5541 :
5542 : @param hDS the dataset handle
5543 : @param pszName the name for the new layer. This should ideally not
5544 : match any existing layer on the datasource.
5545 : @param hSpatialRef the coordinate system to use for the new layer, or NULL if
5546 : no coordinate system is available.
5547 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5548 : are no constraints on the types geometry to be written.
5549 : @param papszOptions a StringList of name=value options. Options are driver
5550 : specific.
5551 :
5552 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5553 :
5554 : */
5555 :
5556 6255 : OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,
5557 : OGRSpatialReferenceH hSpatialRef,
5558 : OGRwkbGeometryType eGType,
5559 : CSLConstList papszOptions)
5560 :
5561 : {
5562 6255 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
5563 :
5564 6255 : if (pszName == nullptr)
5565 : {
5566 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5567 : "Name was NULL in GDALDatasetCreateLayer");
5568 0 : return nullptr;
5569 : }
5570 :
5571 : OGRLayerH hLayer =
5572 12510 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5573 6255 : pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,
5574 : const_cast<char **>(papszOptions)));
5575 :
5576 : #ifdef OGRAPISPY_ENABLED
5577 6255 : if (bOGRAPISpyEnabled)
5578 8 : OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,
5579 : const_cast<char **>(papszOptions), hLayer);
5580 : #endif
5581 :
5582 6255 : return hLayer;
5583 : }
5584 :
5585 : /************************************************************************/
5586 : /* GDALDatasetCreateLayerFromGeomFieldDefn() */
5587 : /************************************************************************/
5588 :
5589 : /**
5590 : \brief This function attempts to create a new layer on the dataset with the
5591 : indicated name and geometry field.
5592 :
5593 : When poGeomFieldDefn is not null, most drivers should honor
5594 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5595 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5596 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5597 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5598 : very few currently.
5599 :
5600 : Note that even if a geometry coordinate precision is set and a driver honors the
5601 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5602 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5603 : with the coordinate precision. That is they are assumed to be valid once their
5604 : coordinates are rounded to it. If it might not be the case, the user may set
5605 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5606 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5607 : the passed geometries.
5608 :
5609 : The papszOptions argument can be used to control driver specific creation
5610 : options. These options are normally documented in the format specific
5611 : documentation.
5612 :
5613 : This method is the same as the C++ method GDALDataset::CreateLayer().
5614 :
5615 : @param hDS the dataset handle
5616 : @param pszName the name for the new layer. This should ideally not
5617 : match any existing layer on the datasource.
5618 : @param hGeomFieldDefn the geometry field definition. May be NULL to indicate
5619 : a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()
5620 : for drivers supporting that interface).
5621 : @param papszOptions a StringList of name=value options. Options are driver
5622 : specific.
5623 :
5624 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5625 :
5626 : @since GDAL 3.9
5627 :
5628 : */
5629 :
5630 : OGRLayerH
5631 14 : GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,
5632 : OGRGeomFieldDefnH hGeomFieldDefn,
5633 : CSLConstList papszOptions)
5634 :
5635 : {
5636 14 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);
5637 :
5638 14 : if (!pszName)
5639 : {
5640 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5641 : "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");
5642 0 : return nullptr;
5643 : }
5644 :
5645 : OGRLayerH hLayer =
5646 28 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5647 14 : pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),
5648 : papszOptions));
5649 14 : return hLayer;
5650 : }
5651 :
5652 : /************************************************************************/
5653 : /* GDALDatasetCopyLayer() */
5654 : /************************************************************************/
5655 :
5656 : /**
5657 : \brief Duplicate an existing layer.
5658 :
5659 : This function creates a new layer, duplicate the field definitions of the
5660 : source layer and then duplicate each features of the source layer.
5661 : The papszOptions argument
5662 : can be used to control driver specific creation options. These options are
5663 : normally documented in the format specific documentation.
5664 : The source layer may come from another dataset.
5665 :
5666 : This method is the same as the C++ method GDALDataset::CopyLayer()
5667 :
5668 :
5669 : @param hDS the dataset handle.
5670 : @param hSrcLayer source layer.
5671 : @param pszNewName the name of the layer to create.
5672 : @param papszOptions a StringList of name=value options. Options are driver
5673 : specific.
5674 :
5675 : @return a handle to the layer, or NULL if an error occurs.
5676 : */
5677 18 : OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,
5678 : const char *pszNewName,
5679 : CSLConstList papszOptions)
5680 :
5681 : {
5682 18 : VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
5683 18 : VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
5684 18 : VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
5685 :
5686 36 : return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(
5687 : OGRLayer::FromHandle(hSrcLayer), pszNewName,
5688 36 : const_cast<char **>(papszOptions)));
5689 : }
5690 :
5691 : /************************************************************************/
5692 : /* GDALDatasetExecuteSQL() */
5693 : /************************************************************************/
5694 :
5695 : /**
5696 : \brief Execute an SQL statement against the data store.
5697 :
5698 : The result of an SQL query is either NULL for statements that are in error,
5699 : or that have no results set, or an OGRLayer pointer representing a results
5700 : set from the query. Note that this OGRLayer is in addition to the layers
5701 : in the data store and must be destroyed with
5702 : ReleaseResultSet() before the dataset is closed
5703 : (destroyed).
5704 :
5705 : This method is the same as the C++ method GDALDataset::ExecuteSQL()
5706 :
5707 : For more information on the SQL dialect supported internally by OGR
5708 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
5709 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
5710 : to the underlying RDBMS.
5711 :
5712 : Starting with OGR 1.10, the <a
5713 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
5714 : also be used.
5715 :
5716 :
5717 : @param hDS the dataset handle.
5718 : @param pszStatement the SQL statement to execute.
5719 : @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
5720 :
5721 : @param pszDialect allows control of the statement dialect. If set to NULL, the
5722 : OGR SQL engine will be used, except for RDBMS drivers that will use their
5723 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
5724 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
5725 :
5726 : @return an OGRLayer containing the results of the query. Deallocate with
5727 : GDALDatasetReleaseResultSet().
5728 :
5729 : */
5730 :
5731 10463 : OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,
5732 : OGRGeometryH hSpatialFilter,
5733 : const char *pszDialect)
5734 :
5735 : {
5736 10463 : VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
5737 :
5738 : OGRLayerH hLayer =
5739 20926 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(
5740 10463 : pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));
5741 :
5742 : #ifdef OGRAPISPY_ENABLED
5743 10463 : if (bOGRAPISpyEnabled)
5744 4 : OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,
5745 : hLayer);
5746 : #endif
5747 :
5748 10463 : return hLayer;
5749 : }
5750 :
5751 : /************************************************************************/
5752 : /* GDALDatasetAbortSQL() */
5753 : /************************************************************************/
5754 :
5755 : /**
5756 : \brief Abort any SQL statement running in the data store.
5757 :
5758 : This function can be safely called from any thread (pending that the dataset
5759 : object is still alive). Driver implementations will make sure that it can be
5760 : called in a thread-safe way.
5761 :
5762 : This might not be implemented by all drivers. At time of writing, only SQLite,
5763 : GPKG and PG drivers implement it
5764 :
5765 : This method is the same as the C++ method GDALDataset::AbortSQL()
5766 :
5767 : @since GDAL 3.2.0
5768 :
5769 : @param hDS the dataset handle.
5770 :
5771 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
5772 : is not supported for this datasource. .
5773 :
5774 : */
5775 :
5776 6 : OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)
5777 :
5778 : {
5779 6 : VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);
5780 6 : return GDALDataset::FromHandle(hDS)->AbortSQL();
5781 : }
5782 :
5783 : /************************************************************************/
5784 : /* GDALDatasetGetStyleTable() */
5785 : /************************************************************************/
5786 :
5787 : /**
5788 : \brief Returns dataset style table.
5789 :
5790 : This function is the same as the C++ method GDALDataset::GetStyleTable()
5791 :
5792 :
5793 : @param hDS the dataset handle
5794 : @return handle to a style table which should not be modified or freed by the
5795 : caller.
5796 : */
5797 :
5798 6 : OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)
5799 :
5800 : {
5801 6 : VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
5802 :
5803 : return reinterpret_cast<OGRStyleTableH>(
5804 6 : GDALDataset::FromHandle(hDS)->GetStyleTable());
5805 : }
5806 :
5807 : /************************************************************************/
5808 : /* GDALDatasetSetStyleTableDirectly() */
5809 : /************************************************************************/
5810 :
5811 : /**
5812 : \brief Set dataset style table.
5813 :
5814 : This function operate exactly as GDALDatasetSetStyleTable() except that it
5815 : assumes ownership of the passed table.
5816 :
5817 : This function is the same as the C++ method
5818 : GDALDataset::SetStyleTableDirectly()
5819 :
5820 :
5821 : @param hDS the dataset handle
5822 : @param hStyleTable style table handle to set
5823 :
5824 : */
5825 :
5826 0 : void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,
5827 : OGRStyleTableH hStyleTable)
5828 :
5829 : {
5830 0 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
5831 :
5832 0 : GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(
5833 0 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5834 : }
5835 :
5836 : /************************************************************************/
5837 : /* GDALDatasetSetStyleTable() */
5838 : /************************************************************************/
5839 :
5840 : /**
5841 : \brief Set dataset style table.
5842 :
5843 : This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
5844 : it assumes ownership of the passed table.
5845 :
5846 : This function is the same as the C++ method GDALDataset::SetStyleTable()
5847 :
5848 :
5849 : @param hDS the dataset handle
5850 : @param hStyleTable style table handle to set
5851 :
5852 : */
5853 :
5854 5 : void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)
5855 :
5856 : {
5857 5 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
5858 5 : VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
5859 :
5860 5 : GDALDataset::FromHandle(hDS)->SetStyleTable(
5861 5 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5862 : }
5863 :
5864 : /************************************************************************/
5865 : /* ValidateLayerCreationOptions() */
5866 : /************************************************************************/
5867 :
5868 : //! @cond Doxygen_Suppress
5869 9432 : int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)
5870 : {
5871 : const char *pszOptionList =
5872 9432 : GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5873 9432 : if (pszOptionList == nullptr && poDriver != nullptr)
5874 : {
5875 : pszOptionList =
5876 9391 : poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5877 : }
5878 18864 : CPLString osDataset;
5879 9432 : osDataset.Printf("dataset %s", GetDescription());
5880 9432 : return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",
5881 18864 : osDataset);
5882 : }
5883 :
5884 : //! @endcond
5885 :
5886 : /************************************************************************/
5887 : /* Release() */
5888 : /************************************************************************/
5889 :
5890 : /**
5891 : \brief Drop a reference to this dataset, and if the reference count drops to one
5892 : close (destroy) the dataset.
5893 :
5894 : This method is the same as the C function OGRReleaseDataSource().
5895 :
5896 : @deprecated. Use GDALClose() instead
5897 :
5898 : @return OGRERR_NONE on success or an error code.
5899 : */
5900 :
5901 4292 : OGRErr GDALDataset::Release()
5902 :
5903 : {
5904 4292 : ReleaseRef();
5905 4292 : return OGRERR_NONE;
5906 : }
5907 :
5908 : /************************************************************************/
5909 : /* GetRefCount() */
5910 : /************************************************************************/
5911 :
5912 : /**
5913 : \brief Fetch reference count.
5914 :
5915 : This method is the same as the C function OGR_DS_GetRefCount().
5916 :
5917 : @return the current reference count for the datasource object itself.
5918 : */
5919 :
5920 4921 : int GDALDataset::GetRefCount() const
5921 : {
5922 4921 : return nRefCount;
5923 : }
5924 :
5925 : /************************************************************************/
5926 : /* GetSummaryRefCount() */
5927 : /************************************************************************/
5928 :
5929 : /**
5930 : \brief Fetch reference count of datasource and all owned layers.
5931 :
5932 : This method is the same as the C function OGR_DS_GetSummaryRefCount().
5933 :
5934 : @deprecated
5935 :
5936 : @return the current summary reference count for the datasource and its layers.
5937 : */
5938 :
5939 0 : int GDALDataset::GetSummaryRefCount() const
5940 :
5941 : {
5942 0 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5943 0 : int nSummaryCount = nRefCount;
5944 0 : GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
5945 :
5946 0 : for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)
5947 0 : nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
5948 :
5949 0 : return nSummaryCount;
5950 : }
5951 :
5952 : /************************************************************************/
5953 : /* ICreateLayer() */
5954 : /************************************************************************/
5955 :
5956 : /**
5957 : \brief This method attempts to create a new layer on the dataset with the
5958 : indicated name, coordinate system, geometry type.
5959 :
5960 : This method is reserved to implementation by drivers.
5961 :
5962 : The papszOptions argument can be used to control driver specific creation
5963 : options. These options are normally documented in the format specific
5964 : documentation.
5965 :
5966 : @param pszName the name for the new layer. This should ideally not
5967 : match any existing layer on the datasource.
5968 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5969 : or NULL if there is no geometry field.
5970 : @param papszOptions a StringList of name=value options. Options are driver
5971 : specific.
5972 :
5973 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5974 :
5975 : */
5976 :
5977 : OGRLayer *
5978 16 : GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,
5979 : CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,
5980 : CPL_UNUSED CSLConstList papszOptions)
5981 :
5982 : {
5983 16 : CPLError(CE_Failure, CPLE_NotSupported,
5984 : "CreateLayer() not supported by this dataset.");
5985 :
5986 16 : return nullptr;
5987 : }
5988 :
5989 : /************************************************************************/
5990 : /* CopyLayer() */
5991 : /************************************************************************/
5992 :
5993 : /**
5994 : \brief Duplicate an existing layer.
5995 :
5996 : This method creates a new layer, duplicate the field definitions of the
5997 : source layer and then duplicate each features of the source layer.
5998 : The papszOptions argument
5999 : can be used to control driver specific creation options. These options are
6000 : normally documented in the format specific documentation.
6001 : The source layer may come from another dataset.
6002 :
6003 : This method is the same as the C function GDALDatasetCopyLayer() and the
6004 : deprecated OGR_DS_CopyLayer().
6005 :
6006 : @param poSrcLayer source layer.
6007 : @param pszNewName the name of the layer to create.
6008 : @param papszOptions a StringList of name=value options. Options are driver
6009 : specific. There is a common option to set output layer
6010 : spatial reference: DST_SRSWKT. The option should be in
6011 : WKT format. Starting with GDAL 3.7, the common option
6012 : COPY_MD can be set to NO to prevent the default copying
6013 : of the metadata from the source layer to the target layer.
6014 :
6015 : @return a handle to the layer, or NULL if an error occurs.
6016 : */
6017 :
6018 134 : OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
6019 : char **papszOptions)
6020 :
6021 : {
6022 : /* -------------------------------------------------------------------- */
6023 : /* Create the layer. */
6024 : /* -------------------------------------------------------------------- */
6025 134 : if (!TestCapability(ODsCCreateLayer))
6026 : {
6027 0 : CPLError(CE_Failure, CPLE_NotSupported,
6028 : "This datasource does not support creation of layers.");
6029 0 : return nullptr;
6030 : }
6031 :
6032 134 : const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
6033 268 : OGRSpatialReference oDstSpaRef(pszSRSWKT);
6034 134 : oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
6035 134 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
6036 134 : OGRLayer *poDstLayer = nullptr;
6037 :
6038 268 : CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));
6039 134 : aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr);
6040 134 : aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr);
6041 :
6042 134 : CPLErrorReset();
6043 134 : const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
6044 134 : if (nSrcGeomFieldCount == 1)
6045 : {
6046 82 : OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
6047 82 : if (pszSRSWKT)
6048 5 : oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);
6049 82 : poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,
6050 82 : aosCleanedUpOptions.List());
6051 : }
6052 : else
6053 : {
6054 : poDstLayer =
6055 52 : ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());
6056 : }
6057 :
6058 134 : if (poDstLayer == nullptr)
6059 0 : return nullptr;
6060 :
6061 134 : if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))
6062 : {
6063 133 : char **papszMD = poSrcLayer->GetMetadata();
6064 133 : if (papszMD)
6065 8 : poDstLayer->SetMetadata(papszMD);
6066 : }
6067 :
6068 : /* -------------------------------------------------------------------- */
6069 : /* Add fields. Default to copy all fields, and make sure to */
6070 : /* establish a mapping between indices, rather than names, in */
6071 : /* case the target datasource has altered it (e.g. Shapefile */
6072 : /* limited to 10 char field names). */
6073 : /* -------------------------------------------------------------------- */
6074 134 : const int nSrcFieldCount = poSrcDefn->GetFieldCount();
6075 :
6076 : // Initialize the index-to-index map to -1's.
6077 268 : std::vector<int> anMap(nSrcFieldCount, -1);
6078 :
6079 : // Caution: At the time of writing, the MapInfo driver
6080 : // returns NULL until a field has been added.
6081 134 : OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
6082 134 : int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
6083 288 : for (int iField = 0; iField < nSrcFieldCount; ++iField)
6084 : {
6085 154 : OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
6086 308 : OGRFieldDefn oFieldDefn(poSrcFieldDefn);
6087 :
6088 : // The field may have been already created at layer creation.
6089 154 : int iDstField = -1;
6090 154 : if (poDstFDefn)
6091 154 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
6092 154 : if (iDstField >= 0)
6093 : {
6094 0 : anMap[iField] = iDstField;
6095 : }
6096 154 : else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)
6097 : {
6098 : // Now that we've created a field, GetLayerDefn() won't return NULL.
6099 154 : if (poDstFDefn == nullptr)
6100 0 : poDstFDefn = poDstLayer->GetLayerDefn();
6101 :
6102 : // Sanity check: if it fails, the driver is buggy.
6103 308 : if (poDstFDefn != nullptr &&
6104 154 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
6105 : {
6106 0 : CPLError(CE_Warning, CPLE_AppDefined,
6107 : "The output driver has claimed to have added the %s "
6108 : "field, but it did not!",
6109 : oFieldDefn.GetNameRef());
6110 : }
6111 : else
6112 : {
6113 154 : anMap[iField] = nDstFieldCount;
6114 154 : ++nDstFieldCount;
6115 : }
6116 : }
6117 : }
6118 :
6119 : /* -------------------------------------------------------------------- */
6120 134 : std::unique_ptr<OGRCoordinateTransformation> poCT;
6121 134 : const OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
6122 134 : if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&
6123 0 : sourceSRS->IsSame(&oDstSpaRef) == FALSE)
6124 : {
6125 0 : poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));
6126 0 : if (nullptr == poCT)
6127 : {
6128 0 : CPLError(CE_Failure, CPLE_NotSupported,
6129 : "This input/output spatial reference is not supported.");
6130 0 : return nullptr;
6131 : }
6132 : }
6133 : /* -------------------------------------------------------------------- */
6134 : /* Create geometry fields. */
6135 : /* -------------------------------------------------------------------- */
6136 135 : if (nSrcGeomFieldCount > 1 &&
6137 1 : TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
6138 : {
6139 :
6140 3 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6141 : {
6142 2 : if (nullptr == pszSRSWKT)
6143 : {
6144 2 : poDstLayer->CreateGeomField(
6145 2 : poSrcDefn->GetGeomFieldDefn(iField));
6146 : }
6147 : else
6148 : {
6149 : OGRGeomFieldDefn *pDstGeomFieldDefn =
6150 0 : poSrcDefn->GetGeomFieldDefn(iField);
6151 0 : pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
6152 0 : poDstLayer->CreateGeomField(pDstGeomFieldDefn);
6153 : }
6154 : }
6155 : }
6156 :
6157 : /* -------------------------------------------------------------------- */
6158 : /* Check if the destination layer supports transactions and set a */
6159 : /* default number of features in a single transaction. */
6160 : /* -------------------------------------------------------------------- */
6161 : const int nGroupTransactions =
6162 134 : poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
6163 :
6164 : /* -------------------------------------------------------------------- */
6165 : /* Transfer features. */
6166 : /* -------------------------------------------------------------------- */
6167 134 : poSrcLayer->ResetReading();
6168 :
6169 134 : if (nGroupTransactions <= 0)
6170 : {
6171 : while (true)
6172 : {
6173 : auto poFeature =
6174 453 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
6175 :
6176 453 : if (poFeature == nullptr)
6177 131 : break;
6178 :
6179 322 : CPLErrorReset();
6180 : auto poDstFeature =
6181 322 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
6182 :
6183 322 : if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=
6184 : OGRERR_NONE)
6185 : {
6186 0 : CPLError(CE_Failure, CPLE_AppDefined,
6187 : "Unable to translate feature " CPL_FRMT_GIB
6188 : " from layer %s.",
6189 0 : poFeature->GetFID(), poSrcDefn->GetName());
6190 0 : return poDstLayer;
6191 : }
6192 :
6193 322 : if (nullptr != poCT)
6194 : {
6195 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6196 : {
6197 0 : OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
6198 0 : if (nullptr == pGeom)
6199 0 : continue;
6200 :
6201 0 : const OGRErr eErr = pGeom->transform(poCT.get());
6202 0 : if (eErr == OGRERR_NONE)
6203 0 : continue;
6204 :
6205 0 : CPLError(CE_Failure, CPLE_AppDefined,
6206 : "Unable to transform geometry " CPL_FRMT_GIB
6207 : " from layer %s.",
6208 0 : poFeature->GetFID(), poSrcDefn->GetName());
6209 0 : return poDstLayer;
6210 : }
6211 : }
6212 :
6213 322 : poDstFeature->SetFID(poFeature->GetFID());
6214 :
6215 322 : CPLErrorReset();
6216 322 : if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)
6217 : {
6218 0 : return poDstLayer;
6219 : }
6220 322 : }
6221 : }
6222 : else
6223 : {
6224 3 : std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;
6225 : try
6226 : {
6227 3 : apoDstFeatures.resize(nGroupTransactions);
6228 : }
6229 0 : catch (const std::exception &e)
6230 : {
6231 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
6232 0 : return poDstLayer;
6233 : }
6234 3 : bool bStopTransfer = false;
6235 6 : while (!bStopTransfer)
6236 : {
6237 : /* --------------------------------------------------------------------
6238 : */
6239 : /* Fill the array with features. */
6240 : /* --------------------------------------------------------------------
6241 : */
6242 : // Number of features in the temporary array.
6243 3 : int nFeatCount = 0; // Used after for.
6244 33 : for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)
6245 : {
6246 : auto poFeature =
6247 33 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
6248 :
6249 33 : if (poFeature == nullptr)
6250 : {
6251 3 : bStopTransfer = true;
6252 3 : break;
6253 : }
6254 :
6255 30 : CPLErrorReset();
6256 30 : apoDstFeatures[nFeatCount] =
6257 60 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
6258 :
6259 60 : if (apoDstFeatures[nFeatCount]->SetFrom(
6260 60 : poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)
6261 : {
6262 0 : CPLError(CE_Failure, CPLE_AppDefined,
6263 : "Unable to translate feature " CPL_FRMT_GIB
6264 : " from layer %s.",
6265 0 : poFeature->GetFID(), poSrcDefn->GetName());
6266 0 : bStopTransfer = true;
6267 0 : poFeature.reset();
6268 0 : break;
6269 : }
6270 :
6271 30 : if (nullptr != poCT)
6272 : {
6273 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6274 : {
6275 : OGRGeometry *pGeom =
6276 0 : apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);
6277 0 : if (nullptr == pGeom)
6278 0 : continue;
6279 :
6280 0 : const OGRErr eErr = pGeom->transform(poCT.get());
6281 0 : if (eErr == OGRERR_NONE)
6282 0 : continue;
6283 :
6284 0 : CPLError(CE_Failure, CPLE_AppDefined,
6285 : "Unable to transform geometry " CPL_FRMT_GIB
6286 : " from layer %s.",
6287 0 : poFeature->GetFID(), poSrcDefn->GetName());
6288 0 : bStopTransfer = true;
6289 0 : poFeature.reset();
6290 0 : break;
6291 : }
6292 : }
6293 :
6294 30 : if (poFeature)
6295 : {
6296 30 : apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());
6297 : }
6298 : }
6299 :
6300 3 : CPLErrorReset();
6301 3 : bool bStopTransaction = false;
6302 6 : while (!bStopTransaction)
6303 : {
6304 3 : bStopTransaction = true;
6305 3 : if (poDstLayer->StartTransaction() != OGRERR_NONE)
6306 0 : break;
6307 33 : for (int i = 0; i < nFeatCount; ++i)
6308 : {
6309 30 : if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=
6310 : OGRERR_NONE)
6311 : {
6312 0 : bStopTransfer = true;
6313 0 : bStopTransaction = false;
6314 0 : break;
6315 : }
6316 30 : apoDstFeatures[i].reset();
6317 : }
6318 3 : if (bStopTransaction)
6319 : {
6320 3 : if (poDstLayer->CommitTransaction() != OGRERR_NONE)
6321 0 : break;
6322 : }
6323 : else
6324 : {
6325 0 : poDstLayer->RollbackTransaction();
6326 : }
6327 : }
6328 : }
6329 : }
6330 :
6331 134 : return poDstLayer;
6332 : }
6333 :
6334 : /************************************************************************/
6335 : /* DeleteLayer() */
6336 : /************************************************************************/
6337 :
6338 : /**
6339 : \fn GDALDataset::DeleteLayer(int)
6340 : \brief Delete the indicated layer from the datasource.
6341 :
6342 : If this method is supported
6343 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
6344 :
6345 : This method is the same as the C function GDALDatasetDeleteLayer() and the
6346 : deprecated OGR_DS_DeleteLayer().
6347 :
6348 : @param iLayer the index of the layer to delete.
6349 :
6350 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
6351 : layers is not supported for this datasource.
6352 :
6353 : */
6354 :
6355 389 : OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)
6356 :
6357 : {
6358 389 : CPLError(CE_Failure, CPLE_NotSupported,
6359 : "DeleteLayer() not supported by this dataset.");
6360 :
6361 389 : return OGRERR_UNSUPPORTED_OPERATION;
6362 : }
6363 :
6364 : /************************************************************************/
6365 : /* GetLayerByName() */
6366 : /************************************************************************/
6367 :
6368 : /**
6369 : \brief Fetch a layer by name.
6370 :
6371 : The returned layer remains owned by the
6372 : GDALDataset and should not be deleted by the application.
6373 :
6374 : This method is the same as the C function GDALDatasetGetLayerByName() and the
6375 : deprecated OGR_DS_GetLayerByName().
6376 :
6377 : @param pszName the layer name of the layer to fetch.
6378 :
6379 : @return the layer, or NULL if Layer is not found or an error occurs.
6380 : */
6381 :
6382 29865 : OGRLayer *GDALDataset::GetLayerByName(const char *pszName)
6383 :
6384 : {
6385 59730 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
6386 :
6387 29865 : if (!pszName)
6388 0 : return nullptr;
6389 :
6390 : // First a case sensitive check.
6391 932395 : for (int i = 0; i < GetLayerCount(); ++i)
6392 : {
6393 914236 : OGRLayer *poLayer = GetLayer(i);
6394 :
6395 914236 : if (strcmp(pszName, poLayer->GetName()) == 0)
6396 11706 : return poLayer;
6397 : }
6398 :
6399 : // Then case insensitive.
6400 893761 : for (int i = 0; i < GetLayerCount(); ++i)
6401 : {
6402 875826 : OGRLayer *poLayer = GetLayer(i);
6403 :
6404 875826 : if (EQUAL(pszName, poLayer->GetName()))
6405 224 : return poLayer;
6406 : }
6407 :
6408 17935 : return nullptr;
6409 : }
6410 :
6411 : //! @cond Doxygen_Suppress
6412 : /************************************************************************/
6413 : /* ProcessSQLCreateIndex() */
6414 : /* */
6415 : /* The correct syntax for creating an index in our dialect of */
6416 : /* SQL is: */
6417 : /* */
6418 : /* CREATE INDEX ON <layername> USING <columnname> */
6419 : /************************************************************************/
6420 :
6421 28 : OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)
6422 :
6423 : {
6424 28 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6425 :
6426 : /* -------------------------------------------------------------------- */
6427 : /* Do some general syntax checking. */
6428 : /* -------------------------------------------------------------------- */
6429 56 : if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||
6430 84 : !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||
6431 28 : !EQUAL(papszTokens[4], "USING"))
6432 : {
6433 0 : CSLDestroy(papszTokens);
6434 0 : CPLError(CE_Failure, CPLE_AppDefined,
6435 : "Syntax error in CREATE INDEX command.\n"
6436 : "Was '%s'\n"
6437 : "Should be of form 'CREATE INDEX ON <table> USING <field>'",
6438 : pszSQLCommand);
6439 0 : return OGRERR_FAILURE;
6440 : }
6441 :
6442 : /* -------------------------------------------------------------------- */
6443 : /* Find the named layer. */
6444 : /* -------------------------------------------------------------------- */
6445 28 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6446 28 : if (poLayer == nullptr)
6447 : {
6448 0 : CPLError(CE_Failure, CPLE_AppDefined,
6449 : "CREATE INDEX ON failed, no such layer as `%s'.",
6450 0 : papszTokens[3]);
6451 0 : CSLDestroy(papszTokens);
6452 0 : return OGRERR_FAILURE;
6453 : }
6454 :
6455 : /* -------------------------------------------------------------------- */
6456 : /* Does this layer even support attribute indexes? */
6457 : /* -------------------------------------------------------------------- */
6458 28 : if (poLayer->GetIndex() == nullptr)
6459 : {
6460 0 : CPLError(CE_Failure, CPLE_AppDefined,
6461 : "CREATE INDEX ON not supported by this driver.");
6462 0 : CSLDestroy(papszTokens);
6463 0 : return OGRERR_FAILURE;
6464 : }
6465 :
6466 : /* -------------------------------------------------------------------- */
6467 : /* Find the named field. */
6468 : /* -------------------------------------------------------------------- */
6469 28 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6470 :
6471 28 : CSLDestroy(papszTokens);
6472 :
6473 28 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6474 : {
6475 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6476 : pszSQLCommand);
6477 0 : return OGRERR_FAILURE;
6478 : }
6479 :
6480 : /* -------------------------------------------------------------------- */
6481 : /* Attempt to create the index. */
6482 : /* -------------------------------------------------------------------- */
6483 28 : OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
6484 28 : if (eErr == OGRERR_NONE)
6485 : {
6486 28 : eErr = poLayer->GetIndex()->IndexAllFeatures(i);
6487 : }
6488 : else
6489 : {
6490 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
6491 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
6492 : }
6493 :
6494 28 : return eErr;
6495 : }
6496 :
6497 : /************************************************************************/
6498 : /* ProcessSQLDropIndex() */
6499 : /* */
6500 : /* The correct syntax for dropping one or more indexes in */
6501 : /* the OGR SQL dialect is: */
6502 : /* */
6503 : /* DROP INDEX ON <layername> [USING <columnname>] */
6504 : /************************************************************************/
6505 :
6506 10 : OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)
6507 :
6508 : {
6509 10 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6510 :
6511 : /* -------------------------------------------------------------------- */
6512 : /* Do some general syntax checking. */
6513 : /* -------------------------------------------------------------------- */
6514 20 : if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||
6515 10 : !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||
6516 30 : !EQUAL(papszTokens[2], "ON") ||
6517 10 : (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))
6518 : {
6519 0 : CSLDestroy(papszTokens);
6520 0 : CPLError(CE_Failure, CPLE_AppDefined,
6521 : "Syntax error in DROP INDEX command.\n"
6522 : "Was '%s'\n"
6523 : "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
6524 : pszSQLCommand);
6525 0 : return OGRERR_FAILURE;
6526 : }
6527 :
6528 : /* -------------------------------------------------------------------- */
6529 : /* Find the named layer. */
6530 : /* -------------------------------------------------------------------- */
6531 10 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6532 10 : if (poLayer == nullptr)
6533 : {
6534 0 : CPLError(CE_Failure, CPLE_AppDefined,
6535 : "DROP INDEX ON failed, no such layer as `%s'.",
6536 0 : papszTokens[3]);
6537 0 : CSLDestroy(papszTokens);
6538 0 : return OGRERR_FAILURE;
6539 : }
6540 :
6541 : /* -------------------------------------------------------------------- */
6542 : /* Does this layer even support attribute indexes? */
6543 : /* -------------------------------------------------------------------- */
6544 10 : if (poLayer->GetIndex() == nullptr)
6545 : {
6546 0 : CPLError(CE_Failure, CPLE_AppDefined,
6547 : "Indexes not supported by this driver.");
6548 0 : CSLDestroy(papszTokens);
6549 0 : return OGRERR_FAILURE;
6550 : }
6551 :
6552 : /* -------------------------------------------------------------------- */
6553 : /* If we were not given a field name, drop all indexes. */
6554 : /* -------------------------------------------------------------------- */
6555 10 : if (CSLCount(papszTokens) == 4)
6556 : {
6557 0 : for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)
6558 : {
6559 : OGRAttrIndex *poAttrIndex;
6560 :
6561 0 : poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
6562 0 : if (poAttrIndex != nullptr)
6563 : {
6564 0 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6565 0 : if (eErr != OGRERR_NONE)
6566 : {
6567 0 : CSLDestroy(papszTokens);
6568 0 : return eErr;
6569 : }
6570 : }
6571 : }
6572 :
6573 0 : CSLDestroy(papszTokens);
6574 0 : return OGRERR_NONE;
6575 : }
6576 :
6577 : /* -------------------------------------------------------------------- */
6578 : /* Find the named field. */
6579 : /* -------------------------------------------------------------------- */
6580 10 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6581 10 : CSLDestroy(papszTokens);
6582 :
6583 10 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6584 : {
6585 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6586 : pszSQLCommand);
6587 0 : return OGRERR_FAILURE;
6588 : }
6589 :
6590 : /* -------------------------------------------------------------------- */
6591 : /* Attempt to drop the index. */
6592 : /* -------------------------------------------------------------------- */
6593 10 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6594 :
6595 10 : return eErr;
6596 : }
6597 :
6598 : /************************************************************************/
6599 : /* ProcessSQLDropTable() */
6600 : /* */
6601 : /* The correct syntax for dropping a table (layer) in the OGR SQL */
6602 : /* dialect is: */
6603 : /* */
6604 : /* DROP TABLE <layername> */
6605 : /************************************************************************/
6606 :
6607 500 : OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)
6608 :
6609 : {
6610 500 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6611 :
6612 : /* -------------------------------------------------------------------- */
6613 : /* Do some general syntax checking. */
6614 : /* -------------------------------------------------------------------- */
6615 1000 : if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||
6616 500 : !EQUAL(papszTokens[1], "TABLE"))
6617 : {
6618 0 : CSLDestroy(papszTokens);
6619 0 : CPLError(CE_Failure, CPLE_AppDefined,
6620 : "Syntax error in DROP TABLE command.\n"
6621 : "Was '%s'\n"
6622 : "Should be of form 'DROP TABLE <table>'",
6623 : pszSQLCommand);
6624 0 : return OGRERR_FAILURE;
6625 : }
6626 :
6627 : /* -------------------------------------------------------------------- */
6628 : /* Find the named layer. */
6629 : /* -------------------------------------------------------------------- */
6630 500 : OGRLayer *poLayer = nullptr;
6631 :
6632 500 : int i = 0; // Used after for.
6633 40199 : for (; i < GetLayerCount(); ++i)
6634 : {
6635 40199 : poLayer = GetLayer(i);
6636 :
6637 40199 : if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))
6638 500 : break;
6639 39699 : poLayer = nullptr;
6640 : }
6641 :
6642 500 : if (poLayer == nullptr)
6643 : {
6644 0 : CPLError(CE_Failure, CPLE_AppDefined,
6645 0 : "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
6646 0 : CSLDestroy(papszTokens);
6647 0 : return OGRERR_FAILURE;
6648 : }
6649 :
6650 500 : CSLDestroy(papszTokens);
6651 :
6652 : /* -------------------------------------------------------------------- */
6653 : /* Delete it. */
6654 : /* -------------------------------------------------------------------- */
6655 :
6656 500 : return DeleteLayer(i);
6657 : }
6658 :
6659 : //! @endcond
6660 :
6661 : /************************************************************************/
6662 : /* GDALDatasetParseSQLType() */
6663 : /************************************************************************/
6664 :
6665 : /* All arguments will be altered */
6666 6 : static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
6667 : int &nPrecision)
6668 : {
6669 6 : char *pszParenthesis = strchr(pszType, '(');
6670 6 : if (pszParenthesis)
6671 : {
6672 4 : nWidth = atoi(pszParenthesis + 1);
6673 4 : *pszParenthesis = '\0';
6674 4 : char *pszComma = strchr(pszParenthesis + 1, ',');
6675 4 : if (pszComma)
6676 2 : nPrecision = atoi(pszComma + 1);
6677 : }
6678 :
6679 6 : OGRFieldType eType = OFTString;
6680 6 : if (EQUAL(pszType, "INTEGER"))
6681 0 : eType = OFTInteger;
6682 6 : else if (EQUAL(pszType, "INTEGER[]"))
6683 0 : eType = OFTIntegerList;
6684 6 : else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||
6685 4 : EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
6686 4 : EQUAL(pszType, "REAL") /* unofficial alias */)
6687 2 : eType = OFTReal;
6688 4 : else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||
6689 4 : EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
6690 4 : EQUAL(pszType, "REAL[]") /* unofficial alias */)
6691 0 : eType = OFTRealList;
6692 4 : else if (EQUAL(pszType, "CHARACTER") ||
6693 0 : EQUAL(pszType, "TEXT") /* unofficial alias */ ||
6694 0 : EQUAL(pszType, "STRING") /* unofficial alias */ ||
6695 0 : EQUAL(pszType, "VARCHAR") /* unofficial alias */)
6696 4 : eType = OFTString;
6697 0 : else if (EQUAL(pszType, "TEXT[]") ||
6698 0 : EQUAL(pszType, "STRING[]") /* unofficial alias */ ||
6699 0 : EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
6700 0 : eType = OFTStringList;
6701 0 : else if (EQUAL(pszType, "DATE"))
6702 0 : eType = OFTDate;
6703 0 : else if (EQUAL(pszType, "TIME"))
6704 0 : eType = OFTTime;
6705 0 : else if (EQUAL(pszType, "TIMESTAMP") ||
6706 0 : EQUAL(pszType, "DATETIME") /* unofficial alias */)
6707 0 : eType = OFTDateTime;
6708 : else
6709 0 : CPLError(CE_Warning, CPLE_NotSupported,
6710 : "Unsupported column type '%s'. Defaulting to VARCHAR",
6711 : pszType);
6712 :
6713 6 : return eType;
6714 : }
6715 :
6716 : /************************************************************************/
6717 : /* ProcessSQLAlterTableAddColumn() */
6718 : /* */
6719 : /* The correct syntax for adding a column in the OGR SQL */
6720 : /* dialect is: */
6721 : /* */
6722 : /* ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
6723 : /************************************************************************/
6724 :
6725 : //! @cond Doxygen_Suppress
6726 2 : OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)
6727 :
6728 : {
6729 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6730 :
6731 : /* -------------------------------------------------------------------- */
6732 : /* Do some general syntax checking. */
6733 : /* -------------------------------------------------------------------- */
6734 2 : const char *pszLayerName = nullptr;
6735 2 : const char *pszColumnName = nullptr;
6736 2 : int iTypeIndex = 0;
6737 2 : const int nTokens = CSLCount(papszTokens);
6738 :
6739 2 : if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6740 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&
6741 2 : EQUAL(papszTokens[4], "COLUMN"))
6742 : {
6743 1 : pszLayerName = papszTokens[2];
6744 1 : pszColumnName = papszTokens[5];
6745 1 : iTypeIndex = 6;
6746 : }
6747 1 : else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&
6748 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))
6749 : {
6750 1 : pszLayerName = papszTokens[2];
6751 1 : pszColumnName = papszTokens[4];
6752 1 : iTypeIndex = 5;
6753 : }
6754 : else
6755 : {
6756 0 : CSLDestroy(papszTokens);
6757 0 : CPLError(CE_Failure, CPLE_AppDefined,
6758 : "Syntax error in ALTER TABLE ADD COLUMN command.\n"
6759 : "Was '%s'\n"
6760 : "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
6761 : "<columnname> <columntype>'",
6762 : pszSQLCommand);
6763 0 : return OGRERR_FAILURE;
6764 : }
6765 :
6766 : /* -------------------------------------------------------------------- */
6767 : /* Merge type components into a single string if there were split */
6768 : /* with spaces */
6769 : /* -------------------------------------------------------------------- */
6770 4 : CPLString osType;
6771 6 : for (int i = iTypeIndex; i < nTokens; ++i)
6772 : {
6773 4 : osType += papszTokens[i];
6774 4 : CPLFree(papszTokens[i]);
6775 : }
6776 2 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6777 2 : papszTokens[iTypeIndex + 1] = nullptr;
6778 :
6779 : /* -------------------------------------------------------------------- */
6780 : /* Find the named layer. */
6781 : /* -------------------------------------------------------------------- */
6782 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6783 2 : if (poLayer == nullptr)
6784 : {
6785 0 : CPLError(CE_Failure, CPLE_AppDefined,
6786 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6787 : pszLayerName);
6788 0 : CSLDestroy(papszTokens);
6789 0 : return OGRERR_FAILURE;
6790 : }
6791 :
6792 : /* -------------------------------------------------------------------- */
6793 : /* Add column. */
6794 : /* -------------------------------------------------------------------- */
6795 :
6796 2 : int nWidth = 0;
6797 2 : int nPrecision = 0;
6798 2 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6799 4 : OGRFieldDefn oFieldDefn(pszColumnName, eType);
6800 2 : oFieldDefn.SetWidth(nWidth);
6801 2 : oFieldDefn.SetPrecision(nPrecision);
6802 :
6803 2 : CSLDestroy(papszTokens);
6804 :
6805 2 : return poLayer->CreateField(&oFieldDefn);
6806 : }
6807 :
6808 : /************************************************************************/
6809 : /* ProcessSQLAlterTableDropColumn() */
6810 : /* */
6811 : /* The correct syntax for dropping a column in the OGR SQL */
6812 : /* dialect is: */
6813 : /* */
6814 : /* ALTER TABLE <layername> DROP [COLUMN] <columnname> */
6815 : /************************************************************************/
6816 :
6817 2 : OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)
6818 :
6819 : {
6820 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6821 :
6822 : /* -------------------------------------------------------------------- */
6823 : /* Do some general syntax checking. */
6824 : /* -------------------------------------------------------------------- */
6825 2 : const char *pszLayerName = nullptr;
6826 2 : const char *pszColumnName = nullptr;
6827 3 : if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&
6828 4 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&
6829 1 : EQUAL(papszTokens[4], "COLUMN"))
6830 : {
6831 1 : pszLayerName = papszTokens[2];
6832 1 : pszColumnName = papszTokens[5];
6833 : }
6834 2 : else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&
6835 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))
6836 : {
6837 1 : pszLayerName = papszTokens[2];
6838 1 : pszColumnName = papszTokens[4];
6839 : }
6840 : else
6841 : {
6842 0 : CSLDestroy(papszTokens);
6843 0 : CPLError(CE_Failure, CPLE_AppDefined,
6844 : "Syntax error in ALTER TABLE DROP COLUMN command.\n"
6845 : "Was '%s'\n"
6846 : "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
6847 : "<columnname>'",
6848 : pszSQLCommand);
6849 0 : return OGRERR_FAILURE;
6850 : }
6851 :
6852 : /* -------------------------------------------------------------------- */
6853 : /* Find the named layer. */
6854 : /* -------------------------------------------------------------------- */
6855 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6856 2 : if (poLayer == nullptr)
6857 : {
6858 0 : CPLError(CE_Failure, CPLE_AppDefined,
6859 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6860 : pszLayerName);
6861 0 : CSLDestroy(papszTokens);
6862 0 : return OGRERR_FAILURE;
6863 : }
6864 :
6865 : /* -------------------------------------------------------------------- */
6866 : /* Find the field. */
6867 : /* -------------------------------------------------------------------- */
6868 :
6869 2 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6870 2 : if (nFieldIndex < 0)
6871 : {
6872 0 : CPLError(CE_Failure, CPLE_AppDefined,
6873 : "%s failed, no such field as `%s'.", pszSQLCommand,
6874 : pszColumnName);
6875 0 : CSLDestroy(papszTokens);
6876 0 : return OGRERR_FAILURE;
6877 : }
6878 :
6879 : /* -------------------------------------------------------------------- */
6880 : /* Remove it. */
6881 : /* -------------------------------------------------------------------- */
6882 :
6883 2 : CSLDestroy(papszTokens);
6884 :
6885 2 : return poLayer->DeleteField(nFieldIndex);
6886 : }
6887 :
6888 : /************************************************************************/
6889 : /* ProcessSQLAlterTableRenameColumn() */
6890 : /* */
6891 : /* The correct syntax for renaming a column in the OGR SQL */
6892 : /* dialect is: */
6893 : /* */
6894 : /* ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
6895 : /************************************************************************/
6896 :
6897 2 : OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)
6898 :
6899 : {
6900 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6901 :
6902 : /* -------------------------------------------------------------------- */
6903 : /* Do some general syntax checking. */
6904 : /* -------------------------------------------------------------------- */
6905 2 : const char *pszLayerName = nullptr;
6906 2 : const char *pszOldColName = nullptr;
6907 2 : const char *pszNewColName = nullptr;
6908 3 : if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&
6909 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&
6910 3 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))
6911 : {
6912 1 : pszLayerName = papszTokens[2];
6913 1 : pszOldColName = papszTokens[5];
6914 1 : pszNewColName = papszTokens[7];
6915 : }
6916 2 : else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&
6917 1 : EQUAL(papszTokens[1], "TABLE") &&
6918 2 : EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))
6919 : {
6920 1 : pszLayerName = papszTokens[2];
6921 1 : pszOldColName = papszTokens[4];
6922 1 : pszNewColName = papszTokens[6];
6923 : }
6924 : else
6925 : {
6926 0 : CSLDestroy(papszTokens);
6927 0 : CPLError(CE_Failure, CPLE_AppDefined,
6928 : "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
6929 : "Was '%s'\n"
6930 : "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
6931 : "<columnname> TO <newname>'",
6932 : pszSQLCommand);
6933 0 : return OGRERR_FAILURE;
6934 : }
6935 :
6936 : /* -------------------------------------------------------------------- */
6937 : /* Find the named layer. */
6938 : /* -------------------------------------------------------------------- */
6939 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6940 2 : if (poLayer == nullptr)
6941 : {
6942 0 : CPLError(CE_Failure, CPLE_AppDefined,
6943 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6944 : pszLayerName);
6945 0 : CSLDestroy(papszTokens);
6946 0 : return OGRERR_FAILURE;
6947 : }
6948 :
6949 : /* -------------------------------------------------------------------- */
6950 : /* Find the field. */
6951 : /* -------------------------------------------------------------------- */
6952 :
6953 : const int nFieldIndex =
6954 2 : poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
6955 2 : if (nFieldIndex < 0)
6956 : {
6957 0 : CPLError(CE_Failure, CPLE_AppDefined,
6958 : "%s failed, no such field as `%s'.", pszSQLCommand,
6959 : pszOldColName);
6960 0 : CSLDestroy(papszTokens);
6961 0 : return OGRERR_FAILURE;
6962 : }
6963 :
6964 : /* -------------------------------------------------------------------- */
6965 : /* Rename column. */
6966 : /* -------------------------------------------------------------------- */
6967 : OGRFieldDefn *poOldFieldDefn =
6968 2 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6969 4 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6970 2 : oNewFieldDefn.SetName(pszNewColName);
6971 :
6972 2 : CSLDestroy(papszTokens);
6973 :
6974 2 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6975 2 : ALTER_NAME_FLAG);
6976 : }
6977 :
6978 : /************************************************************************/
6979 : /* ProcessSQLAlterTableAlterColumn() */
6980 : /* */
6981 : /* The correct syntax for altering the type of a column in the */
6982 : /* OGR SQL dialect is: */
6983 : /* */
6984 : /* ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
6985 : /************************************************************************/
6986 :
6987 4 : OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)
6988 :
6989 : {
6990 4 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6991 :
6992 : /* -------------------------------------------------------------------- */
6993 : /* Do some general syntax checking. */
6994 : /* -------------------------------------------------------------------- */
6995 4 : const char *pszLayerName = nullptr;
6996 4 : const char *pszColumnName = nullptr;
6997 4 : int iTypeIndex = 0;
6998 4 : const int nTokens = CSLCount(papszTokens);
6999 :
7000 4 : if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&
7001 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
7002 2 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))
7003 : {
7004 2 : pszLayerName = papszTokens[2];
7005 2 : pszColumnName = papszTokens[5];
7006 2 : iTypeIndex = 7;
7007 : }
7008 2 : else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
7009 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
7010 2 : EQUAL(papszTokens[5], "TYPE"))
7011 : {
7012 2 : pszLayerName = papszTokens[2];
7013 2 : pszColumnName = papszTokens[4];
7014 2 : iTypeIndex = 6;
7015 : }
7016 : else
7017 : {
7018 0 : CSLDestroy(papszTokens);
7019 0 : CPLError(CE_Failure, CPLE_AppDefined,
7020 : "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
7021 : "Was '%s'\n"
7022 : "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
7023 : "<columnname> TYPE <columntype>'",
7024 : pszSQLCommand);
7025 0 : return OGRERR_FAILURE;
7026 : }
7027 :
7028 : /* -------------------------------------------------------------------- */
7029 : /* Merge type components into a single string if there were split */
7030 : /* with spaces */
7031 : /* -------------------------------------------------------------------- */
7032 8 : CPLString osType;
7033 8 : for (int i = iTypeIndex; i < nTokens; ++i)
7034 : {
7035 4 : osType += papszTokens[i];
7036 4 : CPLFree(papszTokens[i]);
7037 : }
7038 4 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
7039 4 : papszTokens[iTypeIndex + 1] = nullptr;
7040 :
7041 : /* -------------------------------------------------------------------- */
7042 : /* Find the named layer. */
7043 : /* -------------------------------------------------------------------- */
7044 4 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
7045 4 : if (poLayer == nullptr)
7046 : {
7047 0 : CPLError(CE_Failure, CPLE_AppDefined,
7048 : "%s failed, no such layer as `%s'.", pszSQLCommand,
7049 : pszLayerName);
7050 0 : CSLDestroy(papszTokens);
7051 0 : return OGRERR_FAILURE;
7052 : }
7053 :
7054 : /* -------------------------------------------------------------------- */
7055 : /* Find the field. */
7056 : /* -------------------------------------------------------------------- */
7057 :
7058 : const int nFieldIndex =
7059 4 : poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
7060 4 : if (nFieldIndex < 0)
7061 : {
7062 0 : CPLError(CE_Failure, CPLE_AppDefined,
7063 : "%s failed, no such field as `%s'.", pszSQLCommand,
7064 : pszColumnName);
7065 0 : CSLDestroy(papszTokens);
7066 0 : return OGRERR_FAILURE;
7067 : }
7068 :
7069 : /* -------------------------------------------------------------------- */
7070 : /* Alter column. */
7071 : /* -------------------------------------------------------------------- */
7072 :
7073 : OGRFieldDefn *poOldFieldDefn =
7074 4 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
7075 8 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
7076 :
7077 4 : int nWidth = 0;
7078 4 : int nPrecision = 0;
7079 4 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
7080 4 : oNewFieldDefn.SetType(eType);
7081 4 : oNewFieldDefn.SetWidth(nWidth);
7082 4 : oNewFieldDefn.SetPrecision(nPrecision);
7083 :
7084 4 : int l_nFlags = 0;
7085 4 : if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
7086 2 : l_nFlags |= ALTER_TYPE_FLAG;
7087 4 : if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
7088 0 : poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
7089 4 : l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
7090 :
7091 4 : CSLDestroy(papszTokens);
7092 :
7093 4 : if (l_nFlags == 0)
7094 0 : return OGRERR_NONE;
7095 :
7096 4 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
7097 : }
7098 :
7099 : //! @endcond
7100 :
7101 : /************************************************************************/
7102 : /* ExecuteSQL() */
7103 : /************************************************************************/
7104 :
7105 : /**
7106 : \brief Execute an SQL statement against the data store.
7107 :
7108 : The result of an SQL query is either NULL for statements that are in error,
7109 : or that have no results set, or an OGRLayer pointer representing a results
7110 : set from the query. Note that this OGRLayer is in addition to the layers
7111 : in the data store and must be destroyed with
7112 : ReleaseResultSet() before the dataset is closed
7113 : (destroyed).
7114 :
7115 : This method is the same as the C function GDALDatasetExecuteSQL() and the
7116 : deprecated OGR_DS_ExecuteSQL().
7117 :
7118 : For more information on the SQL dialect supported internally by OGR
7119 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
7120 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
7121 : to the underlying RDBMS.
7122 :
7123 : Starting with OGR 1.10, the <a
7124 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
7125 : also be used.
7126 :
7127 : @param pszStatement the SQL statement to execute.
7128 : @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
7129 : @param pszDialect allows control of the statement dialect. If set to NULL, the
7130 : OGR SQL engine will be used, except for RDBMS drivers that will use their
7131 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
7132 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
7133 :
7134 : @return an OGRLayer containing the results of the query. Deallocate with
7135 : ReleaseResultSet().
7136 :
7137 : */
7138 :
7139 3571 : OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,
7140 : OGRGeometry *poSpatialFilter,
7141 : const char *pszDialect)
7142 :
7143 : {
7144 3571 : return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
7145 : }
7146 :
7147 : //! @cond Doxygen_Suppress
7148 : OGRLayer *
7149 3579 : GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
7150 : const char *pszDialect,
7151 : swq_select_parse_options *poSelectParseOptions)
7152 :
7153 : {
7154 3579 : if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))
7155 : {
7156 : #ifdef SQLITE_ENABLED
7157 650 : return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
7158 650 : pszDialect);
7159 : #else
7160 : CPLError(CE_Failure, CPLE_NotSupported,
7161 : "The SQLite driver needs to be compiled to support the "
7162 : "SQLite SQL dialect");
7163 : return nullptr;
7164 : #endif
7165 : }
7166 :
7167 2929 : if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
7168 14 : !EQUAL(pszDialect, "OGRSQL"))
7169 : {
7170 6 : std::string osDialectList = "'OGRSQL'";
7171 : #ifdef SQLITE_ENABLED
7172 3 : osDialectList += ", 'SQLITE'";
7173 : #endif
7174 : const char *pszDialects =
7175 3 : GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);
7176 3 : if (pszDialects)
7177 : {
7178 : const CPLStringList aosTokens(
7179 0 : CSLTokenizeString2(pszDialects, " ", 0));
7180 0 : for (int i = 0; i < aosTokens.size(); ++i)
7181 : {
7182 0 : if (!EQUAL(aosTokens[i], "OGRSQL") &&
7183 0 : !EQUAL(aosTokens[i], "SQLITE"))
7184 : {
7185 0 : osDialectList += ", '";
7186 0 : osDialectList += aosTokens[i];
7187 0 : osDialectList += "'";
7188 : }
7189 : }
7190 : }
7191 3 : CPLError(CE_Warning, CPLE_NotSupported,
7192 : "Dialect '%s' is unsupported. Only supported dialects are %s. "
7193 : "Defaulting to OGRSQL",
7194 : pszDialect, osDialectList.c_str());
7195 : }
7196 :
7197 : /* -------------------------------------------------------------------- */
7198 : /* Handle CREATE INDEX statements specially. */
7199 : /* -------------------------------------------------------------------- */
7200 2929 : if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))
7201 : {
7202 28 : ProcessSQLCreateIndex(pszStatement);
7203 28 : return nullptr;
7204 : }
7205 :
7206 : /* -------------------------------------------------------------------- */
7207 : /* Handle DROP INDEX statements specially. */
7208 : /* -------------------------------------------------------------------- */
7209 2901 : if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))
7210 : {
7211 10 : ProcessSQLDropIndex(pszStatement);
7212 10 : return nullptr;
7213 : }
7214 :
7215 : /* -------------------------------------------------------------------- */
7216 : /* Handle DROP TABLE statements specially. */
7217 : /* -------------------------------------------------------------------- */
7218 2891 : if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))
7219 : {
7220 500 : ProcessSQLDropTable(pszStatement);
7221 500 : return nullptr;
7222 : }
7223 :
7224 : /* -------------------------------------------------------------------- */
7225 : /* Handle ALTER TABLE statements specially. */
7226 : /* -------------------------------------------------------------------- */
7227 2391 : if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))
7228 : {
7229 11 : char **papszTokens = CSLTokenizeString(pszStatement);
7230 11 : const int nTokens = CSLCount(papszTokens);
7231 11 : if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))
7232 : {
7233 2 : ProcessSQLAlterTableAddColumn(pszStatement);
7234 2 : CSLDestroy(papszTokens);
7235 2 : return nullptr;
7236 : }
7237 9 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))
7238 : {
7239 2 : ProcessSQLAlterTableDropColumn(pszStatement);
7240 2 : CSLDestroy(papszTokens);
7241 2 : return nullptr;
7242 : }
7243 7 : else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&
7244 1 : EQUAL(papszTokens[4], "TO"))
7245 : {
7246 1 : const char *pszSrcTableName = papszTokens[2];
7247 1 : const char *pszDstTableName = papszTokens[5];
7248 1 : auto poSrcLayer = GetLayerByName(pszSrcTableName);
7249 1 : if (poSrcLayer)
7250 : {
7251 1 : CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));
7252 : }
7253 : else
7254 : {
7255 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");
7256 : }
7257 1 : CSLDestroy(papszTokens);
7258 1 : return nullptr;
7259 : }
7260 6 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))
7261 : {
7262 2 : ProcessSQLAlterTableRenameColumn(pszStatement);
7263 2 : CSLDestroy(papszTokens);
7264 2 : return nullptr;
7265 : }
7266 4 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))
7267 : {
7268 4 : ProcessSQLAlterTableAlterColumn(pszStatement);
7269 4 : CSLDestroy(papszTokens);
7270 4 : return nullptr;
7271 : }
7272 : else
7273 : {
7274 0 : CPLError(CE_Failure, CPLE_AppDefined,
7275 : "Unsupported ALTER TABLE command : %s", pszStatement);
7276 0 : CSLDestroy(papszTokens);
7277 0 : return nullptr;
7278 : }
7279 : }
7280 :
7281 : /* -------------------------------------------------------------------- */
7282 : /* Preparse the SQL statement. */
7283 : /* -------------------------------------------------------------------- */
7284 2380 : swq_select *psSelectInfo = new swq_select();
7285 2380 : swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
7286 2380 : if (poSelectParseOptions != nullptr)
7287 8 : poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
7288 2380 : if (psSelectInfo->preparse(pszStatement,
7289 2380 : poCustomFuncRegistrar != nullptr) != CE_None)
7290 : {
7291 143 : delete psSelectInfo;
7292 143 : return nullptr;
7293 : }
7294 :
7295 : /* -------------------------------------------------------------------- */
7296 : /* If there is no UNION ALL, build result layer. */
7297 : /* -------------------------------------------------------------------- */
7298 2237 : if (psSelectInfo->poOtherSelect == nullptr)
7299 : {
7300 2231 : return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
7301 2231 : pszDialect, poSelectParseOptions);
7302 : }
7303 :
7304 : /* -------------------------------------------------------------------- */
7305 : /* Build result union layer. */
7306 : /* -------------------------------------------------------------------- */
7307 6 : int nSrcLayers = 0;
7308 6 : OGRLayer **papoSrcLayers = nullptr;
7309 :
7310 6 : do
7311 : {
7312 12 : swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
7313 12 : psSelectInfo->poOtherSelect = nullptr;
7314 :
7315 12 : OGRLayer *poLayer = BuildLayerFromSelectInfo(
7316 : psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
7317 12 : if (poLayer == nullptr)
7318 : {
7319 : // Each source layer owns an independent select info.
7320 0 : for (int i = 0; i < nSrcLayers; ++i)
7321 0 : delete papoSrcLayers[i];
7322 0 : CPLFree(papoSrcLayers);
7323 :
7324 : // So we just have to destroy the remaining select info.
7325 0 : delete psNextSelectInfo;
7326 :
7327 0 : return nullptr;
7328 : }
7329 : else
7330 : {
7331 24 : papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
7332 12 : papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
7333 12 : papoSrcLayers[nSrcLayers] = poLayer;
7334 12 : ++nSrcLayers;
7335 :
7336 12 : psSelectInfo = psNextSelectInfo;
7337 : }
7338 12 : } while (psSelectInfo != nullptr);
7339 :
7340 6 : return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
7341 : }
7342 :
7343 : //! @endcond
7344 :
7345 : /************************************************************************/
7346 : /* AbortSQL() */
7347 : /************************************************************************/
7348 :
7349 : /**
7350 : \brief Abort any SQL statement running in the data store.
7351 :
7352 : This function can be safely called from any thread (pending that the dataset
7353 : object is still alive). Driver implementations will make sure that it can be
7354 : called in a thread-safe way.
7355 :
7356 : This might not be implemented by all drivers. At time of writing, only SQLite,
7357 : GPKG and PG drivers implement it
7358 :
7359 : This method is the same as the C method GDALDatasetAbortSQL()
7360 :
7361 : @since GDAL 3.2.0
7362 :
7363 :
7364 : */
7365 :
7366 0 : OGRErr GDALDataset::AbortSQL()
7367 : {
7368 0 : CPLError(CE_Failure, CPLE_NotSupported,
7369 : "AbortSQL is not supported for this driver.");
7370 0 : return OGRERR_UNSUPPORTED_OPERATION;
7371 : }
7372 :
7373 : /************************************************************************/
7374 : /* BuildLayerFromSelectInfo() */
7375 : /************************************************************************/
7376 :
7377 : struct GDALSQLParseInfo
7378 : {
7379 : swq_field_list sFieldList;
7380 : int nExtraDSCount;
7381 : GDALDataset **papoExtraDS;
7382 : char *pszWHERE;
7383 : };
7384 :
7385 2243 : OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
7386 : swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
7387 : const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
7388 : {
7389 4486 : std::unique_ptr<swq_select> psSelectInfoUnique(psSelectInfo);
7390 :
7391 2243 : std::unique_ptr<OGRGenSQLResultsLayer> poResults;
7392 : GDALSQLParseInfo *psParseInfo =
7393 2243 : BuildParseInfo(psSelectInfoUnique.get(), poSelectParseOptions);
7394 :
7395 2243 : if (psParseInfo)
7396 : {
7397 2208 : const auto nErrorCounter = CPLGetErrorCounter();
7398 4416 : poResults = std::make_unique<OGRGenSQLResultsLayer>(
7399 2208 : this, std::move(psSelectInfoUnique), poSpatialFilter,
7400 4416 : psParseInfo->pszWHERE, pszDialect);
7401 2285 : if (CPLGetErrorCounter() > nErrorCounter &&
7402 77 : CPLGetLastErrorType() != CE_None)
7403 77 : poResults.reset();
7404 : }
7405 :
7406 2243 : DestroyParseInfo(psParseInfo);
7407 :
7408 4486 : return poResults.release();
7409 : }
7410 :
7411 : /************************************************************************/
7412 : /* DestroyParseInfo() */
7413 : /************************************************************************/
7414 :
7415 : //! @cond Doxygen_Suppress
7416 2312 : void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
7417 : {
7418 2312 : if (psParseInfo == nullptr)
7419 35 : return;
7420 :
7421 2277 : CPLFree(psParseInfo->sFieldList.names);
7422 2277 : CPLFree(psParseInfo->sFieldList.types);
7423 2277 : CPLFree(psParseInfo->sFieldList.table_ids);
7424 2277 : CPLFree(psParseInfo->sFieldList.ids);
7425 :
7426 : // Release the datasets we have opened with OGROpenShared()
7427 : // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
7428 : // has taken a reference on them, which it will release in its
7429 : // destructor.
7430 2284 : for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)
7431 7 : GDALClose(psParseInfo->papoExtraDS[iEDS]);
7432 :
7433 2277 : CPLFree(psParseInfo->papoExtraDS);
7434 2277 : CPLFree(psParseInfo->pszWHERE);
7435 2277 : CPLFree(psParseInfo);
7436 : }
7437 :
7438 : /************************************************************************/
7439 : /* BuildParseInfo() */
7440 : /************************************************************************/
7441 :
7442 : GDALSQLParseInfo *
7443 2277 : GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
7444 : swq_select_parse_options *poSelectParseOptions)
7445 : {
7446 2277 : int nFirstLayerFirstSpecialFieldIndex = 0;
7447 :
7448 : GDALSQLParseInfo *psParseInfo =
7449 2277 : static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
7450 :
7451 : /* -------------------------------------------------------------------- */
7452 : /* Validate that all the source tables are recognized, count */
7453 : /* fields. */
7454 : /* -------------------------------------------------------------------- */
7455 2277 : int nFieldCount = 0;
7456 :
7457 4622 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7458 : {
7459 2348 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7460 2348 : GDALDataset *poTableDS = this;
7461 :
7462 2348 : if (psTableDef->data_source != nullptr)
7463 : {
7464 7 : poTableDS = GDALDataset::FromHandle(
7465 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7466 7 : if (poTableDS == nullptr)
7467 : {
7468 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
7469 0 : CPLError(CE_Failure, CPLE_AppDefined,
7470 : "Unable to open secondary datasource "
7471 : "`%s' required by JOIN.",
7472 : psTableDef->data_source);
7473 :
7474 0 : DestroyParseInfo(psParseInfo);
7475 0 : return nullptr;
7476 : }
7477 :
7478 : // Keep in an array to release at the end of this function.
7479 14 : psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
7480 7 : psParseInfo->papoExtraDS,
7481 7 : sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
7482 7 : psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
7483 : }
7484 :
7485 : OGRLayer *poSrcLayer =
7486 2348 : poTableDS->GetLayerByName(psTableDef->table_name);
7487 :
7488 2348 : if (poSrcLayer == nullptr)
7489 : {
7490 3 : CPLError(CE_Failure, CPLE_AppDefined,
7491 : "SELECT from table %s failed, no such table/featureclass.",
7492 : psTableDef->table_name);
7493 :
7494 3 : DestroyParseInfo(psParseInfo);
7495 3 : return nullptr;
7496 : }
7497 :
7498 2345 : nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
7499 2345 : if (iTable == 0 ||
7500 34 : (poSelectParseOptions &&
7501 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7502 2308 : nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7503 :
7504 2345 : const char *pszFID = poSrcLayer->GetFIDColumn();
7505 2956 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7506 611 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7507 561 : nFieldCount++;
7508 : }
7509 :
7510 : /* -------------------------------------------------------------------- */
7511 : /* Build the field list for all indicated tables. */
7512 : /* -------------------------------------------------------------------- */
7513 :
7514 2274 : psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
7515 2274 : psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
7516 :
7517 2274 : psParseInfo->sFieldList.count = 0;
7518 2274 : psParseInfo->sFieldList.names = static_cast<char **>(
7519 2274 : CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7520 4548 : psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
7521 2274 : sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7522 2274 : psParseInfo->sFieldList.table_ids = static_cast<int *>(
7523 2274 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7524 2274 : psParseInfo->sFieldList.ids = static_cast<int *>(
7525 2274 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7526 :
7527 2274 : bool bIsFID64 = false;
7528 4619 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7529 : {
7530 2345 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7531 2345 : GDALDataset *poTableDS = this;
7532 :
7533 2345 : if (psTableDef->data_source != nullptr)
7534 : {
7535 7 : poTableDS = GDALDataset::FromHandle(
7536 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7537 7 : CPLAssert(poTableDS != nullptr);
7538 7 : poTableDS->Dereference();
7539 : }
7540 :
7541 : OGRLayer *poSrcLayer =
7542 2345 : poTableDS->GetLayerByName(psTableDef->table_name);
7543 :
7544 2345 : for (int iField = 0;
7545 18551 : iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)
7546 : {
7547 : OGRFieldDefn *poFDefn =
7548 16206 : poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
7549 16206 : const int iOutField = psParseInfo->sFieldList.count++;
7550 32412 : psParseInfo->sFieldList.names[iOutField] =
7551 16206 : const_cast<char *>(poFDefn->GetNameRef());
7552 16206 : if (poFDefn->GetType() == OFTInteger)
7553 : {
7554 4089 : if (poFDefn->GetSubType() == OFSTBoolean)
7555 160 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7556 : else
7557 3929 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7558 : }
7559 12117 : else if (poFDefn->GetType() == OFTInteger64)
7560 : {
7561 758 : if (poFDefn->GetSubType() == OFSTBoolean)
7562 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7563 : else
7564 758 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7565 : }
7566 11359 : else if (poFDefn->GetType() == OFTReal)
7567 2720 : psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
7568 8639 : else if (poFDefn->GetType() == OFTString)
7569 5585 : psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
7570 3054 : else if (poFDefn->GetType() == OFTTime)
7571 83 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
7572 2971 : else if (poFDefn->GetType() == OFTDate)
7573 143 : psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
7574 2828 : else if (poFDefn->GetType() == OFTDateTime)
7575 939 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
7576 : else
7577 1889 : psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
7578 :
7579 16206 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7580 16206 : psParseInfo->sFieldList.ids[iOutField] = iField;
7581 : }
7582 :
7583 2345 : if (iTable == 0)
7584 : {
7585 2274 : nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
7586 : }
7587 :
7588 2345 : if (iTable == 0 ||
7589 34 : (poSelectParseOptions &&
7590 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7591 : {
7592 :
7593 2308 : for (int iField = 0;
7594 4265 : iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7595 : iField++)
7596 : {
7597 : OGRGeomFieldDefn *poFDefn =
7598 1957 : poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
7599 1957 : const int iOutField = psParseInfo->sFieldList.count++;
7600 3914 : psParseInfo->sFieldList.names[iOutField] =
7601 1957 : const_cast<char *>(poFDefn->GetNameRef());
7602 1957 : if (*psParseInfo->sFieldList.names[iOutField] == '\0')
7603 1137 : psParseInfo->sFieldList.names[iOutField] =
7604 : const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
7605 1957 : psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
7606 :
7607 1957 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7608 1957 : psParseInfo->sFieldList.ids[iOutField] =
7609 1957 : GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
7610 : poSrcLayer->GetLayerDefn(), iField);
7611 : }
7612 : }
7613 :
7614 2346 : if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7615 1 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7616 : {
7617 1 : bIsFID64 = true;
7618 : }
7619 : }
7620 :
7621 : /* -------------------------------------------------------------------- */
7622 : /* Expand '*' in 'SELECT *' now before we add the pseudo fields */
7623 : /* -------------------------------------------------------------------- */
7624 2274 : const bool bAlwaysPrefixWithTableName =
7625 2316 : poSelectParseOptions &&
7626 42 : poSelectParseOptions->bAlwaysPrefixWithTableName;
7627 2274 : if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
7628 2274 : bAlwaysPrefixWithTableName) != CE_None)
7629 : {
7630 2 : DestroyParseInfo(psParseInfo);
7631 2 : return nullptr;
7632 : }
7633 :
7634 13632 : for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
7635 : {
7636 11360 : psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
7637 11360 : const_cast<char *>(SpecialFieldNames[iField]);
7638 11360 : psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
7639 11360 : (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
7640 : : SpecialFieldTypes[iField];
7641 11360 : psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
7642 11360 : psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
7643 11360 : nFirstLayerFirstSpecialFieldIndex + iField;
7644 11360 : psParseInfo->sFieldList.count++;
7645 : }
7646 :
7647 : /* In the case a layer has an explicit FID column name, then add it */
7648 : /* so it can be selected */
7649 4615 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7650 : {
7651 2343 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7652 2343 : GDALDataset *poTableDS = this;
7653 :
7654 2343 : if (psTableDef->data_source != nullptr)
7655 : {
7656 7 : poTableDS = GDALDataset::FromHandle(
7657 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7658 7 : CPLAssert(poTableDS != nullptr);
7659 7 : poTableDS->Dereference();
7660 : }
7661 :
7662 : OGRLayer *poSrcLayer =
7663 2343 : poTableDS->GetLayerByName(psTableDef->table_name);
7664 :
7665 2343 : const char *pszFID = poSrcLayer->GetFIDColumn();
7666 2954 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7667 611 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7668 : {
7669 561 : const int iOutField = psParseInfo->sFieldList.count++;
7670 561 : psParseInfo->sFieldList.names[iOutField] =
7671 : const_cast<char *>(pszFID);
7672 561 : if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7673 0 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7674 : {
7675 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7676 : }
7677 : else
7678 : {
7679 561 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7680 : }
7681 561 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7682 1122 : psParseInfo->sFieldList.ids[iOutField] =
7683 561 : poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
7684 : }
7685 : }
7686 :
7687 : /* -------------------------------------------------------------------- */
7688 : /* Finish the parse operation. */
7689 : /* -------------------------------------------------------------------- */
7690 2272 : if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
7691 : CE_None)
7692 : {
7693 30 : DestroyParseInfo(psParseInfo);
7694 30 : return nullptr;
7695 : }
7696 :
7697 : /* -------------------------------------------------------------------- */
7698 : /* Extract the WHERE expression to use separately. */
7699 : /* -------------------------------------------------------------------- */
7700 2242 : if (psSelectInfo->where_expr != nullptr)
7701 : {
7702 960 : psParseInfo->pszWHERE =
7703 960 : psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
7704 : // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
7705 : }
7706 :
7707 2242 : return psParseInfo;
7708 : }
7709 :
7710 : //! @endcond
7711 :
7712 : /************************************************************************/
7713 : /* ReleaseResultSet() */
7714 : /************************************************************************/
7715 :
7716 : /**
7717 : \brief Release results of ExecuteSQL().
7718 :
7719 : This method should only be used to deallocate OGRLayers resulting from
7720 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
7721 : results set before destroying the GDALDataset may cause errors.
7722 :
7723 : This method is the same as the C function GDALDatasetReleaseResultSet() and the
7724 : deprecated OGR_DS_ReleaseResultSet().
7725 :
7726 : @param poResultsSet the result of a previous ExecuteSQL() call.
7727 : */
7728 :
7729 2158 : void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)
7730 :
7731 : {
7732 2158 : delete poResultsSet;
7733 2158 : }
7734 :
7735 : /************************************************************************/
7736 : /* GetStyleTable() */
7737 : /************************************************************************/
7738 :
7739 : /**
7740 : \brief Returns dataset style table.
7741 :
7742 : This method is the same as the C function GDALDatasetGetStyleTable() and the
7743 : deprecated OGR_DS_GetStyleTable().
7744 :
7745 : @return pointer to a style table which should not be modified or freed by the
7746 : caller.
7747 : */
7748 :
7749 923 : OGRStyleTable *GDALDataset::GetStyleTable()
7750 : {
7751 923 : return m_poStyleTable;
7752 : }
7753 :
7754 : /************************************************************************/
7755 : /* SetStyleTableDirectly() */
7756 : /************************************************************************/
7757 :
7758 : /**
7759 : \brief Set dataset style table.
7760 :
7761 : This method operate exactly as SetStyleTable() except that it
7762 : assumes ownership of the passed table.
7763 :
7764 : This method is the same as the C function GDALDatasetSetStyleTableDirectly()
7765 : and the deprecated OGR_DS_SetStyleTableDirectly().
7766 :
7767 : @param poStyleTable pointer to style table to set
7768 :
7769 : */
7770 0 : void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
7771 : {
7772 0 : if (m_poStyleTable)
7773 0 : delete m_poStyleTable;
7774 0 : m_poStyleTable = poStyleTable;
7775 0 : }
7776 :
7777 : /************************************************************************/
7778 : /* SetStyleTable() */
7779 : /************************************************************************/
7780 :
7781 : /**
7782 : \brief Set dataset style table.
7783 :
7784 : This method operate exactly as SetStyleTableDirectly() except
7785 : that it does not assume ownership of the passed table.
7786 :
7787 : This method is the same as the C function GDALDatasetSetStyleTable() and the
7788 : deprecated OGR_DS_SetStyleTable().
7789 :
7790 : @param poStyleTable pointer to style table to set
7791 :
7792 : */
7793 :
7794 919 : void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
7795 : {
7796 919 : if (m_poStyleTable)
7797 0 : delete m_poStyleTable;
7798 919 : if (poStyleTable)
7799 1 : m_poStyleTable = poStyleTable->Clone();
7800 919 : }
7801 :
7802 : /************************************************************************/
7803 : /* IsGenericSQLDialect() */
7804 : /************************************************************************/
7805 :
7806 : //! @cond Doxygen_Suppress
7807 1748 : int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
7808 : {
7809 3188 : return pszDialect != nullptr &&
7810 3188 : (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
7811 : }
7812 :
7813 : //! @endcond
7814 :
7815 : /************************************************************************/
7816 : /* GetLayerCount() */
7817 : /************************************************************************/
7818 :
7819 : /**
7820 : \brief Get the number of layers in this dataset.
7821 :
7822 : This method is the same as the C function GDALDatasetGetLayerCount(),
7823 : and the deprecated OGR_DS_GetLayerCount().
7824 :
7825 : Note that even if this method is const, there is no guarantee it can be
7826 : safely called by concurrent threads on the same GDALDataset object.
7827 :
7828 : @return layer count.
7829 : */
7830 :
7831 115369 : int GDALDataset::GetLayerCount() const
7832 : {
7833 115369 : return 0;
7834 : }
7835 :
7836 : /************************************************************************/
7837 : /* GetLayer() */
7838 : /************************************************************************/
7839 :
7840 : /**
7841 : \fn const GDALDataset::GetLayer(int) const
7842 : \brief Fetch a layer by index.
7843 :
7844 : The returned layer remains owned by the
7845 : GDALDataset and should not be deleted by the application.
7846 :
7847 : Note that even if this method is const, there is no guarantee it can be
7848 : safely called by concurrent threads on the same GDALDataset object.
7849 :
7850 : See GetLayers() for a C++ iterator version of this method.
7851 :
7852 : This method is the same as the C function GDALDatasetGetLayer() and the
7853 : deprecated OGR_DS_GetLayer().
7854 :
7855 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7856 :
7857 : @return the layer, or NULL if iLayer is out of range or an error occurs.
7858 :
7859 : @see GetLayers()
7860 :
7861 : @since GDAL 3.12
7862 : */
7863 :
7864 0 : const OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer) const
7865 : {
7866 0 : return nullptr;
7867 : }
7868 :
7869 : /**
7870 : \fn GDALDataset::GetLayer(int)
7871 : \brief Fetch a layer by index.
7872 :
7873 : The returned layer remains owned by the
7874 : GDALDataset and should not be deleted by the application.
7875 :
7876 : See GetLayers() for a C++ iterator version of this method.
7877 :
7878 : This method is the same as the C function GDALDatasetGetLayer() and the
7879 : deprecated OGR_DS_GetLayer().
7880 :
7881 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7882 :
7883 : @return the layer, or NULL if iLayer is out of range or an error occurs.
7884 :
7885 : @see GetLayers()
7886 : */
7887 :
7888 : /************************************************************************/
7889 : /* IsLayerPrivate() */
7890 : /************************************************************************/
7891 :
7892 : /**
7893 : \fn GDALDataset::IsLayerPrivate(int)
7894 : \brief Returns true if the layer at the specified index is deemed a private or
7895 : system table, or an internal detail only.
7896 :
7897 : This method is the same as the C function GDALDatasetIsLayerPrivate().
7898 :
7899 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7900 :
7901 : @return true if the layer is a private or system table.
7902 :
7903 : @since GDAL 3.4
7904 : */
7905 :
7906 940 : bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const
7907 : {
7908 940 : return false;
7909 : }
7910 :
7911 : /************************************************************************/
7912 : /* ResetReading() */
7913 : /************************************************************************/
7914 :
7915 : /**
7916 : \brief Reset feature reading to start on the first feature.
7917 :
7918 : This affects GetNextFeature().
7919 :
7920 : Depending on drivers, this may also have the side effect of calling
7921 : OGRLayer::ResetReading() on the layers of this dataset.
7922 :
7923 : This method is the same as the C function GDALDatasetResetReading().
7924 :
7925 : */
7926 7 : void GDALDataset::ResetReading()
7927 : {
7928 7 : if (!m_poPrivate)
7929 0 : return;
7930 7 : m_poPrivate->nCurrentLayerIdx = 0;
7931 7 : m_poPrivate->nLayerCount = -1;
7932 7 : m_poPrivate->poCurrentLayer = nullptr;
7933 7 : m_poPrivate->nFeatureReadInLayer = 0;
7934 7 : m_poPrivate->nFeatureReadInDataset = 0;
7935 7 : m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
7936 7 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
7937 : }
7938 :
7939 : /************************************************************************/
7940 : /* GDALDatasetResetReading() */
7941 : /************************************************************************/
7942 :
7943 : /**
7944 : \brief Reset feature reading to start on the first feature.
7945 :
7946 : This affects GDALDatasetGetNextFeature().
7947 :
7948 : Depending on drivers, this may also have the side effect of calling
7949 : OGR_L_ResetReading() on the layers of this dataset.
7950 :
7951 : This method is the same as the C++ method GDALDataset::ResetReading()
7952 :
7953 : @param hDS dataset handle
7954 : */
7955 14 : void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)
7956 : {
7957 14 : VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
7958 :
7959 14 : return GDALDataset::FromHandle(hDS)->ResetReading();
7960 : }
7961 :
7962 : /************************************************************************/
7963 : /* GetNextFeature() */
7964 : /************************************************************************/
7965 :
7966 : /**
7967 : \brief Fetch the next available feature from this dataset.
7968 :
7969 : This method is intended for the few drivers where OGRLayer::GetNextFeature()
7970 : is not efficient, but in general OGRLayer::GetNextFeature() is a more
7971 : natural API.
7972 :
7973 : See GetFeatures() for a C++ iterator version of this method.
7974 :
7975 : The returned feature becomes the responsibility of the caller to
7976 : delete with OGRFeature::DestroyFeature().
7977 :
7978 : Depending on the driver, this method may return features from layers in a
7979 : non sequential way. This is what may happen when the
7980 : ODsCRandomLayerRead capability is declared (for example for the
7981 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7982 : advised to use GDALDataset::GetNextFeature() instead of
7983 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7984 : implementation.
7985 :
7986 : The default implementation, used by most drivers, will
7987 : however iterate over each layer, and then over each feature within this
7988 : layer.
7989 :
7990 : This method takes into account spatial and attribute filters set on layers that
7991 : will be iterated upon.
7992 :
7993 : The ResetReading() method can be used to start at the beginning again.
7994 :
7995 : Depending on drivers, this may also have the side effect of calling
7996 : OGRLayer::GetNextFeature() on the layers of this dataset.
7997 :
7998 : This method is the same as the C function GDALDatasetGetNextFeature().
7999 :
8000 : @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
8001 : layer to which the object belongs to, or NULL.
8002 : It is possible that the output of *ppoBelongingLayer
8003 : to be NULL despite the feature not being NULL.
8004 : @param pdfProgressPct a pointer to a double variable to receive the
8005 : percentage progress (in [0,1] range), or NULL.
8006 : On return, the pointed value might be negative if
8007 : determining the progress is not possible.
8008 : @param pfnProgress a progress callback to report progress (for
8009 : GetNextFeature() calls that might have a long
8010 : duration) and offer cancellation possibility, or NULL.
8011 : @param pProgressData user data provided to pfnProgress, or NULL
8012 : @return a feature, or NULL if no more features are available.
8013 : @see GetFeatures()
8014 : */
8015 :
8016 60 : OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,
8017 : double *pdfProgressPct,
8018 : GDALProgressFunc pfnProgress,
8019 : void *pProgressData)
8020 : {
8021 60 : if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)
8022 : {
8023 2 : if (ppoBelongingLayer != nullptr)
8024 2 : *ppoBelongingLayer = nullptr;
8025 2 : if (pdfProgressPct != nullptr)
8026 1 : *pdfProgressPct = 1.0;
8027 2 : if (pfnProgress != nullptr)
8028 0 : pfnProgress(1.0, "", pProgressData);
8029 2 : return nullptr;
8030 : }
8031 :
8032 58 : if (m_poPrivate->poCurrentLayer == nullptr &&
8033 8 : (pdfProgressPct != nullptr || pfnProgress != nullptr))
8034 : {
8035 1 : if (m_poPrivate->nLayerCount < 0)
8036 : {
8037 1 : m_poPrivate->nLayerCount = GetLayerCount();
8038 : }
8039 :
8040 1 : if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)
8041 : {
8042 1 : m_poPrivate->nTotalFeatures = 0;
8043 5 : for (int i = 0; i < m_poPrivate->nLayerCount; i++)
8044 : {
8045 4 : OGRLayer *poLayer = GetLayer(i);
8046 8 : if (poLayer == nullptr ||
8047 4 : !poLayer->TestCapability(OLCFastFeatureCount))
8048 : {
8049 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
8050 0 : break;
8051 : }
8052 4 : GIntBig nCount = poLayer->GetFeatureCount(FALSE);
8053 4 : if (nCount < 0)
8054 : {
8055 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
8056 0 : break;
8057 : }
8058 4 : m_poPrivate->nTotalFeatures += nCount;
8059 : }
8060 : }
8061 : }
8062 :
8063 : while (true)
8064 : {
8065 71 : if (m_poPrivate->poCurrentLayer == nullptr)
8066 : {
8067 44 : m_poPrivate->poCurrentLayer =
8068 22 : GetLayer(m_poPrivate->nCurrentLayerIdx);
8069 22 : if (m_poPrivate->poCurrentLayer == nullptr)
8070 : {
8071 7 : m_poPrivate->nCurrentLayerIdx = -1;
8072 7 : if (ppoBelongingLayer != nullptr)
8073 7 : *ppoBelongingLayer = nullptr;
8074 7 : if (pdfProgressPct != nullptr)
8075 1 : *pdfProgressPct = 1.0;
8076 7 : return nullptr;
8077 : }
8078 15 : m_poPrivate->poCurrentLayer->ResetReading();
8079 15 : m_poPrivate->nFeatureReadInLayer = 0;
8080 15 : if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)
8081 : {
8082 0 : if (m_poPrivate->poCurrentLayer->TestCapability(
8083 0 : OLCFastFeatureCount))
8084 0 : m_poPrivate->nTotalFeaturesInLayer =
8085 0 : m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
8086 : else
8087 0 : m_poPrivate->nTotalFeaturesInLayer = 0;
8088 : }
8089 : }
8090 64 : OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
8091 64 : if (poFeature == nullptr)
8092 : {
8093 13 : m_poPrivate->nCurrentLayerIdx++;
8094 13 : m_poPrivate->poCurrentLayer = nullptr;
8095 13 : continue;
8096 : }
8097 :
8098 51 : m_poPrivate->nFeatureReadInLayer++;
8099 51 : m_poPrivate->nFeatureReadInDataset++;
8100 51 : if (pdfProgressPct != nullptr || pfnProgress != nullptr)
8101 : {
8102 4 : double dfPct = 0.0;
8103 4 : if (m_poPrivate->nTotalFeatures > 0)
8104 : {
8105 4 : dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
8106 4 : m_poPrivate->nTotalFeatures;
8107 : }
8108 : else
8109 : {
8110 0 : dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /
8111 0 : m_poPrivate->nLayerCount;
8112 0 : if (m_poPrivate->nTotalFeaturesInLayer > 0)
8113 : {
8114 0 : dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
8115 0 : m_poPrivate->nTotalFeaturesInLayer /
8116 0 : m_poPrivate->nLayerCount;
8117 : }
8118 : }
8119 4 : if (pdfProgressPct)
8120 4 : *pdfProgressPct = dfPct;
8121 4 : if (pfnProgress)
8122 0 : pfnProgress(dfPct, "", nullptr);
8123 : }
8124 :
8125 51 : if (ppoBelongingLayer != nullptr)
8126 51 : *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
8127 51 : return poFeature;
8128 13 : }
8129 : }
8130 :
8131 : /************************************************************************/
8132 : /* GDALDatasetGetNextFeature() */
8133 : /************************************************************************/
8134 : /**
8135 : \brief Fetch the next available feature from this dataset.
8136 :
8137 : This method is intended for the few drivers where OGR_L_GetNextFeature()
8138 : is not efficient, but in general OGR_L_GetNextFeature() is a more
8139 : natural API.
8140 :
8141 : The returned feature becomes the responsibility of the caller to
8142 : delete with OGRFeature::DestroyFeature().
8143 :
8144 : Depending on the driver, this method may return features from layers in a
8145 : non sequential way. This is what may happen when the
8146 : ODsCRandomLayerRead capability is declared (for example for the
8147 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
8148 : advised to use GDALDataset::GetNextFeature() instead of
8149 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
8150 : implementation.
8151 :
8152 : The default implementation, used by most drivers, will
8153 : however iterate over each layer, and then over each feature within this
8154 : layer.
8155 :
8156 : This method takes into account spatial and attribute filters set on layers that
8157 : will be iterated upon.
8158 :
8159 : The ResetReading() method can be used to start at the beginning again.
8160 :
8161 : Depending on drivers, this may also have the side effect of calling
8162 : OGRLayer::GetNextFeature() on the layers of this dataset.
8163 :
8164 : This method is the same as the C++ method GDALDataset::GetNextFeature()
8165 :
8166 : @param hDS dataset handle.
8167 : @param phBelongingLayer a pointer to a OGRLayer* variable to receive the
8168 : layer to which the object belongs to, or NULL.
8169 : It is possible that the output of *ppoBelongingLayer
8170 : to be NULL despite the feature not being NULL.
8171 : @param pdfProgressPct a pointer to a double variable to receive the
8172 : percentage progress (in [0,1] range), or NULL.
8173 : On return, the pointed value might be negative if
8174 : determining the progress is not possible.
8175 : @param pfnProgress a progress callback to report progress (for
8176 : GetNextFeature() calls that might have a long
8177 : duration) and offer cancellation possibility, or NULL
8178 : @param pProgressData user data provided to pfnProgress, or NULL
8179 : @return a feature, or NULL if no more features are available.
8180 : */
8181 1917 : OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,
8182 : OGRLayerH *phBelongingLayer,
8183 : double *pdfProgressPct,
8184 : GDALProgressFunc pfnProgress,
8185 : void *pProgressData)
8186 : {
8187 1917 : VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
8188 :
8189 3834 : return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(
8190 : reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
8191 3834 : pfnProgress, pProgressData));
8192 : }
8193 :
8194 : /************************************************************************/
8195 : /* TestCapability() */
8196 : /************************************************************************/
8197 :
8198 : /**
8199 : \fn GDALDataset::TestCapability( const char * pszCap )
8200 : \brief Test if capability is available.
8201 :
8202 : One of the following dataset capability names can be passed into this
8203 : method, and a TRUE or FALSE value will be returned indicating whether or not
8204 : the capability is available for this object.
8205 :
8206 : <ul>
8207 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
8208 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
8209 : layers.<p>
8210 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
8211 : datasource support CreateGeomField() just after layer creation.<p>
8212 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
8213 : geometries.<p>
8214 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
8215 : transactions.<p>
8216 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
8217 : transactions through emulation.<p>
8218 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
8219 : GetNextFeature() implementation, potentially returning features from
8220 : layers in a non sequential way.<p>
8221 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
8222 : CreateFeature() on layers in a non sequential way.<p>
8223 : <li> <b>GDsCAddRelationship</b>: True if AddRelationship() is supported</li>
8224 : <li> <b>GDsCDeleteRelationship</b>: True if DeleteRelationship() is supported</li>
8225 : <li> <b>GDsCUpdateRelationship</b>: True if UpdateRelationship() is supported</li>
8226 : <li> <b>GDsCFastGetExtent</b>: True if GetExtent() is fast</li>
8227 : <li> <b>GDsCFastGetExtentWGS84LongLat</b>: True if GetExtentWGS84LongLat() is fast</li>
8228 : </ul>
8229 :
8230 : The \#define macro forms of the capability names should be used in preference
8231 : to the strings themselves to avoid misspelling.
8232 :
8233 : This method is the same as the C function GDALDatasetTestCapability() and the
8234 : deprecated OGR_DS_TestCapability().
8235 :
8236 : @param pszCap the capability to test.
8237 :
8238 : @return TRUE if capability available otherwise FALSE.
8239 : */
8240 :
8241 712 : int GDALDataset::TestCapability(const char *pszCap) const
8242 : {
8243 712 : if (EQUAL(pszCap, GDsCFastGetExtent) ||
8244 710 : EQUAL(pszCap, GDsCFastGetExtentWGS84LongLat))
8245 : {
8246 4 : for (auto &&poLayer : GetLayers())
8247 : {
8248 2 : if (!poLayer->TestCapability(OLCFastGetExtent))
8249 2 : return FALSE;
8250 : }
8251 2 : return TRUE;
8252 : }
8253 708 : return FALSE;
8254 : }
8255 :
8256 : /************************************************************************/
8257 : /* GDALDatasetTestCapability() */
8258 : /************************************************************************/
8259 :
8260 : /**
8261 : \brief Test if capability is available.
8262 :
8263 : One of the following dataset capability names can be passed into this
8264 : function, and a TRUE or FALSE value will be returned indicating whether or not
8265 : the capability is available for this object.
8266 :
8267 : <ul>
8268 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
8269 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
8270 : layers.<p>
8271 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
8272 : datasource support CreateGeomField() just after layer creation.<p>
8273 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
8274 : geometries.<p>
8275 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
8276 : transactions.<p>
8277 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
8278 : transactions through emulation.<p>
8279 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
8280 : GetNextFeature() implementation, potentially returning features from
8281 : layers in a non sequential way.<p>
8282 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
8283 : CreateFeature() on layers in a non sequential way.<p>
8284 : <li> <b>GDsCAddRelationship</b>: True if AddRelationship() is supported</li>
8285 : <li> <b>GDsCDeleteRelationship</b>: True if DeleteRelationship() is supported</li>
8286 : <li> <b>GDsCUpdateRelationship</b>: True if UpdateRelationship() is supported</li>
8287 : <li> <b>GDsCFastGetExtent</b>: True if GetExtent() is fast</li>
8288 : <li> <b>GDsCFastGetExtentWGS84LongLat</b>: True if GetExtentWGS84LongLat() is fast</li>
8289 : </ul>
8290 :
8291 : The \#define macro forms of the capability names should be used in preference
8292 : to the strings themselves to avoid misspelling.
8293 :
8294 : This function is the same as the C++ method GDALDataset::TestCapability()
8295 :
8296 :
8297 : @param hDS the dataset handle.
8298 : @param pszCap the capability to test.
8299 :
8300 : @return TRUE if capability available otherwise FALSE.
8301 : */
8302 122 : int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)
8303 :
8304 : {
8305 122 : VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
8306 122 : VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
8307 :
8308 122 : return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
8309 : }
8310 :
8311 : /************************************************************************/
8312 : /* StartTransaction() */
8313 : /************************************************************************/
8314 :
8315 : /**
8316 : \fn GDALDataset::StartTransaction(int)
8317 : \brief For datasources which support transactions, StartTransaction creates a
8318 : `transaction.
8319 :
8320 : If starting the transaction fails, will return
8321 : OGRERR_FAILURE. Datasources which do not support transactions will
8322 : always return OGRERR_UNSUPPORTED_OPERATION.
8323 :
8324 : Nested transactions are not supported.
8325 :
8326 : All changes done after the start of the transaction are definitely applied in
8327 : the datasource if CommitTransaction() is called. They may be canceled by
8328 : calling RollbackTransaction() instead.
8329 :
8330 : At the time of writing, transactions only apply on vector layers.
8331 :
8332 : Datasets that support transactions will advertise the ODsCTransactions
8333 : capability. Use of transactions at dataset level is generally preferred to
8334 : transactions at layer level, whose scope is rarely limited to the layer from
8335 : which it was started.
8336 :
8337 : In case StartTransaction() fails, neither CommitTransaction() or
8338 : RollbackTransaction() should be called.
8339 :
8340 : If an error occurs after a successful StartTransaction(), the whole transaction
8341 : may or may not be implicitly canceled, depending on drivers. (e.g. the PG
8342 : driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
8343 : an explicit call to RollbackTransaction() should be done to keep things
8344 : balanced.
8345 :
8346 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8347 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8348 : with significant overhead, in which case the user must explicitly allow for
8349 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8350 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8351 : ODsCTransactions).
8352 :
8353 : This function is the same as the C function GDALDatasetStartTransaction().
8354 :
8355 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8356 : transaction
8357 : mechanism is acceptable.
8358 :
8359 : @return OGRERR_NONE on success.
8360 : */
8361 :
8362 37 : OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
8363 : {
8364 37 : return OGRERR_UNSUPPORTED_OPERATION;
8365 : }
8366 :
8367 : /************************************************************************/
8368 : /* GDALDatasetStartTransaction() */
8369 : /************************************************************************/
8370 :
8371 : /**
8372 : \brief For datasources which support transactions, StartTransaction creates a
8373 : transaction.
8374 :
8375 : If starting the transaction fails, will return
8376 : OGRERR_FAILURE. Datasources which do not support transactions will
8377 : always return OGRERR_UNSUPPORTED_OPERATION.
8378 :
8379 : Nested transactions are not supported.
8380 :
8381 : All changes done after the start of the transaction are definitely applied in
8382 : the datasource if CommitTransaction() is called. They may be canceled by
8383 : calling RollbackTransaction() instead.
8384 :
8385 : At the time of writing, transactions only apply on vector layers.
8386 :
8387 : Datasets that support transactions will advertise the ODsCTransactions
8388 : capability.
8389 : Use of transactions at dataset level is generally preferred to transactions at
8390 : layer level, whose scope is rarely limited to the layer from which it was
8391 : started.
8392 :
8393 : In case StartTransaction() fails, neither CommitTransaction() or
8394 : RollbackTransaction() should be called.
8395 :
8396 : If an error occurs after a successful StartTransaction(), the whole
8397 : transaction may or may not be implicitly canceled, depending on drivers. (e.g.
8398 : the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
8399 : error, an explicit call to RollbackTransaction() should be done to keep things
8400 : balanced.
8401 :
8402 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8403 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8404 : with significant overhead, in which case the user must explicitly allow for
8405 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8406 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8407 : ODsCTransactions).
8408 :
8409 : This function is the same as the C++ method GDALDataset::StartTransaction()
8410 :
8411 : @param hDS the dataset handle.
8412 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8413 : transaction
8414 : mechanism is acceptable.
8415 :
8416 : @return OGRERR_NONE on success.
8417 : */
8418 105 : OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
8419 : {
8420 105 : VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
8421 : OGRERR_INVALID_HANDLE);
8422 :
8423 : #ifdef OGRAPISPY_ENABLED
8424 105 : if (bOGRAPISpyEnabled)
8425 2 : OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
8426 : #endif
8427 :
8428 105 : return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
8429 : }
8430 :
8431 : /************************************************************************/
8432 : /* CommitTransaction() */
8433 : /************************************************************************/
8434 :
8435 : /**
8436 : \brief For datasources which support transactions, CommitTransaction commits a
8437 : transaction.
8438 :
8439 : If no transaction is active, or the commit fails, will return
8440 : OGRERR_FAILURE. Datasources which do not support transactions will
8441 : always return OGRERR_UNSUPPORTED_OPERATION.
8442 :
8443 : Depending on drivers, this may or may not abort layer sequential readings that
8444 : are active.
8445 :
8446 : This function is the same as the C function GDALDatasetCommitTransaction().
8447 :
8448 : @return OGRERR_NONE on success.
8449 : */
8450 52 : OGRErr GDALDataset::CommitTransaction()
8451 : {
8452 52 : return OGRERR_UNSUPPORTED_OPERATION;
8453 : }
8454 :
8455 : /************************************************************************/
8456 : /* GDALDatasetCommitTransaction() */
8457 : /************************************************************************/
8458 :
8459 : /**
8460 : \brief For datasources which support transactions, CommitTransaction commits a
8461 : transaction.
8462 :
8463 : If no transaction is active, or the commit fails, will return
8464 : OGRERR_FAILURE. Datasources which do not support transactions will
8465 : always return OGRERR_UNSUPPORTED_OPERATION.
8466 :
8467 : Depending on drivers, this may or may not abort layer sequential readings that
8468 : are active.
8469 :
8470 : This function is the same as the C++ method GDALDataset::CommitTransaction()
8471 :
8472 : @return OGRERR_NONE on success.
8473 : */
8474 76 : OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
8475 : {
8476 76 : VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
8477 : OGRERR_INVALID_HANDLE);
8478 :
8479 : #ifdef OGRAPISPY_ENABLED
8480 76 : if (bOGRAPISpyEnabled)
8481 2 : OGRAPISpy_Dataset_CommitTransaction(hDS);
8482 : #endif
8483 :
8484 76 : return GDALDataset::FromHandle(hDS)->CommitTransaction();
8485 : }
8486 :
8487 : /************************************************************************/
8488 : /* RollbackTransaction() */
8489 : /************************************************************************/
8490 :
8491 : /**
8492 : \brief For datasources which support transactions, RollbackTransaction will
8493 : roll back a datasource to its state before the start of the current
8494 : transaction.
8495 : If no transaction is active, or the rollback fails, will return
8496 : OGRERR_FAILURE. Datasources which do not support transactions will
8497 : always return OGRERR_UNSUPPORTED_OPERATION.
8498 :
8499 : This function is the same as the C function GDALDatasetRollbackTransaction().
8500 :
8501 : @return OGRERR_NONE on success.
8502 : */
8503 2 : OGRErr GDALDataset::RollbackTransaction()
8504 : {
8505 2 : return OGRERR_UNSUPPORTED_OPERATION;
8506 : }
8507 :
8508 : /************************************************************************/
8509 : /* GDALDatasetRollbackTransaction() */
8510 : /************************************************************************/
8511 :
8512 : /**
8513 : \brief For datasources which support transactions, RollbackTransaction will
8514 : roll back a datasource to its state before the start of the current
8515 : transaction.
8516 : If no transaction is active, or the rollback fails, will return
8517 : OGRERR_FAILURE. Datasources which do not support transactions will
8518 : always return OGRERR_UNSUPPORTED_OPERATION.
8519 :
8520 : This function is the same as the C++ method GDALDataset::RollbackTransaction().
8521 :
8522 : @return OGRERR_NONE on success.
8523 : */
8524 44 : OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
8525 : {
8526 44 : VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
8527 : OGRERR_INVALID_HANDLE);
8528 :
8529 : #ifdef OGRAPISPY_ENABLED
8530 44 : if (bOGRAPISpyEnabled)
8531 2 : OGRAPISpy_Dataset_RollbackTransaction(hDS);
8532 : #endif
8533 :
8534 44 : return GDALDataset::FromHandle(hDS)->RollbackTransaction();
8535 : }
8536 :
8537 : //! @cond Doxygen_Suppress
8538 :
8539 : /************************************************************************/
8540 : /* ShareLockWithParentDataset() */
8541 : /************************************************************************/
8542 :
8543 : /* To be used typically by the GTiff driver to link overview datasets */
8544 : /* with their main dataset, so that they share the same lock */
8545 : /* Cf https://github.com/OSGeo/gdal/issues/1488 */
8546 : /* The parent dataset should remain alive while the this dataset is alive */
8547 :
8548 2328 : void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)
8549 : {
8550 2328 : if (m_poPrivate != nullptr)
8551 : {
8552 2328 : m_poPrivate->poParentDataset = poParentDataset;
8553 : }
8554 2328 : }
8555 :
8556 : /************************************************************************/
8557 : /* SetQueryLoggerFunc() */
8558 : /************************************************************************/
8559 :
8560 0 : bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,
8561 : CPL_UNUSED void *context)
8562 : {
8563 0 : return false;
8564 : }
8565 :
8566 : /************************************************************************/
8567 : /* EnterReadWrite() */
8568 : /************************************************************************/
8569 :
8570 8002940 : int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
8571 : {
8572 16005700 : if (m_poPrivate == nullptr ||
8573 8002920 : IsThreadSafe(GDAL_OF_RASTER | (nOpenFlags & GDAL_OF_UPDATE)))
8574 11986 : return FALSE;
8575 :
8576 7990840 : if (m_poPrivate->poParentDataset)
8577 242552 : return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
8578 :
8579 7748290 : if (eAccess == GA_Update)
8580 : {
8581 2202330 : if (m_poPrivate->eStateReadWriteMutex ==
8582 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8583 : {
8584 : // In case dead-lock would occur, which is not impossible,
8585 : // this can be used to prevent it, but at the risk of other
8586 : // issues.
8587 10522 : if (CPLTestBool(
8588 : CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
8589 : {
8590 10522 : m_poPrivate->eStateReadWriteMutex =
8591 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
8592 : }
8593 : else
8594 : {
8595 0 : m_poPrivate->eStateReadWriteMutex =
8596 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8597 : }
8598 : }
8599 2202330 : if (m_poPrivate->eStateReadWriteMutex ==
8600 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)
8601 : {
8602 : // There should be no race related to creating this mutex since
8603 : // it should be first created through IWriteBlock() / IRasterIO()
8604 : // and then GDALRasterBlock might call it from another thread.
8605 : #ifdef DEBUG_VERBOSE
8606 : CPLDebug("GDAL",
8607 : "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
8608 : CPLGetPID(), GetDescription());
8609 : #endif
8610 1536450 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8611 :
8612 : const int nCountMutex =
8613 1536540 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
8614 1536480 : if (nCountMutex == 0 && eRWFlag == GF_Read)
8615 : {
8616 521031 : CPLReleaseMutex(m_poPrivate->hMutex);
8617 1654230 : for (int i = 0; i < nBands; i++)
8618 : {
8619 1133200 : auto blockCache = papoBands[i]->poBandBlockCache;
8620 1133200 : if (blockCache)
8621 817077 : blockCache->WaitCompletionPendingTasks();
8622 : }
8623 521033 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8624 : }
8625 :
8626 1536530 : return TRUE;
8627 : }
8628 : }
8629 6211840 : return FALSE;
8630 : }
8631 :
8632 : /************************************************************************/
8633 : /* LeaveReadWrite() */
8634 : /************************************************************************/
8635 :
8636 1765490 : void GDALDataset::LeaveReadWrite()
8637 : {
8638 1765490 : if (m_poPrivate)
8639 : {
8640 1765480 : if (m_poPrivate->poParentDataset)
8641 : {
8642 228956 : m_poPrivate->poParentDataset->LeaveReadWrite();
8643 228956 : return;
8644 : }
8645 :
8646 1536520 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
8647 1536440 : CPLReleaseMutex(m_poPrivate->hMutex);
8648 : #ifdef DEBUG_VERBOSE
8649 : CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
8650 : CPLGetPID(), GetDescription());
8651 : #endif
8652 : }
8653 : }
8654 :
8655 : /************************************************************************/
8656 : /* InitRWLock() */
8657 : /************************************************************************/
8658 :
8659 3986350 : void GDALDataset::InitRWLock()
8660 : {
8661 3986350 : if (m_poPrivate)
8662 : {
8663 3986350 : if (m_poPrivate->poParentDataset)
8664 : {
8665 8584 : m_poPrivate->poParentDataset->InitRWLock();
8666 8584 : return;
8667 : }
8668 :
8669 3977770 : if (m_poPrivate->eStateReadWriteMutex ==
8670 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8671 : {
8672 1 : if (EnterReadWrite(GF_Write))
8673 1 : LeaveReadWrite();
8674 : }
8675 : }
8676 : }
8677 :
8678 : /************************************************************************/
8679 : /* DisableReadWriteMutex() */
8680 : /************************************************************************/
8681 :
8682 : // The mutex logic is broken in multi-threaded situations, for example
8683 : // with 2 WarpedVRT datasets being read at the same time. In that
8684 : // particular case, the mutex is not needed, so allow the VRTWarpedDataset code
8685 : // to disable it.
8686 21044 : void GDALDataset::DisableReadWriteMutex()
8687 : {
8688 21044 : if (m_poPrivate)
8689 : {
8690 21044 : if (m_poPrivate->poParentDataset)
8691 : {
8692 0 : m_poPrivate->poParentDataset->DisableReadWriteMutex();
8693 0 : return;
8694 : }
8695 :
8696 21044 : m_poPrivate->eStateReadWriteMutex =
8697 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8698 : }
8699 : }
8700 :
8701 : /************************************************************************/
8702 : /* TemporarilyDropReadWriteLock() */
8703 : /************************************************************************/
8704 :
8705 3394390 : void GDALDataset::TemporarilyDropReadWriteLock()
8706 : {
8707 3394390 : if (m_poPrivate == nullptr)
8708 0 : return;
8709 :
8710 3394390 : if (m_poPrivate->poParentDataset)
8711 : {
8712 26298 : m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
8713 26298 : return;
8714 : }
8715 :
8716 : #ifndef __COVERITY__
8717 3368090 : if (m_poPrivate->hMutex)
8718 : {
8719 : #ifdef DEBUG_VERBOSE
8720 : CPLDebug("GDAL",
8721 : "[Thread " CPL_FRMT_GIB "] "
8722 : "Temporarily drop RW mutex for %s",
8723 : CPLGetPID(), GetDescription());
8724 : #endif
8725 418158 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8726 : const int nCount =
8727 418156 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8728 : #ifdef DEBUG_EXTRA
8729 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
8730 : #endif
8731 1261440 : for (int i = 0; i < nCount + 1; i++)
8732 : {
8733 : // The mutex is recursive
8734 843285 : CPLReleaseMutex(m_poPrivate->hMutex);
8735 : }
8736 : }
8737 : #endif
8738 : }
8739 :
8740 : /************************************************************************/
8741 : /* ReacquireReadWriteLock() */
8742 : /************************************************************************/
8743 :
8744 3394420 : void GDALDataset::ReacquireReadWriteLock()
8745 : {
8746 3394420 : if (m_poPrivate == nullptr)
8747 0 : return;
8748 :
8749 3394420 : if (m_poPrivate->poParentDataset)
8750 : {
8751 26298 : m_poPrivate->poParentDataset->ReacquireReadWriteLock();
8752 26298 : return;
8753 : }
8754 :
8755 : #ifndef __COVERITY__
8756 3368130 : if (m_poPrivate->hMutex)
8757 : {
8758 : #ifdef DEBUG_VERBOSE
8759 : CPLDebug("GDAL",
8760 : "[Thread " CPL_FRMT_GIB "] "
8761 : "Reacquire temporarily dropped RW mutex for %s",
8762 : CPLGetPID(), GetDescription());
8763 : #endif
8764 418150 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8765 : const int nCount =
8766 417977 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8767 : #ifdef DEBUG_EXTRA
8768 : CPLAssert(nCount ==
8769 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
8770 : #endif
8771 418147 : if (nCount == 0)
8772 18644 : CPLReleaseMutex(m_poPrivate->hMutex);
8773 443817 : for (int i = 0; i < nCount - 1; i++)
8774 : {
8775 : // The mutex is recursive
8776 25669 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8777 : }
8778 : }
8779 : #endif
8780 : }
8781 :
8782 : /************************************************************************/
8783 : /* AcquireMutex() */
8784 : /************************************************************************/
8785 :
8786 196 : int GDALDataset::AcquireMutex()
8787 : {
8788 196 : if (m_poPrivate == nullptr)
8789 0 : return 0;
8790 196 : if (m_poPrivate->poParentDataset)
8791 : {
8792 0 : return m_poPrivate->poParentDataset->AcquireMutex();
8793 : }
8794 :
8795 196 : return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8796 : }
8797 :
8798 : /************************************************************************/
8799 : /* ReleaseMutex() */
8800 : /************************************************************************/
8801 :
8802 196 : void GDALDataset::ReleaseMutex()
8803 : {
8804 196 : if (m_poPrivate)
8805 : {
8806 196 : if (m_poPrivate->poParentDataset)
8807 : {
8808 0 : m_poPrivate->poParentDataset->ReleaseMutex();
8809 0 : return;
8810 : }
8811 :
8812 196 : CPLReleaseMutex(m_poPrivate->hMutex);
8813 : }
8814 : }
8815 :
8816 : //! @endcond
8817 :
8818 : /************************************************************************/
8819 : /* GDALDataset::Features::Iterator::Private */
8820 : /************************************************************************/
8821 :
8822 : struct GDALDataset::Features::Iterator::Private
8823 : {
8824 : GDALDataset::FeatureLayerPair m_oPair{};
8825 : GDALDataset *m_poDS = nullptr;
8826 : bool m_bEOF = true;
8827 : };
8828 :
8829 4 : GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8830 4 : : m_poPrivate(new GDALDataset::Features::Iterator::Private())
8831 : {
8832 4 : m_poPrivate->m_poDS = poDS;
8833 4 : if (bStart)
8834 : {
8835 2 : poDS->ResetReading();
8836 4 : m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(
8837 2 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8838 2 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8839 : }
8840 4 : }
8841 :
8842 : GDALDataset::Features::Iterator::~Iterator() = default;
8843 :
8844 : const GDALDataset::FeatureLayerPair &
8845 20 : GDALDataset::Features::Iterator::operator*() const
8846 : {
8847 20 : return m_poPrivate->m_oPair;
8848 : }
8849 :
8850 20 : GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()
8851 : {
8852 40 : m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(
8853 20 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8854 20 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8855 20 : return *this;
8856 : }
8857 :
8858 22 : bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const
8859 : {
8860 22 : return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
8861 : }
8862 :
8863 : /************************************************************************/
8864 : /* GetFeatures() */
8865 : /************************************************************************/
8866 :
8867 : /** Function that return an iterable object over features in the dataset
8868 : * layer.
8869 : *
8870 : * This is a C++ iterator friendly version of GetNextFeature().
8871 : *
8872 : * Using this iterator for standard range-based loops is safe, but
8873 : * due to implementation limitations, you shouldn't try to access
8874 : * (dereference) more than one iterator step at a time, since the
8875 : * FeatureLayerPair reference which is returned is reused.
8876 : *
8877 : * Typical use is:
8878 : * \code{.cpp}
8879 : * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
8880 : * {
8881 : * std::cout << "Feature of layer " <<
8882 : * oFeatureLayerPair.layer->GetName() << std::endl;
8883 : * oFeatureLayerPair.feature->DumpReadable();
8884 : * }
8885 : * \endcode
8886 : *
8887 : * @see GetNextFeature()
8888 : *
8889 : */
8890 2 : GDALDataset::Features GDALDataset::GetFeatures()
8891 : {
8892 2 : return Features(this);
8893 : }
8894 :
8895 : /************************************************************************/
8896 : /* begin() */
8897 : /************************************************************************/
8898 :
8899 : /**
8900 : \brief Return beginning of feature iterator.
8901 :
8902 : */
8903 :
8904 2 : const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
8905 : {
8906 2 : return {m_poSelf, true};
8907 : }
8908 :
8909 : /************************************************************************/
8910 : /* end() */
8911 : /************************************************************************/
8912 :
8913 : /**
8914 : \brief Return end of feature iterator.
8915 :
8916 : */
8917 :
8918 2 : const GDALDataset::Features::Iterator GDALDataset::Features::end() const
8919 : {
8920 2 : return {m_poSelf, false};
8921 : }
8922 :
8923 : /************************************************************************/
8924 : /* GDALDataset::Layers::Iterator::Private */
8925 : /************************************************************************/
8926 :
8927 : struct GDALDataset::Layers::Iterator::Private
8928 : {
8929 : OGRLayer *m_poLayer = nullptr;
8930 : int m_iCurLayer = 0;
8931 : int m_nLayerCount = 0;
8932 : GDALDataset *m_poDS = nullptr;
8933 : };
8934 :
8935 2 : GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())
8936 : {
8937 2 : }
8938 :
8939 : // False positive of cppcheck 1.72
8940 : // cppcheck-suppress uninitMemberVar
8941 9 : GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)
8942 9 : : m_poPrivate(new Private(*(oOther.m_poPrivate)))
8943 : {
8944 9 : }
8945 :
8946 5 : GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept
8947 5 : : m_poPrivate(std::move(oOther.m_poPrivate))
8948 : {
8949 5 : }
8950 :
8951 604 : GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8952 604 : : m_poPrivate(new Private())
8953 : {
8954 604 : m_poPrivate->m_poDS = poDS;
8955 604 : m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
8956 604 : if (bStart)
8957 : {
8958 304 : if (m_poPrivate->m_nLayerCount)
8959 295 : m_poPrivate->m_poLayer = poDS->GetLayer(0);
8960 : }
8961 : else
8962 : {
8963 300 : m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
8964 : }
8965 604 : }
8966 :
8967 : GDALDataset::Layers::Iterator::~Iterator() = default;
8968 :
8969 : // False positive of cppcheck 1.72
8970 : // cppcheck-suppress operatorEqVarError
8971 : GDALDataset::Layers::Iterator &
8972 1 : GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)
8973 : {
8974 1 : *m_poPrivate = *oOther.m_poPrivate;
8975 1 : return *this;
8976 : }
8977 :
8978 3 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(
8979 : GDALDataset::Layers::Iterator &&oOther) noexcept
8980 : {
8981 3 : m_poPrivate = std::move(oOther.m_poPrivate);
8982 3 : return *this;
8983 : }
8984 :
8985 358 : OGRLayer *GDALDataset::Layers::Iterator::operator*() const
8986 : {
8987 358 : return m_poPrivate->m_poLayer;
8988 : }
8989 :
8990 333 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()
8991 : {
8992 333 : m_poPrivate->m_iCurLayer++;
8993 333 : if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
8994 : {
8995 69 : m_poPrivate->m_poLayer =
8996 69 : m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
8997 : }
8998 : else
8999 : {
9000 264 : m_poPrivate->m_poLayer = nullptr;
9001 : }
9002 333 : return *this;
9003 : }
9004 :
9005 2 : GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
9006 : {
9007 2 : GDALDataset::Layers::Iterator temp = *this;
9008 2 : ++(*this);
9009 2 : return temp;
9010 : }
9011 :
9012 627 : bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const
9013 : {
9014 627 : return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
9015 : }
9016 :
9017 : /************************************************************************/
9018 : /* GetLayers() */
9019 : /************************************************************************/
9020 :
9021 : /** Function that returns an iterable object over layers in the dataset.
9022 : *
9023 : * This is a C++ iterator friendly version of GetLayer().
9024 : *
9025 : * Typical use is:
9026 : * \code{.cpp}
9027 : * for( auto&& poLayer: poDS->GetLayers() )
9028 : * {
9029 : * std::cout << "Layer << poLayer->GetName() << std::endl;
9030 : * }
9031 : * \endcode
9032 : *
9033 : * @see GetLayer()
9034 : *
9035 : */
9036 305 : GDALDataset::Layers GDALDataset::GetLayers()
9037 : {
9038 305 : return Layers(this);
9039 : }
9040 :
9041 : /************************************************************************/
9042 : /* begin() */
9043 : /************************************************************************/
9044 :
9045 : /**
9046 : \brief Return beginning of layer iterator.
9047 :
9048 : */
9049 :
9050 304 : GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
9051 : {
9052 304 : return {m_poSelf, true};
9053 : }
9054 :
9055 : /************************************************************************/
9056 : /* end() */
9057 : /************************************************************************/
9058 :
9059 : /**
9060 : \brief Return end of layer iterator.
9061 :
9062 : */
9063 :
9064 300 : GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
9065 : {
9066 300 : return {m_poSelf, false};
9067 : }
9068 :
9069 : /************************************************************************/
9070 : /* size() */
9071 : /************************************************************************/
9072 :
9073 : /**
9074 : \brief Get the number of layers in this dataset.
9075 :
9076 : @return layer count.
9077 :
9078 : */
9079 :
9080 1 : size_t GDALDataset::Layers::size() const
9081 : {
9082 1 : return static_cast<size_t>(m_poSelf->GetLayerCount());
9083 : }
9084 :
9085 : /************************************************************************/
9086 : /* operator[]() */
9087 : /************************************************************************/
9088 : /**
9089 : \brief Fetch a layer by index.
9090 :
9091 : The returned layer remains owned by the
9092 : GDALDataset and should not be deleted by the application.
9093 :
9094 : @param iLayer a layer number between 0 and size()-1.
9095 :
9096 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
9097 :
9098 : */
9099 :
9100 9 : OGRLayer *GDALDataset::Layers::operator[](int iLayer)
9101 : {
9102 9 : return m_poSelf->GetLayer(iLayer);
9103 : }
9104 :
9105 : /************************************************************************/
9106 : /* operator[]() */
9107 : /************************************************************************/
9108 : /**
9109 : \brief Fetch a layer by index.
9110 :
9111 : The returned layer remains owned by the
9112 : GDALDataset and should not be deleted by the application.
9113 :
9114 : @param iLayer a layer number between 0 and size()-1.
9115 :
9116 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
9117 :
9118 : */
9119 :
9120 1 : OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)
9121 : {
9122 1 : return m_poSelf->GetLayer(static_cast<int>(iLayer));
9123 : }
9124 :
9125 : /************************************************************************/
9126 : /* operator[]() */
9127 : /************************************************************************/
9128 : /**
9129 : \brief Fetch a layer by name.
9130 :
9131 : The returned layer remains owned by the
9132 : GDALDataset and should not be deleted by the application.
9133 :
9134 : @param pszLayerName layer name
9135 :
9136 : @return the layer, or nullptr if pszLayerName does not match with a layer
9137 :
9138 : */
9139 :
9140 1 : OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)
9141 : {
9142 1 : return m_poSelf->GetLayerByName(pszLayerName);
9143 : }
9144 :
9145 : /************************************************************************/
9146 : /* GDALDataset::ConstLayers::Iterator::Private */
9147 : /************************************************************************/
9148 :
9149 : struct GDALDataset::ConstLayers::Iterator::Private
9150 : {
9151 : const OGRLayer *m_poLayer = nullptr;
9152 : int m_iCurLayer = 0;
9153 : int m_nLayerCount = 0;
9154 : const GDALDataset *m_poDS = nullptr;
9155 : };
9156 :
9157 2 : GDALDataset::ConstLayers::Iterator::Iterator() : m_poPrivate(new Private())
9158 : {
9159 2 : }
9160 :
9161 : // False positive of cppcheck 1.72
9162 : // cppcheck-suppress uninitMemberVar
9163 9 : GDALDataset::ConstLayers::Iterator::Iterator(const Iterator &oOther)
9164 9 : : m_poPrivate(new Private(*(oOther.m_poPrivate)))
9165 : {
9166 9 : }
9167 :
9168 5 : GDALDataset::ConstLayers::Iterator::Iterator(Iterator &&oOther) noexcept
9169 5 : : m_poPrivate(std::move(oOther.m_poPrivate))
9170 : {
9171 5 : }
9172 :
9173 34568 : GDALDataset::ConstLayers::Iterator::Iterator(const GDALDataset *poDS,
9174 34568 : bool bStart)
9175 34568 : : m_poPrivate(new Private())
9176 : {
9177 34565 : m_poPrivate->m_poDS = poDS;
9178 34565 : m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
9179 34566 : if (bStart)
9180 : {
9181 17285 : if (m_poPrivate->m_nLayerCount)
9182 218 : m_poPrivate->m_poLayer = poDS->GetLayer(0);
9183 : }
9184 : else
9185 : {
9186 17281 : m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
9187 : }
9188 34567 : }
9189 :
9190 : GDALDataset::ConstLayers::Iterator::~Iterator() = default;
9191 :
9192 : // False positive of cppcheck 1.72
9193 : // cppcheck-suppress operatorEqVarError
9194 : GDALDataset::ConstLayers::Iterator &
9195 1 : GDALDataset::ConstLayers::Iterator::operator=(const Iterator &oOther)
9196 : {
9197 1 : *m_poPrivate = *oOther.m_poPrivate;
9198 1 : return *this;
9199 : }
9200 :
9201 : GDALDataset::ConstLayers::Iterator &
9202 3 : GDALDataset::ConstLayers::Iterator::operator=(
9203 : GDALDataset::ConstLayers::Iterator &&oOther) noexcept
9204 : {
9205 3 : m_poPrivate = std::move(oOther.m_poPrivate);
9206 3 : return *this;
9207 : }
9208 :
9209 16176 : const OGRLayer *GDALDataset::ConstLayers::Iterator::operator*() const
9210 : {
9211 16176 : return m_poPrivate->m_poLayer;
9212 : }
9213 :
9214 : GDALDataset::ConstLayers::Iterator &
9215 16171 : GDALDataset::ConstLayers::Iterator::operator++()
9216 : {
9217 16171 : m_poPrivate->m_iCurLayer++;
9218 16171 : if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
9219 : {
9220 15964 : m_poPrivate->m_poLayer =
9221 15964 : m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
9222 : }
9223 : else
9224 : {
9225 207 : m_poPrivate->m_poLayer = nullptr;
9226 : }
9227 16171 : return *this;
9228 : }
9229 :
9230 : GDALDataset::ConstLayers::Iterator
9231 2 : GDALDataset::ConstLayers::Iterator::operator++(int)
9232 : {
9233 2 : GDALDataset::ConstLayers::Iterator temp = *this;
9234 2 : ++(*this);
9235 2 : return temp;
9236 : }
9237 :
9238 33445 : bool GDALDataset::ConstLayers::Iterator::operator!=(const Iterator &it) const
9239 : {
9240 33445 : return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
9241 : }
9242 :
9243 : /************************************************************************/
9244 : /* GetLayers() */
9245 : /************************************************************************/
9246 :
9247 : /** Function that returns an iterable object over layers in the dataset.
9248 : *
9249 : * This is a C++ iterator friendly version of GetLayer().
9250 : *
9251 : * Typical use is:
9252 : * \code{.cpp}
9253 : * for( auto&& poLayer: poDS->GetLayers() )
9254 : * {
9255 : * std::cout << "Layer << poLayer->GetName() << std::endl;
9256 : * }
9257 : * \endcode
9258 : *
9259 : * @see GetLayer()
9260 : *
9261 : * @since GDAL 3.12
9262 : */
9263 17287 : GDALDataset::ConstLayers GDALDataset::GetLayers() const
9264 : {
9265 17287 : return ConstLayers(this);
9266 : }
9267 :
9268 : /************************************************************************/
9269 : /* begin() */
9270 : /************************************************************************/
9271 :
9272 : /**
9273 : \brief Return beginning of layer iterator.
9274 :
9275 : @since GDAL 3.12
9276 : */
9277 :
9278 17286 : GDALDataset::ConstLayers::Iterator GDALDataset::ConstLayers::begin() const
9279 : {
9280 17286 : return {m_poSelf, true};
9281 : }
9282 :
9283 : /************************************************************************/
9284 : /* end() */
9285 : /************************************************************************/
9286 :
9287 : /**
9288 : \brief Return end of layer iterator.
9289 :
9290 : @since GDAL 3.12
9291 : */
9292 :
9293 17282 : GDALDataset::ConstLayers::Iterator GDALDataset::ConstLayers::end() const
9294 : {
9295 17282 : return {m_poSelf, false};
9296 : }
9297 :
9298 : /************************************************************************/
9299 : /* size() */
9300 : /************************************************************************/
9301 :
9302 : /**
9303 : \brief Get the number of layers in this dataset.
9304 :
9305 : @return layer count.
9306 :
9307 : @since GDAL 3.12
9308 : */
9309 :
9310 1 : size_t GDALDataset::ConstLayers::size() const
9311 : {
9312 1 : return static_cast<size_t>(m_poSelf->GetLayerCount());
9313 : }
9314 :
9315 : /************************************************************************/
9316 : /* operator[]() */
9317 : /************************************************************************/
9318 : /**
9319 : \brief Fetch a layer by index.
9320 :
9321 : The returned layer remains owned by the
9322 : GDALDataset and should not be deleted by the application.
9323 :
9324 : @param iLayer a layer number between 0 and size()-1.
9325 :
9326 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
9327 :
9328 : @since GDAL 3.12
9329 : */
9330 :
9331 9 : const OGRLayer *GDALDataset::ConstLayers::operator[](int iLayer)
9332 : {
9333 9 : return m_poSelf->GetLayer(iLayer);
9334 : }
9335 :
9336 : /************************************************************************/
9337 : /* operator[]() */
9338 : /************************************************************************/
9339 : /**
9340 : \brief Fetch a layer by index.
9341 :
9342 : The returned layer remains owned by the
9343 : GDALDataset and should not be deleted by the application.
9344 :
9345 : @param iLayer a layer number between 0 and size()-1.
9346 :
9347 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
9348 :
9349 : @since GDAL 3.12
9350 : */
9351 :
9352 1 : const OGRLayer *GDALDataset::ConstLayers::operator[](size_t iLayer)
9353 : {
9354 1 : return m_poSelf->GetLayer(static_cast<int>(iLayer));
9355 : }
9356 :
9357 : /************************************************************************/
9358 : /* operator[]() */
9359 : /************************************************************************/
9360 : /**
9361 : \brief Fetch a layer by name.
9362 :
9363 : The returned layer remains owned by the
9364 : GDALDataset and should not be deleted by the application.
9365 :
9366 : @param pszLayerName layer name
9367 :
9368 : @return the layer, or nullptr if pszLayerName does not match with a layer
9369 :
9370 : @since GDAL 3.12
9371 : */
9372 :
9373 1 : const OGRLayer *GDALDataset::ConstLayers::operator[](const char *pszLayerName)
9374 : {
9375 1 : return const_cast<GDALDataset *>(m_poSelf)->GetLayerByName(pszLayerName);
9376 : }
9377 :
9378 : /************************************************************************/
9379 : /* GDALDataset::Bands::Iterator::Private */
9380 : /************************************************************************/
9381 :
9382 : struct GDALDataset::Bands::Iterator::Private
9383 : {
9384 : GDALRasterBand *m_poBand = nullptr;
9385 : int m_iCurBand = 0;
9386 : int m_nBandCount = 0;
9387 : GDALDataset *m_poDS = nullptr;
9388 : };
9389 :
9390 6 : GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)
9391 6 : : m_poPrivate(new GDALDataset::Bands::Iterator::Private())
9392 : {
9393 6 : m_poPrivate->m_poDS = poDS;
9394 6 : m_poPrivate->m_nBandCount = poDS->GetRasterCount();
9395 6 : if (bStart)
9396 : {
9397 3 : if (m_poPrivate->m_nBandCount)
9398 3 : m_poPrivate->m_poBand = poDS->GetRasterBand(1);
9399 : }
9400 : else
9401 : {
9402 3 : m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
9403 : }
9404 6 : }
9405 :
9406 : GDALDataset::Bands::Iterator::~Iterator() = default;
9407 :
9408 5 : GDALRasterBand *GDALDataset::Bands::Iterator::operator*()
9409 : {
9410 5 : return m_poPrivate->m_poBand;
9411 : }
9412 :
9413 3 : GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()
9414 : {
9415 3 : m_poPrivate->m_iCurBand++;
9416 3 : if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
9417 : {
9418 2 : m_poPrivate->m_poBand =
9419 2 : m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
9420 : }
9421 : else
9422 : {
9423 1 : m_poPrivate->m_poBand = nullptr;
9424 : }
9425 3 : return *this;
9426 : }
9427 :
9428 6 : bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const
9429 : {
9430 6 : return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
9431 : }
9432 :
9433 : /************************************************************************/
9434 : /* GetBands() */
9435 : /************************************************************************/
9436 :
9437 : /** Function that returns an iterable object over GDALRasterBand in the dataset.
9438 : *
9439 : * This is a C++ iterator friendly version of GetRasterBand().
9440 : *
9441 : * Typical use is:
9442 : * \code{.cpp}
9443 : * for( auto&& poBand: poDS->GetBands() )
9444 : * {
9445 : * std::cout << "Band << poBand->GetDescription() << std::endl;
9446 : * }
9447 : * \endcode
9448 : *
9449 : * @see GetRasterBand()
9450 : *
9451 : */
9452 7 : GDALDataset::Bands GDALDataset::GetBands()
9453 : {
9454 7 : return Bands(this);
9455 : }
9456 :
9457 : /************************************************************************/
9458 : /* begin() */
9459 : /************************************************************************/
9460 :
9461 : /**
9462 : \brief Return beginning of band iterator.
9463 :
9464 : */
9465 :
9466 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
9467 : {
9468 3 : return {m_poSelf, true};
9469 : }
9470 :
9471 : /************************************************************************/
9472 : /* end() */
9473 : /************************************************************************/
9474 :
9475 : /**
9476 : \brief Return end of band iterator.
9477 :
9478 : */
9479 :
9480 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
9481 : {
9482 3 : return {m_poSelf, false};
9483 : }
9484 :
9485 : /************************************************************************/
9486 : /* size() */
9487 : /************************************************************************/
9488 :
9489 : /**
9490 : \brief Get the number of raster bands in this dataset.
9491 :
9492 : @return raster band count.
9493 :
9494 : */
9495 :
9496 2 : size_t GDALDataset::Bands::size() const
9497 : {
9498 2 : return static_cast<size_t>(m_poSelf->GetRasterCount());
9499 : }
9500 :
9501 : /************************************************************************/
9502 : /* operator[]() */
9503 : /************************************************************************/
9504 : /**
9505 : \brief Fetch a raster band by index.
9506 :
9507 : The returned band remains owned by the
9508 : GDALDataset and should not be deleted by the application.
9509 :
9510 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9511 : consistent with the conventions of C/C++, i.e. starting at 0.
9512 :
9513 : @param iBand a band index between 0 and size()-1.
9514 :
9515 : @return the band, or nullptr if iBand is out of range or an error occurs.
9516 :
9517 : */
9518 :
9519 1 : GDALRasterBand *GDALDataset::Bands::operator[](int iBand)
9520 : {
9521 1 : return m_poSelf->GetRasterBand(1 + iBand);
9522 : }
9523 :
9524 : /************************************************************************/
9525 : /* operator[]() */
9526 : /************************************************************************/
9527 :
9528 : /**
9529 : \brief Fetch a raster band by index.
9530 :
9531 : The returned band remains owned by the
9532 : GDALDataset and should not be deleted by the application.
9533 :
9534 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9535 : consistent with the conventions of C/C++, i.e. starting at 0.
9536 :
9537 : @param iBand a band index between 0 and size()-1.
9538 :
9539 : @return the band, or nullptr if iBand is out of range or an error occurs.
9540 :
9541 : */
9542 :
9543 1 : GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)
9544 : {
9545 1 : return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
9546 : }
9547 :
9548 : /************************************************************************/
9549 : /* GDALDataset::ConstBands::Iterator::Private */
9550 : /************************************************************************/
9551 :
9552 : struct GDALDataset::ConstBands::Iterator::Private
9553 : {
9554 : const GDALRasterBand *m_poBand = nullptr;
9555 : int m_iCurBand = 0;
9556 : int m_nBandCount = 0;
9557 : const GDALDataset *m_poDS = nullptr;
9558 : };
9559 :
9560 2 : GDALDataset::ConstBands::Iterator::Iterator(const GDALDataset *poDS,
9561 2 : bool bStart)
9562 2 : : m_poPrivate(new GDALDataset::ConstBands::Iterator::Private())
9563 : {
9564 2 : m_poPrivate->m_poDS = poDS;
9565 2 : m_poPrivate->m_nBandCount = poDS->GetRasterCount();
9566 2 : if (bStart)
9567 : {
9568 1 : if (m_poPrivate->m_nBandCount)
9569 1 : m_poPrivate->m_poBand = poDS->GetRasterBand(1);
9570 : }
9571 : else
9572 : {
9573 1 : m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
9574 : }
9575 2 : }
9576 :
9577 : GDALDataset::ConstBands::Iterator::~Iterator() = default;
9578 :
9579 3 : const GDALRasterBand *GDALDataset::ConstBands::Iterator::operator*() const
9580 : {
9581 3 : return m_poPrivate->m_poBand;
9582 : }
9583 :
9584 : GDALDataset::ConstBands::Iterator &
9585 3 : GDALDataset::ConstBands::Iterator::operator++()
9586 : {
9587 3 : m_poPrivate->m_iCurBand++;
9588 3 : if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
9589 : {
9590 2 : m_poPrivate->m_poBand =
9591 2 : m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
9592 : }
9593 : else
9594 : {
9595 1 : m_poPrivate->m_poBand = nullptr;
9596 : }
9597 3 : return *this;
9598 : }
9599 :
9600 4 : bool GDALDataset::ConstBands::Iterator::operator!=(const Iterator &it) const
9601 : {
9602 4 : return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
9603 : }
9604 :
9605 : /************************************************************************/
9606 : /* GetBands() */
9607 : /************************************************************************/
9608 :
9609 : /** Function that returns an iterable object over GDALRasterBand in the dataset.
9610 : *
9611 : * This is a C++ iterator friendly version of GetRasterBand().
9612 : *
9613 : * Typical use is:
9614 : * \code{.cpp}
9615 : * for( const auto* poBand: poDS->GetConstBands() )
9616 : * {
9617 : * std::cout << "Band << poBand->GetDescription() << std::endl;
9618 : * }
9619 : * \endcode
9620 : *
9621 : * @see GetRasterBand()
9622 : *
9623 : * @since GDAL 3.12
9624 : */
9625 4 : GDALDataset::ConstBands GDALDataset::GetBands() const
9626 : {
9627 4 : return ConstBands(this);
9628 : }
9629 :
9630 : /************************************************************************/
9631 : /* begin() */
9632 : /************************************************************************/
9633 :
9634 : /**
9635 : \brief Return beginning of band iterator.
9636 :
9637 : @since GDAL 3.12
9638 : */
9639 :
9640 1 : const GDALDataset::ConstBands::Iterator GDALDataset::ConstBands::begin() const
9641 : {
9642 1 : return {m_poSelf, true};
9643 : }
9644 :
9645 : /************************************************************************/
9646 : /* end() */
9647 : /************************************************************************/
9648 :
9649 : /**
9650 : \brief Return end of band iterator.
9651 :
9652 : @since GDAL 3.12
9653 : */
9654 :
9655 1 : const GDALDataset::ConstBands::Iterator GDALDataset::ConstBands::end() const
9656 : {
9657 1 : return {m_poSelf, false};
9658 : }
9659 :
9660 : /************************************************************************/
9661 : /* size() */
9662 : /************************************************************************/
9663 :
9664 : /**
9665 : \brief Get the number of raster bands in this dataset.
9666 :
9667 : @return raster band count.
9668 :
9669 : @since GDAL 3.12
9670 : */
9671 :
9672 1 : size_t GDALDataset::ConstBands::size() const
9673 : {
9674 1 : return static_cast<size_t>(m_poSelf->GetRasterCount());
9675 : }
9676 :
9677 : /************************************************************************/
9678 : /* operator[]() */
9679 : /************************************************************************/
9680 : /**
9681 : \brief Fetch a raster band by index.
9682 :
9683 : The returned band remains owned by the
9684 : GDALDataset and should not be deleted by the application.
9685 :
9686 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9687 : consistent with the conventions of C/C++, i.e. starting at 0.
9688 :
9689 : @param iBand a band index between 0 and size()-1.
9690 :
9691 : @return the band, or nullptr if iBand is out of range or an error occurs.
9692 :
9693 : @since GDAL 3.12
9694 : */
9695 :
9696 1 : const GDALRasterBand *GDALDataset::ConstBands::operator[](int iBand) const
9697 : {
9698 1 : return m_poSelf->GetRasterBand(1 + iBand);
9699 : }
9700 :
9701 : /************************************************************************/
9702 : /* operator[]() */
9703 : /************************************************************************/
9704 :
9705 : /**
9706 : \brief Fetch a raster band by index.
9707 :
9708 : The returned band remains owned by the
9709 : GDALDataset and should not be deleted by the application.
9710 :
9711 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9712 : consistent with the conventions of C/C++, i.e. starting at 0.
9713 :
9714 : @param iBand a band index between 0 and size()-1.
9715 :
9716 : @return the band, or nullptr if iBand is out of range or an error occurs.
9717 :
9718 : @since GDAL 3.12
9719 : */
9720 :
9721 1 : const GDALRasterBand *GDALDataset::ConstBands::operator[](size_t iBand) const
9722 : {
9723 1 : return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
9724 : }
9725 :
9726 : /************************************************************************/
9727 : /* GetRootGroup() */
9728 : /************************************************************************/
9729 :
9730 : /**
9731 : \brief Return the root GDALGroup of this dataset.
9732 :
9733 : Only valid for multidimensional datasets.
9734 :
9735 : This is the same as the C function GDALDatasetGetRootGroup().
9736 :
9737 : @since GDAL 3.1
9738 : */
9739 :
9740 2806 : std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
9741 : {
9742 2806 : return nullptr;
9743 : }
9744 :
9745 : /************************************************************************/
9746 : /* GetRawBinaryLayout() */
9747 : /************************************************************************/
9748 :
9749 : //! @cond Doxygen_Suppress
9750 : /**
9751 : \brief Return the layout of a dataset that can be considered as a raw binary
9752 : format.
9753 :
9754 : @param sLayout Structure that will be set if the dataset is a raw binary one.
9755 : @return true if the dataset is a raw binary one.
9756 : @since GDAL 3.1
9757 : */
9758 :
9759 0 : bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)
9760 : {
9761 0 : CPL_IGNORE_RET_VAL(sLayout);
9762 0 : return false;
9763 : }
9764 :
9765 : //! @endcond
9766 :
9767 : /************************************************************************/
9768 : /* ClearStatistics() */
9769 : /************************************************************************/
9770 :
9771 : /**
9772 : \brief Clear statistics
9773 :
9774 : Only implemented for now in PAM supported datasets
9775 :
9776 : This is the same as the C function GDALDatasetClearStatistics().
9777 :
9778 : @since GDAL 3.2
9779 : */
9780 :
9781 11 : void GDALDataset::ClearStatistics()
9782 : {
9783 22 : auto poRootGroup = GetRootGroup();
9784 11 : if (poRootGroup)
9785 1 : poRootGroup->ClearStatistics();
9786 11 : }
9787 :
9788 : /************************************************************************/
9789 : /* GDALDatasetClearStatistics() */
9790 : /************************************************************************/
9791 :
9792 : /**
9793 : \brief Clear statistics
9794 :
9795 : This is the same as the C++ method GDALDataset::ClearStatistics().
9796 :
9797 : @since GDAL 3.2
9798 : */
9799 :
9800 2 : void GDALDatasetClearStatistics(GDALDatasetH hDS)
9801 : {
9802 2 : VALIDATE_POINTER0(hDS, __func__);
9803 2 : GDALDataset::FromHandle(hDS)->ClearStatistics();
9804 : }
9805 :
9806 : /************************************************************************/
9807 : /* GetFieldDomainNames() */
9808 : /************************************************************************/
9809 :
9810 : /** Returns a list of the names of all field domains stored in the dataset.
9811 : *
9812 : * @note The default implementation assumes that drivers fully populate
9813 : * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect
9814 : * then a specialized implementation of GetFieldDomainNames() must be
9815 : * implemented.
9816 : *
9817 : * @param papszOptions Driver specific options determining how attributes
9818 : * should be retrieved. Pass nullptr for default behavior.
9819 : *
9820 : * @return list of field domain names
9821 : * @since GDAL 3.5
9822 : */
9823 : std::vector<std::string>
9824 44 : GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const
9825 : {
9826 :
9827 44 : std::vector<std::string> names;
9828 44 : names.reserve(m_oMapFieldDomains.size());
9829 56 : for (const auto &it : m_oMapFieldDomains)
9830 : {
9831 12 : names.emplace_back(it.first);
9832 : }
9833 44 : return names;
9834 : }
9835 :
9836 : /************************************************************************/
9837 : /* GDALDatasetGetFieldDomainNames() */
9838 : /************************************************************************/
9839 :
9840 : /** Returns a list of the names of all field domains stored in the dataset.
9841 : *
9842 : * This is the same as the C++ method GDALDataset::GetFieldDomainNames().
9843 : *
9844 : * @param hDS Dataset handle.
9845 : * @param papszOptions Driver specific options determining how attributes
9846 : * should be retrieved. Pass nullptr for default behavior.
9847 : *
9848 : * @return list of field domain names, to be freed with CSLDestroy()
9849 : * @since GDAL 3.5
9850 : */
9851 32 : char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,
9852 : CSLConstList papszOptions)
9853 : {
9854 32 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9855 : auto names =
9856 64 : GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);
9857 64 : CPLStringList res;
9858 137 : for (const auto &name : names)
9859 : {
9860 105 : res.AddString(name.c_str());
9861 : }
9862 32 : return res.StealList();
9863 : }
9864 :
9865 : /************************************************************************/
9866 : /* GetFieldDomain() */
9867 : /************************************************************************/
9868 :
9869 : /** Get a field domain from its name.
9870 : *
9871 : * @return the field domain, or nullptr if not found.
9872 : * @since GDAL 3.3
9873 : */
9874 270 : const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const
9875 : {
9876 270 : const auto iter = m_oMapFieldDomains.find(name);
9877 270 : if (iter == m_oMapFieldDomains.end())
9878 116 : return nullptr;
9879 154 : return iter->second.get();
9880 : }
9881 :
9882 : /************************************************************************/
9883 : /* GDALDatasetGetFieldDomain() */
9884 : /************************************************************************/
9885 :
9886 : /** Get a field domain from its name.
9887 : *
9888 : * This is the same as the C++ method GDALDataset::GetFieldDomain().
9889 : *
9890 : * @param hDS Dataset handle.
9891 : * @param pszName Name of field domain.
9892 : * @return the field domain (ownership remains to the dataset), or nullptr if
9893 : * not found.
9894 : * @since GDAL 3.3
9895 : */
9896 114 : OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)
9897 : {
9898 114 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9899 114 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9900 114 : return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(
9901 114 : GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
9902 : }
9903 :
9904 : /************************************************************************/
9905 : /* AddFieldDomain() */
9906 : /************************************************************************/
9907 :
9908 : /** Add a field domain to the dataset.
9909 : *
9910 : * Only a few drivers will support this operation, and some of them might only
9911 : * support it only for some types of field domains.
9912 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9913 : * support this operation. A dataset having at least some support for this
9914 : * operation should report the ODsCAddFieldDomain dataset capability.
9915 : *
9916 : * Anticipated failures will not be emitted through the CPLError()
9917 : * infrastructure, but will be reported in the failureReason output parameter.
9918 : *
9919 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9920 : * default implementation of GetFieldDomainNames() to work correctly, or
9921 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9922 : * implemented.
9923 : *
9924 : * @param domain The domain definition.
9925 : * @param failureReason Output parameter. Will contain an error message if
9926 : * an error occurs.
9927 : * @return true in case of success.
9928 : * @since GDAL 3.3
9929 : */
9930 0 : bool GDALDataset::AddFieldDomain(
9931 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9932 : std::string &failureReason)
9933 : {
9934 0 : failureReason = "AddFieldDomain not supported by this driver";
9935 0 : return false;
9936 : }
9937 :
9938 : /************************************************************************/
9939 : /* GDALDatasetAddFieldDomain() */
9940 : /************************************************************************/
9941 :
9942 : /** Add a field domain to the dataset.
9943 : *
9944 : * Only a few drivers will support this operation, and some of them might only
9945 : * support it only for some types of field domains.
9946 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9947 : * support this operation. A dataset having at least some support for this
9948 : * operation should report the ODsCAddFieldDomain dataset capability.
9949 : *
9950 : * Anticipated failures will not be emitted through the CPLError()
9951 : * infrastructure, but will be reported in the ppszFailureReason output
9952 : * parameter.
9953 : *
9954 : * @param hDS Dataset handle.
9955 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9956 : * the passed object is copied.
9957 : * @param ppszFailureReason Output parameter. Will contain an error message if
9958 : * an error occurs (*ppszFailureReason to be freed
9959 : * with CPLFree). May be NULL.
9960 : * @return true in case of success.
9961 : * @since GDAL 3.3
9962 : */
9963 37 : bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,
9964 : char **ppszFailureReason)
9965 : {
9966 37 : VALIDATE_POINTER1(hDS, __func__, false);
9967 37 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9968 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9969 74 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9970 37 : if (poDomain == nullptr)
9971 0 : return false;
9972 37 : std::string failureReason;
9973 74 : const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(
9974 37 : std::move(poDomain), failureReason);
9975 37 : if (ppszFailureReason)
9976 : {
9977 37 : *ppszFailureReason =
9978 37 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9979 : }
9980 37 : return bRet;
9981 : }
9982 :
9983 : /************************************************************************/
9984 : /* DeleteFieldDomain() */
9985 : /************************************************************************/
9986 :
9987 : /** Removes a field domain from the dataset.
9988 : *
9989 : * Only a few drivers will support this operation.
9990 : *
9991 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9992 : * support this operation. A dataset having at least some support for this
9993 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9994 : *
9995 : * Anticipated failures will not be emitted through the CPLError()
9996 : * infrastructure, but will be reported in the failureReason output parameter.
9997 : *
9998 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9999 : * default implementation of GetFieldDomainNames() to work correctly, or
10000 : * alternatively a specialized implementation of GetFieldDomainNames() should be
10001 : * implemented.
10002 : *
10003 : * @param name The domain name.
10004 : * @param failureReason Output parameter. Will contain an error message if
10005 : * an error occurs.
10006 : * @return true in case of success.
10007 : * @since GDAL 3.5
10008 : */
10009 0 : bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,
10010 : std::string &failureReason)
10011 : {
10012 0 : failureReason = "DeleteFieldDomain not supported by this driver";
10013 0 : return false;
10014 : }
10015 :
10016 : /************************************************************************/
10017 : /* GDALDatasetDeleteFieldDomain() */
10018 : /************************************************************************/
10019 :
10020 : /** Removes a field domain from the dataset.
10021 : *
10022 : * Only a few drivers will support this operation.
10023 : *
10024 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
10025 : * support this operation. A dataset having at least some support for this
10026 : * operation should report the ODsCDeleteFieldDomain dataset capability.
10027 : *
10028 : * Anticipated failures will not be emitted through the CPLError()
10029 : * infrastructure, but will be reported in the ppszFailureReason output
10030 : * parameter.
10031 : *
10032 : * @param hDS Dataset handle.
10033 : * @param pszName The domain name.
10034 : * @param ppszFailureReason Output parameter. Will contain an error message if
10035 : * an error occurs (*ppszFailureReason to be freed
10036 : * with CPLFree). May be NULL.
10037 : * @return true in case of success.
10038 : * @since GDAL 3.3
10039 : */
10040 8 : bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,
10041 : char **ppszFailureReason)
10042 : {
10043 8 : VALIDATE_POINTER1(hDS, __func__, false);
10044 8 : VALIDATE_POINTER1(pszName, __func__, false);
10045 8 : std::string failureReason;
10046 : const bool bRet =
10047 8 : GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);
10048 8 : if (ppszFailureReason)
10049 : {
10050 0 : *ppszFailureReason =
10051 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
10052 : }
10053 8 : return bRet;
10054 : }
10055 :
10056 : /************************************************************************/
10057 : /* UpdateFieldDomain() */
10058 : /************************************************************************/
10059 :
10060 : /** Updates an existing field domain by replacing its definition.
10061 : *
10062 : * The existing field domain with matching name will be replaced.
10063 : *
10064 : * Only a few drivers will support this operation, and some of them might only
10065 : * support it only for some types of field domains.
10066 : * At the time of writing (GDAL 3.5), only the Memory driver
10067 : * supports this operation. A dataset having at least some support for this
10068 : * operation should report the ODsCUpdateFieldDomain dataset capability.
10069 : *
10070 : * Anticipated failures will not be emitted through the CPLError()
10071 : * infrastructure, but will be reported in the failureReason output parameter.
10072 : *
10073 : * @param domain The domain definition.
10074 : * @param failureReason Output parameter. Will contain an error message if
10075 : * an error occurs.
10076 : * @return true in case of success.
10077 : * @since GDAL 3.5
10078 : */
10079 0 : bool GDALDataset::UpdateFieldDomain(
10080 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
10081 : std::string &failureReason)
10082 : {
10083 0 : failureReason = "UpdateFieldDomain not supported by this driver";
10084 0 : return false;
10085 : }
10086 :
10087 : /************************************************************************/
10088 : /* GDALDatasetUpdateFieldDomain() */
10089 : /************************************************************************/
10090 :
10091 : /** Updates an existing field domain by replacing its definition.
10092 : *
10093 : * The existing field domain with matching name will be replaced.
10094 : *
10095 : * Only a few drivers will support this operation, and some of them might only
10096 : * support it only for some types of field domains.
10097 : * At the time of writing (GDAL 3.5), only the Memory driver
10098 : * supports this operation. A dataset having at least some support for this
10099 : * operation should report the ODsCUpdateFieldDomain dataset capability.
10100 : *
10101 : * Anticipated failures will not be emitted through the CPLError()
10102 : * infrastructure, but will be reported in the failureReason output parameter.
10103 : *
10104 : * @param hDS Dataset handle.
10105 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
10106 : * the passed object is copied.
10107 : * @param ppszFailureReason Output parameter. Will contain an error message if
10108 : * an error occurs (*ppszFailureReason to be freed
10109 : * with CPLFree). May be NULL.
10110 : * @return true in case of success.
10111 : * @since GDAL 3.5
10112 : */
10113 4 : bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,
10114 : OGRFieldDomainH hFieldDomain,
10115 : char **ppszFailureReason)
10116 : {
10117 4 : VALIDATE_POINTER1(hDS, __func__, false);
10118 4 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
10119 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
10120 8 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
10121 4 : if (poDomain == nullptr)
10122 0 : return false;
10123 4 : std::string failureReason;
10124 8 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(
10125 4 : std::move(poDomain), failureReason);
10126 4 : if (ppszFailureReason)
10127 : {
10128 0 : *ppszFailureReason =
10129 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
10130 : }
10131 4 : return bRet;
10132 : }
10133 :
10134 : /************************************************************************/
10135 : /* GetRelationshipNames() */
10136 : /************************************************************************/
10137 :
10138 : /** Returns a list of the names of all relationships stored in the dataset.
10139 : *
10140 : * @param papszOptions Driver specific options determining how relationships
10141 : * should be retrieved. Pass nullptr for default behavior.
10142 : *
10143 : * @return list of relationship names
10144 : * @since GDAL 3.6
10145 : */
10146 : std::vector<std::string>
10147 180 : GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const
10148 : {
10149 180 : return {};
10150 : }
10151 :
10152 : /************************************************************************/
10153 : /* GDALDatasetGetRelationshipNames() */
10154 : /************************************************************************/
10155 :
10156 : /** Returns a list of the names of all relationships stored in the dataset.
10157 : *
10158 : * This is the same as the C++ method GDALDataset::GetRelationshipNames().
10159 : *
10160 : * @param hDS Dataset handle.
10161 : * @param papszOptions Driver specific options determining how relationships
10162 : * should be retrieved. Pass nullptr for default behavior.
10163 : *
10164 : * @return list of relationship names, to be freed with CSLDestroy()
10165 : * @since GDAL 3.6
10166 : */
10167 46 : char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,
10168 : CSLConstList papszOptions)
10169 : {
10170 46 : VALIDATE_POINTER1(hDS, __func__, nullptr);
10171 : auto names =
10172 92 : GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);
10173 92 : CPLStringList res;
10174 146 : for (const auto &name : names)
10175 : {
10176 100 : res.AddString(name.c_str());
10177 : }
10178 46 : return res.StealList();
10179 : }
10180 :
10181 : /************************************************************************/
10182 : /* GetRelationship() */
10183 : /************************************************************************/
10184 :
10185 : /** Get a relationship from its name.
10186 : *
10187 : * @return the relationship, or nullptr if not found.
10188 : * @since GDAL 3.6
10189 : */
10190 : const GDALRelationship *
10191 0 : GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const
10192 : {
10193 0 : return nullptr;
10194 : }
10195 :
10196 : /************************************************************************/
10197 : /* GDALDatasetGetRelationship() */
10198 : /************************************************************************/
10199 :
10200 : /** Get a relationship from its name.
10201 : *
10202 : * This is the same as the C++ method GDALDataset::GetRelationship().
10203 : *
10204 : * @param hDS Dataset handle.
10205 : * @param pszName Name of relationship.
10206 : * @return the relationship (ownership remains to the dataset), or nullptr if
10207 : * not found.
10208 : * @since GDAL 3.6
10209 : */
10210 52 : GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,
10211 : const char *pszName)
10212 : {
10213 52 : VALIDATE_POINTER1(hDS, __func__, nullptr);
10214 52 : VALIDATE_POINTER1(pszName, __func__, nullptr);
10215 52 : return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(
10216 52 : GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));
10217 : }
10218 :
10219 : /************************************************************************/
10220 : /* AddRelationship() */
10221 : /************************************************************************/
10222 :
10223 : /** Add a relationship to the dataset.
10224 : *
10225 : * Only a few drivers will support this operation, and some of them might only
10226 : * support it only for some types of relationships.
10227 : *
10228 : * A dataset having at least some support for this
10229 : * operation should report the GDsCAddRelationship dataset capability.
10230 : *
10231 : * Anticipated failures will not be emitted through the CPLError()
10232 : * infrastructure, but will be reported in the failureReason output parameter.
10233 : *
10234 : * When adding a many-to-many relationship
10235 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
10236 : * mapping table name (see GDALRelationship::GetMappingTableName) to instruct
10237 : * the driver to create an appropriately named and structured mapping table.
10238 : * Some dataset formats require particular naming conventions and field
10239 : * structures for the mapping table, and delegating the construction of the
10240 : * mapping table to the driver will avoid these pitfalls.
10241 : *
10242 : * @param relationship The relationship definition.
10243 : * @param failureReason Output parameter. Will contain an error message if
10244 : * an error occurs.
10245 : * @return true in case of success.
10246 : * @since GDAL 3.6
10247 : */
10248 0 : bool GDALDataset::AddRelationship(
10249 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
10250 : std::string &failureReason)
10251 : {
10252 0 : failureReason = "AddRelationship not supported by this driver";
10253 0 : return false;
10254 : }
10255 :
10256 : /************************************************************************/
10257 : /* GDALDatasetAddRelationship() */
10258 : /************************************************************************/
10259 :
10260 : /** Add a relationship to the dataset.
10261 : *
10262 : * Only a few drivers will support this operation, and some of them might only
10263 : * support it only for some types of relationships.
10264 : *
10265 : * A dataset having at least some support for this
10266 : * operation should report the GDsCAddRelationship dataset capability.
10267 : *
10268 : * Anticipated failures will not be emitted through the CPLError()
10269 : * infrastructure, but will be reported in the failureReason output parameter.
10270 : *
10271 : * When adding a many-to-many relationship
10272 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
10273 : * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the
10274 : * driver to create an appropriately named and structured mapping table. Some
10275 : * dataset formats require particular naming conventions and field structures
10276 : * for the mapping table, and delegating the construction of the mapping table
10277 : * to the driver will avoid these pitfalls.
10278 : *
10279 : * @param hDS Dataset handle.
10280 : * @param hRelationship The relationship definition. Contrary to the C++
10281 : * version, the passed object is copied.
10282 : * @param ppszFailureReason Output parameter. Will contain an error message if
10283 : * an error occurs (*ppszFailureReason to be freed
10284 : * with CPLFree). May be NULL.
10285 : * @return true in case of success.
10286 : * @since GDAL 3.6
10287 : */
10288 42 : bool GDALDatasetAddRelationship(GDALDatasetH hDS,
10289 : GDALRelationshipH hRelationship,
10290 : char **ppszFailureReason)
10291 : {
10292 42 : VALIDATE_POINTER1(hDS, __func__, false);
10293 42 : VALIDATE_POINTER1(hRelationship, __func__, false);
10294 : std::unique_ptr<GDALRelationship> poRelationship(
10295 84 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
10296 42 : std::string failureReason;
10297 84 : const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(
10298 42 : std::move(poRelationship), failureReason);
10299 42 : if (ppszFailureReason)
10300 : {
10301 0 : *ppszFailureReason =
10302 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
10303 : }
10304 42 : return bRet;
10305 : }
10306 :
10307 : /************************************************************************/
10308 : /* DeleteRelationship() */
10309 : /************************************************************************/
10310 :
10311 : /** Removes a relationship from the dataset.
10312 : *
10313 : * Only a few drivers will support this operation.
10314 : *
10315 : * A dataset having at least some support for this
10316 : * operation should report the GDsCDeleteRelationship dataset capability.
10317 : *
10318 : * Anticipated failures will not be emitted through the CPLError()
10319 : * infrastructure, but will be reported in the failureReason output parameter.
10320 : *
10321 : * @param name The relationship name.
10322 : * @param failureReason Output parameter. Will contain an error message if
10323 : * an error occurs.
10324 : * @return true in case of success.
10325 : * @since GDAL 3.6
10326 : */
10327 0 : bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,
10328 : std::string &failureReason)
10329 : {
10330 0 : failureReason = "DeleteRelationship not supported by this driver";
10331 0 : return false;
10332 : }
10333 :
10334 : /************************************************************************/
10335 : /* GDALDatasetDeleteRelationship() */
10336 : /************************************************************************/
10337 :
10338 : /** Removes a relationship from the dataset.
10339 : *
10340 : * Only a few drivers will support this operation.
10341 : *
10342 : * A dataset having at least some support for this
10343 : * operation should report the GDsCDeleteRelationship dataset capability.
10344 : *
10345 : * Anticipated failures will not be emitted through the CPLError()
10346 : * infrastructure, but will be reported in the ppszFailureReason output
10347 : * parameter.
10348 : *
10349 : * @param hDS Dataset handle.
10350 : * @param pszName The relationship name.
10351 : * @param ppszFailureReason Output parameter. Will contain an error message if
10352 : * an error occurs (*ppszFailureReason to be freed
10353 : * with CPLFree). May be NULL.
10354 : * @return true in case of success.
10355 : * @since GDAL 3.6
10356 : */
10357 6 : bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,
10358 : char **ppszFailureReason)
10359 : {
10360 6 : VALIDATE_POINTER1(hDS, __func__, false);
10361 6 : VALIDATE_POINTER1(pszName, __func__, false);
10362 6 : std::string failureReason;
10363 12 : const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(
10364 6 : pszName, failureReason);
10365 6 : if (ppszFailureReason)
10366 : {
10367 0 : *ppszFailureReason =
10368 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
10369 : }
10370 6 : return bRet;
10371 : }
10372 :
10373 : /************************************************************************/
10374 : /* UpdateRelationship() */
10375 : /************************************************************************/
10376 :
10377 : /** Updates an existing relationship by replacing its definition.
10378 : *
10379 : * The existing relationship with matching name will be replaced.
10380 : *
10381 : * Only a few drivers will support this operation, and some of them might only
10382 : * support it only for some types of relationships.
10383 : * A dataset having at least some support for this
10384 : * operation should report the GDsCUpdateRelationship dataset capability.
10385 : *
10386 : * Anticipated failures will not be emitted through the CPLError()
10387 : * infrastructure, but will be reported in the failureReason output parameter.
10388 : *
10389 : * @param relationship The relationship definition.
10390 : * @param failureReason Output parameter. Will contain an error message if
10391 : * an error occurs.
10392 : * @return true in case of success.
10393 : * @since GDAL 3.6
10394 : */
10395 0 : bool GDALDataset::UpdateRelationship(
10396 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
10397 : std::string &failureReason)
10398 : {
10399 0 : failureReason = "UpdateRelationship not supported by this driver";
10400 0 : return false;
10401 : }
10402 :
10403 : /************************************************************************/
10404 : /* GDALDatasetUpdateRelationship() */
10405 : /************************************************************************/
10406 :
10407 : /** Updates an existing relationship by replacing its definition.
10408 : *
10409 : * The existing relationship with matching name will be replaced.
10410 : *
10411 : * Only a few drivers will support this operation, and some of them might only
10412 : * support it only for some types of relationships.
10413 : * A dataset having at least some support for this
10414 : * operation should report the GDsCUpdateRelationship dataset capability.
10415 : *
10416 : * Anticipated failures will not be emitted through the CPLError()
10417 : * infrastructure, but will be reported in the failureReason output parameter.
10418 : *
10419 : * @param hDS Dataset handle.
10420 : * @param hRelationship The relationship definition. Contrary to the C++
10421 : * version, the passed object is copied.
10422 : * @param ppszFailureReason Output parameter. Will contain an error message if
10423 : * an error occurs (*ppszFailureReason to be freed
10424 : * with CPLFree). May be NULL.
10425 : * @return true in case of success.
10426 : * @since GDAL 3.5
10427 : */
10428 9 : bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,
10429 : GDALRelationshipH hRelationship,
10430 : char **ppszFailureReason)
10431 : {
10432 9 : VALIDATE_POINTER1(hDS, __func__, false);
10433 9 : VALIDATE_POINTER1(hRelationship, __func__, false);
10434 : std::unique_ptr<GDALRelationship> poRelationship(
10435 18 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
10436 9 : std::string failureReason;
10437 18 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(
10438 9 : std::move(poRelationship), failureReason);
10439 9 : if (ppszFailureReason)
10440 : {
10441 0 : *ppszFailureReason =
10442 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
10443 : }
10444 9 : return bRet;
10445 : }
10446 :
10447 : /************************************************************************/
10448 : /* GDALDatasetSetQueryLoggerFunc() */
10449 : /************************************************************************/
10450 :
10451 : /**
10452 : * Sets the SQL query logger callback.
10453 : *
10454 : * When supported by the driver, the callback will be called with
10455 : * the executed SQL text, the error message, the execution time in milliseconds,
10456 : * the number of records fetched/affected and the client status data.
10457 : *
10458 : * A value of -1 in the execution time or in the number of records indicates
10459 : * that the values are unknown.
10460 : *
10461 : * @param hDS Dataset handle.
10462 : * @param pfnQueryLoggerFunc Callback function
10463 : * @param poQueryLoggerArg Opaque client status data
10464 : * @return true in case of success.
10465 : * @since GDAL 3.7
10466 : */
10467 1 : bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,
10468 : GDALQueryLoggerFunc pfnQueryLoggerFunc,
10469 : void *poQueryLoggerArg)
10470 : {
10471 1 : VALIDATE_POINTER1(hDS, __func__, false);
10472 2 : return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,
10473 1 : poQueryLoggerArg);
10474 : }
10475 :
10476 : //! @cond Doxygen_Suppress
10477 :
10478 : /************************************************************************/
10479 : /* SetEnableOverviews() */
10480 : /************************************************************************/
10481 :
10482 7521 : void GDALDataset::SetEnableOverviews(bool bEnable)
10483 : {
10484 7521 : if (m_poPrivate)
10485 : {
10486 7521 : m_poPrivate->m_bOverviewsEnabled = bEnable;
10487 : }
10488 7521 : }
10489 :
10490 : /************************************************************************/
10491 : /* AreOverviewsEnabled() */
10492 : /************************************************************************/
10493 :
10494 2006070 : bool GDALDataset::AreOverviewsEnabled() const
10495 : {
10496 2006070 : return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
10497 : }
10498 :
10499 : /************************************************************************/
10500 : /* IsAllBands() */
10501 : /************************************************************************/
10502 :
10503 3696 : bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const
10504 : {
10505 3696 : if (nBands != nBandCount)
10506 1 : return false;
10507 3695 : if (panBandList)
10508 : {
10509 13681 : for (int i = 0; i < nBandCount; ++i)
10510 : {
10511 10080 : if (panBandList[i] != i + 1)
10512 27 : return false;
10513 : }
10514 : }
10515 3668 : return true;
10516 : }
10517 :
10518 : //! @endcond
10519 :
10520 : /************************************************************************/
10521 : /* GetCompressionFormats() */
10522 : /************************************************************************/
10523 :
10524 : /** Return the compression formats that can be natively obtained for the
10525 : * window of interest and requested bands.
10526 : *
10527 : * For example, a tiled dataset may be able to return data in a compressed
10528 : * format if the window of interest matches exactly a tile. For some formats,
10529 : * drivers may also be able to merge several tiles together (not currently
10530 : * implemented though).
10531 : *
10532 : * Each format string is a pseudo MIME type, whose first part can be passed
10533 : * as the pszFormat argument of ReadCompressedData(), with additional
10534 : * parameters specified as key=value with a semi-colon separator.
10535 : *
10536 : * The amount and types of optional parameters passed after the MIME type is
10537 : * format dependent, and driver dependent (some drivers might not be able to
10538 : * return those extra information without doing a rather costly processing).
10539 : *
10540 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
10541 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
10542 : * consequently "JPEG" can be passed as the pszFormat argument of
10543 : * ReadCompressedData(). For JPEG, implementations can use the
10544 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
10545 : * above from a JPEG codestream.
10546 : *
10547 : * Several values might be returned. For example,
10548 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
10549 : * if the JPEGXL codestream includes a JPEG reconstruction box.
10550 : *
10551 : * In the general case this method will return an empty list.
10552 : *
10553 : * This is the same as C function GDALDatasetGetCompressionFormats().
10554 : *
10555 : * @param nXOff The pixel offset to the top left corner of the region
10556 : * of the band to be accessed. This would be zero to start from the left side.
10557 : *
10558 : * @param nYOff The line offset to the top left corner of the region
10559 : * of the band to be accessed. This would be zero to start from the top.
10560 : *
10561 : * @param nXSize The width of the region of the band to be accessed in pixels.
10562 : *
10563 : * @param nYSize The height of the region of the band to be accessed in lines.
10564 : *
10565 : * @param nBandCount the number of bands being requested.
10566 : *
10567 : * @param panBandList the list of nBandCount band numbers.
10568 : * Note band numbers are 1 based. This may be NULL to select the first
10569 : * nBandCount bands.
10570 : *
10571 : * @return a list of compatible formats (which may be empty)
10572 : *
10573 : * For example, to check if native compression format(s) are available on the
10574 : * whole image:
10575 : * \code{.cpp}
10576 : * const CPLStringList aosFormats =
10577 : * poDataset->GetCompressionFormats(0, 0,
10578 : * poDataset->GetRasterXSize(),
10579 : * poDataset->GetRasterYSize(),
10580 : * poDataset->GetRasterCount(),
10581 : * nullptr);
10582 : * for( const char* pszFormat: aosFormats )
10583 : * {
10584 : * // Remove optional parameters and just print out the MIME type.
10585 : * const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));
10586 : * printf("Found format %s\n, aosTokens[0]);
10587 : * }
10588 : * \endcode
10589 : *
10590 : * @since GDAL 3.7
10591 : */
10592 : CPLStringList
10593 0 : GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
10594 : CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10595 : CPL_UNUSED int nBandCount,
10596 : CPL_UNUSED const int *panBandList)
10597 : {
10598 0 : return CPLStringList();
10599 : }
10600 :
10601 : /************************************************************************/
10602 : /* GDALDatasetGetCompressionFormats() */
10603 : /************************************************************************/
10604 :
10605 : /** Return the compression formats that can be natively obtained for the
10606 : * window of interest and requested bands.
10607 : *
10608 : * For example, a tiled dataset may be able to return data in a compressed
10609 : * format if the window of interest matches exactly a tile. For some formats,
10610 : * drivers may also be able to merge several tiles together (not currently
10611 : * implemented though).
10612 : *
10613 : * Each format string is a pseudo MIME type, whose first part can be passed
10614 : * as the pszFormat argument of ReadCompressedData(), with additional
10615 : * parameters specified as key=value with a semi-colon separator.
10616 : *
10617 : * The amount and types of optional parameters passed after the MIME type is
10618 : * format dependent, and driver dependent (some drivers might not be able to
10619 : * return those extra information without doing a rather costly processing).
10620 : *
10621 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
10622 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
10623 : * consequently "JPEG" can be passed as the pszFormat argument of
10624 : * ReadCompressedData(). For JPEG, implementations can use the
10625 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
10626 : * above from a JPEG codestream.
10627 : *
10628 : * Several values might be returned. For example,
10629 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
10630 : * if the JPEGXL codestream includes a JPEG reconstruction box.
10631 : *
10632 : * In the general case this method will return an empty list.
10633 : *
10634 : * This is the same as C++ method GDALDataset::GetCompressionFormats().
10635 : *
10636 : * @param hDS Dataset handle.
10637 : *
10638 : * @param nXOff The pixel offset to the top left corner of the region
10639 : * of the band to be accessed. This would be zero to start from the left side.
10640 : *
10641 : * @param nYOff The line offset to the top left corner of the region
10642 : * of the band to be accessed. This would be zero to start from the top.
10643 : *
10644 : * @param nXSize The width of the region of the band to be accessed in pixels.
10645 : *
10646 : * @param nYSize The height of the region of the band to be accessed in lines.
10647 : *
10648 : * @param nBandCount the number of bands being requested.
10649 : *
10650 : * @param panBandList the list of nBandCount band numbers.
10651 : * Note band numbers are 1 based. This may be NULL to select the first
10652 : * nBandCount bands.
10653 : *
10654 : * @return a list of compatible formats (which may be empty) that should be
10655 : * freed with CSLDestroy(), or nullptr.
10656 : *
10657 : * @since GDAL 3.7
10658 : */
10659 9 : char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,
10660 : int nXSize, int nYSize, int nBandCount,
10661 : const int *panBandList)
10662 : {
10663 9 : VALIDATE_POINTER1(hDS, __func__, nullptr);
10664 9 : return GDALDataset::FromHandle(hDS)
10665 9 : ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,
10666 9 : panBandList)
10667 9 : .StealList();
10668 : }
10669 :
10670 : /************************************************************************/
10671 : /* ReadCompressedData() */
10672 : /************************************************************************/
10673 :
10674 : /** Return the compressed content that can be natively obtained for the
10675 : * window of interest and requested bands.
10676 : *
10677 : * For example, a tiled dataset may be able to return data in compressed format
10678 : * if the window of interest matches exactly a tile. For some formats, drivers
10679 : * may also be example to merge several tiles together (not currently
10680 : * implemented though).
10681 : *
10682 : * The implementation should make sure that the content returned forms a valid
10683 : * standalone file. For example, for the GeoTIFF implementation of this method,
10684 : * when extracting a JPEG tile, the method will automatically add the content
10685 : * of the JPEG Huffman and/or quantization tables that might be stored in the
10686 : * TIFF JpegTables tag, and not in tile data itself.
10687 : *
10688 : * In the general case this method will return CE_Failure.
10689 : *
10690 : * This is the same as C function GDALDatasetReadCompressedData().
10691 : *
10692 : * @param pszFormat Requested compression format (e.g. "JPEG",
10693 : * "WEBP", "JXL"). This is the MIME type of one of the values
10694 : * returned by GetCompressionFormats(). The format string is designed to
10695 : * potentially include at a later point key=value optional parameters separated
10696 : * by a semi-colon character. At time of writing, none are implemented.
10697 : * ReadCompressedData() implementations should verify optional parameters and
10698 : * return CE_Failure if they cannot support one of them.
10699 : *
10700 : * @param nXOff The pixel offset to the top left corner of the region
10701 : * of the band to be accessed. This would be zero to start from the left side.
10702 : *
10703 : * @param nYOff The line offset to the top left corner of the region
10704 : * of the band to be accessed. This would be zero to start from the top.
10705 : *
10706 : * @param nXSize The width of the region of the band to be accessed in pixels.
10707 : *
10708 : * @param nYSize The height of the region of the band to be accessed in lines.
10709 : *
10710 : * @param nBandCount the number of bands being requested.
10711 : *
10712 : * @param panBandList the list of nBandCount band numbers.
10713 : * Note band numbers are 1 based. This may be NULL to select the first
10714 : * nBandCount bands.
10715 : *
10716 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10717 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10718 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10719 : * buffer will be filled with the compressed data, provided that pnBufferSize
10720 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10721 : * of *ppBuffer, is sufficiently large to hold the data.
10722 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10723 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10724 : * free it with VSIFree().
10725 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10726 : * but *pnBufferSize will be updated with an upper bound of the size that would
10727 : * be necessary to hold it (if pnBufferSize != nullptr).
10728 : *
10729 : * @param pnBufferSize Output buffer size, or nullptr.
10730 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10731 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10732 : * method is successful, *pnBufferSize will be updated with the actual size
10733 : * used.
10734 : *
10735 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10736 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10737 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10738 : * *ppszDetailedFormat might contain strings like
10739 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10740 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10741 : * The string will contain at least as much information as what
10742 : * GetCompressionFormats() returns, and potentially more when
10743 : * ppBuffer != nullptr.
10744 : *
10745 : * @return CE_None in case of success, CE_Failure otherwise.
10746 : *
10747 : * For example, to request JPEG content on the whole image and let GDAL deal
10748 : * with the buffer allocation.
10749 : * \code{.cpp}
10750 : * void* pBuffer = nullptr;
10751 : * size_t nBufferSize = 0;
10752 : * CPLErr eErr =
10753 : * poDataset->ReadCompressedData("JPEG",
10754 : * 0, 0,
10755 : * poDataset->GetRasterXSize(),
10756 : * poDataset->GetRasterYSize(),
10757 : * poDataset->GetRasterCount(),
10758 : * nullptr, // panBandList
10759 : * &pBuffer,
10760 : * &nBufferSize,
10761 : * nullptr // ppszDetailedFormat
10762 : * );
10763 : * if (eErr == CE_None)
10764 : * {
10765 : * CPLAssert(pBuffer != nullptr);
10766 : * CPLAssert(nBufferSize > 0);
10767 : * VSILFILE* fp = VSIFOpenL("my.jpeg", "wb");
10768 : * if (fp)
10769 : * {
10770 : * VSIFWriteL(pBuffer, nBufferSize, 1, fp);
10771 : * VSIFCloseL(fp);
10772 : * }
10773 : * VSIFree(pBuffer);
10774 : * }
10775 : * \endcode
10776 : *
10777 : * Or to manage the buffer allocation on your side:
10778 : * \code{.cpp}
10779 : * size_t nUpperBoundBufferSize = 0;
10780 : * CPLErr eErr =
10781 : * poDataset->ReadCompressedData("JPEG",
10782 : * 0, 0,
10783 : * poDataset->GetRasterXSize(),
10784 : * poDataset->GetRasterYSize(),
10785 : * poDataset->GetRasterCount(),
10786 : * nullptr, // panBandList
10787 : * nullptr, // ppBuffer,
10788 : * &nUpperBoundBufferSize,
10789 : * nullptr // ppszDetailedFormat
10790 : * );
10791 : * if (eErr == CE_None)
10792 : * {
10793 : * std::vector<uint8_t> myBuffer;
10794 : * myBuffer.resize(nUpperBoundBufferSize);
10795 : * void* pBuffer = myBuffer.data();
10796 : * size_t nActualSize = nUpperBoundBufferSize;
10797 : * char* pszDetailedFormat = nullptr;
10798 : * // We also request detailed format, but we could have passed it to
10799 : * // nullptr as well.
10800 : * eErr =
10801 : * poDataset->ReadCompressedData("JPEG",
10802 : * 0, 0,
10803 : * poDataset->GetRasterXSize(),
10804 : * poDataset->GetRasterYSize(),
10805 : * poDataset->GetRasterCount(),
10806 : * nullptr, // panBandList
10807 : * &pBuffer,
10808 : * &nActualSize,
10809 : * &pszDetailedFormat);
10810 : * if (eErr == CE_None)
10811 : * {
10812 : * CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified
10813 : * CPLAssert(nActualSize <= nUpperBoundBufferSize);
10814 : * myBuffer.resize(nActualSize);
10815 : * // do something useful
10816 : * VSIFree(pszDetailedFormat);
10817 : * }
10818 : * }
10819 : * \endcode
10820 : *
10821 : * @since GDAL 3.7
10822 : */
10823 441 : CPLErr GDALDataset::ReadCompressedData(
10824 : CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,
10825 : CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10826 : CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,
10827 : CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,
10828 : CPL_UNUSED char **ppszDetailedFormat)
10829 : {
10830 441 : return CE_Failure;
10831 : }
10832 :
10833 : /************************************************************************/
10834 : /* GDALDatasetReadCompressedData() */
10835 : /************************************************************************/
10836 :
10837 : /** Return the compressed content that can be natively obtained for the
10838 : * window of interest and requested bands.
10839 : *
10840 : * For example, a tiled dataset may be able to return data in compressed format
10841 : * if the window of interest matches exactly a tile. For some formats, drivers
10842 : * may also be example to merge several tiles together (not currently
10843 : * implemented though).
10844 : *
10845 : * The implementation should make sure that the content returned forms a valid
10846 : * standalone file. For example, for the GeoTIFF implementation of this method,
10847 : * when extracting a JPEG tile, the method will automatically adds the content
10848 : * of the JPEG Huffman and/or quantization tables that might be stored in the
10849 : * TIFF JpegTables tag, and not in tile data itself.
10850 : *
10851 : * In the general case this method will return CE_Failure.
10852 : *
10853 : * This is the same as C++ method GDALDataset:ReadCompressedData().
10854 : *
10855 : * @param hDS Dataset handle.
10856 : *
10857 : * @param pszFormat Requested compression format (e.g. "JPEG",
10858 : * "WEBP", "JXL"). This is the MIME type of one of the values
10859 : * returned by GetCompressionFormats(). The format string is designed to
10860 : * potentially include at a later point key=value optional parameters separated
10861 : * by a semi-colon character. At time of writing, none are implemented.
10862 : * ReadCompressedData() implementations should verify optional parameters and
10863 : * return CE_Failure if they cannot support one of them.
10864 : *
10865 : * @param nXOff The pixel offset to the top left corner of the region
10866 : * of the band to be accessed. This would be zero to start from the left side.
10867 : *
10868 : * @param nYOff The line offset to the top left corner of the region
10869 : * of the band to be accessed. This would be zero to start from the top.
10870 : *
10871 : * @param nXSize The width of the region of the band to be accessed in pixels.
10872 : *
10873 : * @param nYSize The height of the region of the band to be accessed in lines.
10874 : *
10875 : * @param nBandCount the number of bands being requested.
10876 : *
10877 : * @param panBandList the list of nBandCount band numbers.
10878 : * Note band numbers are 1 based. This may be NULL to select the first
10879 : * nBandCount bands.
10880 : *
10881 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10882 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10883 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10884 : * buffer will be filled with the compressed data, provided that pnBufferSize
10885 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10886 : * of *ppBuffer, is sufficiently large to hold the data.
10887 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10888 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10889 : * free it with VSIFree().
10890 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10891 : * but *pnBufferSize will be updated with an upper bound of the size that would
10892 : * be necessary to hold it (if pnBufferSize != nullptr).
10893 : *
10894 : * @param pnBufferSize Output buffer size, or nullptr.
10895 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10896 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10897 : * method is successful, *pnBufferSize will be updated with the actual size
10898 : * used.
10899 : *
10900 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10901 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10902 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10903 : * *ppszDetailedFormat might contain strings like
10904 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10905 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10906 : * The string will contain at least as much information as what
10907 : * GetCompressionFormats() returns, and potentially more when
10908 : * ppBuffer != nullptr.
10909 : *
10910 : * @return CE_None in case of success, CE_Failure otherwise.
10911 : *
10912 : * @since GDAL 3.7
10913 : */
10914 28 : CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,
10915 : int nXOff, int nYOff, int nXSize,
10916 : int nYSize, int nBandCount,
10917 : const int *panBandList, void **ppBuffer,
10918 : size_t *pnBufferSize,
10919 : char **ppszDetailedFormat)
10920 : {
10921 28 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10922 56 : return GDALDataset::FromHandle(hDS)->ReadCompressedData(
10923 : pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,
10924 28 : ppBuffer, pnBufferSize, ppszDetailedFormat);
10925 : }
10926 :
10927 : /************************************************************************/
10928 : /* CanBeCloned() */
10929 : /************************************************************************/
10930 :
10931 : //! @cond Doxygen_Suppress
10932 :
10933 : /** This method is called by GDALThreadSafeDataset::Create() to determine if
10934 : * it is possible to create a thread-safe wrapper for a dataset, which involves
10935 : * the ability to Clone() it.
10936 : *
10937 : * Implementations of this method must be thread-safe.
10938 : *
10939 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10940 : * expressing the intended use for thread-safety.
10941 : * Currently, the only valid scope is in the base
10942 : * implementation is GDAL_OF_RASTER.
10943 : * @param bCanShareState Determines if cloned datasets are allowed to share
10944 : * state with the dataset they have been cloned from.
10945 : * If set to true, the dataset from which they have been
10946 : * cloned from must remain opened during the lifetime of
10947 : * its clones.
10948 : * @return true if the Clone() method is expected to succeed with the same values
10949 : * of nScopeFlags and bCanShareState.
10950 : */
10951 149 : bool GDALDataset::CanBeCloned(int nScopeFlags,
10952 : [[maybe_unused]] bool bCanShareState) const
10953 : {
10954 149 : return m_bCanBeReopened && nScopeFlags == GDAL_OF_RASTER;
10955 : }
10956 :
10957 : //! @endcond
10958 :
10959 : /************************************************************************/
10960 : /* Clone() */
10961 : /************************************************************************/
10962 :
10963 : //! @cond Doxygen_Suppress
10964 :
10965 : /** This method "clones" the current dataset, that is it returns a new instance
10966 : * that is opened on the same underlying "file".
10967 : *
10968 : * The base implementation uses GDALDataset::Open() to re-open the dataset.
10969 : * The MEM driver has a specialized implementation that returns a new instance,
10970 : * but which shares the same memory buffer as this.
10971 : *
10972 : * Implementations of this method must be thread-safe.
10973 : *
10974 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10975 : * expressing the intended use for thread-safety.
10976 : * Currently, the only valid scope is in the base
10977 : * implementation is GDAL_OF_RASTER.
10978 : * @param bCanShareState Determines if cloned datasets are allowed to share
10979 : * state with the dataset they have been cloned from.
10980 : * If set to true, the dataset from which they have been
10981 : * cloned from must remain opened during the lifetime of
10982 : * its clones.
10983 : * @return a new instance, or nullptr in case of error.
10984 : */
10985 : std::unique_ptr<GDALDataset>
10986 2051 : GDALDataset::Clone(int nScopeFlags, [[maybe_unused]] bool bCanShareState) const
10987 : {
10988 4101 : CPLStringList aosAllowedDrivers;
10989 2051 : if (poDriver)
10990 2051 : aosAllowedDrivers.AddString(poDriver->GetDescription());
10991 : return std::unique_ptr<GDALDataset>(GDALDataset::Open(
10992 2051 : GetDescription(),
10993 2051 : nScopeFlags | GDAL_OF_INTERNAL | GDAL_OF_VERBOSE_ERROR,
10994 4102 : aosAllowedDrivers.List(), papszOpenOptions));
10995 : }
10996 :
10997 : //! @endcond
10998 :
10999 : /************************************************************************/
11000 : /* GeolocationToPixelLine() */
11001 : /************************************************************************/
11002 :
11003 : /** Transform georeferenced coordinates to pixel/line coordinates.
11004 : *
11005 : * When poSRS is null, those georeferenced coordinates (dfGeolocX, dfGeolocY)
11006 : * must be in the "natural" SRS of the dataset, that is the one returned by
11007 : * GetSpatialRef() if there is a geotransform, GetGCPSpatialRef() if there are
11008 : * GCPs, WGS 84 if there are RPC coefficients, or the SRS of the geolocation
11009 : * array (generally WGS 84) if there is a geolocation array.
11010 : * If that natural SRS is a geographic one, dfGeolocX must be a longitude, and
11011 : * dfGeolocY a latitude. If that natural SRS is a projected one, dfGeolocX must
11012 : * be a easting, and dfGeolocY a northing.
11013 : *
11014 : * When poSRS is set to a non-null value, (dfGeolocX, dfGeolocY) must be
11015 : * expressed in that CRS, and that tuple must be conformant with the
11016 : * data-axis-to-crs-axis setting of poSRS, that is the one returned by
11017 : * the OGRSpatialReference::GetDataAxisToSRSAxisMapping(). If you want to be sure
11018 : * of the axis order, then make sure to call poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER)
11019 : * before calling this method, and in that case, dfGeolocX must be a longitude
11020 : * or an easting value, and dfGeolocX a latitude or a northing value.
11021 : *
11022 : * This method uses GDALCreateGenImgProjTransformer2() underneath.
11023 : *
11024 : * @param dfGeolocX X coordinate of the position (longitude or easting if poSRS
11025 : * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
11026 : * where interpolation should be done.
11027 : * @param dfGeolocY Y coordinate of the position (latitude or northing if poSRS
11028 : * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
11029 : * where interpolation should be done.
11030 : * @param poSRS If set, override the natural CRS in which dfGeolocX, dfGeolocY are expressed
11031 : * @param[out] pdfPixel Pointer to the variable where to the store the pixel/column coordinate.
11032 : * @param[out] pdfLine Pointer to the variable where to the store the line coordinate.
11033 : * @param papszTransformerOptions Options accepted by GDALCreateGenImgProjTransformer2(), or nullptr.
11034 : *
11035 : * @return CE_None on success, or an error code on failure.
11036 : * @since GDAL 3.11
11037 : */
11038 :
11039 : CPLErr
11040 15 : GDALDataset::GeolocationToPixelLine(double dfGeolocX, double dfGeolocY,
11041 : const OGRSpatialReference *poSRS,
11042 : double *pdfPixel, double *pdfLine,
11043 : CSLConstList papszTransformerOptions) const
11044 : {
11045 30 : CPLStringList aosTO(papszTransformerOptions);
11046 :
11047 15 : if (poSRS)
11048 : {
11049 4 : const char *const apszOptions[] = {"FORMAT=WKT2", nullptr};
11050 8 : const std::string osWKT = poSRS->exportToWkt(apszOptions);
11051 4 : aosTO.SetNameValue("DST_SRS", osWKT.c_str());
11052 4 : const auto eAxisMappingStrategy = poSRS->GetAxisMappingStrategy();
11053 4 : if (eAxisMappingStrategy == OAMS_TRADITIONAL_GIS_ORDER)
11054 : aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
11055 1 : "TRADITIONAL_GIS_ORDER");
11056 3 : else if (eAxisMappingStrategy == OAMS_AUTHORITY_COMPLIANT)
11057 : aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
11058 1 : "AUTHORITY_COMPLIANT");
11059 : else
11060 : {
11061 2 : const auto &anValues = poSRS->GetDataAxisToSRSAxisMapping();
11062 4 : std::string osVal;
11063 6 : for (int v : anValues)
11064 : {
11065 4 : if (!osVal.empty())
11066 2 : osVal += ',';
11067 4 : osVal += std::to_string(v);
11068 : }
11069 : aosTO.SetNameValue("DST_SRS_DATA_AXIS_TO_SRS_AXIS_MAPPING",
11070 2 : osVal.c_str());
11071 : }
11072 : }
11073 :
11074 15 : auto hTransformer = GDALCreateGenImgProjTransformer2(
11075 : GDALDataset::ToHandle(const_cast<GDALDataset *>(this)), nullptr,
11076 15 : aosTO.List());
11077 15 : if (hTransformer == nullptr)
11078 : {
11079 1 : return CE_Failure;
11080 : }
11081 :
11082 14 : double z = 0;
11083 14 : int bSuccess = 0;
11084 14 : GDALGenImgProjTransform(hTransformer, TRUE, 1, &dfGeolocX, &dfGeolocY, &z,
11085 : &bSuccess);
11086 14 : GDALDestroyTransformer(hTransformer);
11087 14 : if (bSuccess)
11088 : {
11089 14 : if (pdfPixel)
11090 14 : *pdfPixel = dfGeolocX;
11091 14 : if (pdfLine)
11092 14 : *pdfLine = dfGeolocY;
11093 14 : return CE_None;
11094 : }
11095 : else
11096 : {
11097 0 : return CE_Failure;
11098 : }
11099 : }
11100 :
11101 : /************************************************************************/
11102 : /* GDALDatasetGeolocationToPixelLine() */
11103 : /************************************************************************/
11104 :
11105 : /** Transform georeferenced coordinates to pixel/line coordinates.
11106 : *
11107 : * @see GDALDataset::GeolocationToPixelLine()
11108 : * @since GDAL 3.11
11109 : */
11110 :
11111 0 : CPLErr GDALDatasetGeolocationToPixelLine(GDALDatasetH hDS, double dfGeolocX,
11112 : double dfGeolocY,
11113 : OGRSpatialReferenceH hSRS,
11114 : double *pdfPixel, double *pdfLine,
11115 : CSLConstList papszTransformerOptions)
11116 : {
11117 0 : VALIDATE_POINTER1(hDS, "GDALDatasetGeolocationToPixelLine", CE_Failure);
11118 :
11119 0 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
11120 0 : return poDS->GeolocationToPixelLine(
11121 0 : dfGeolocX, dfGeolocY, OGRSpatialReference::FromHandle(hSRS), pdfPixel,
11122 0 : pdfLine, papszTransformerOptions);
11123 : }
11124 :
11125 : /************************************************************************/
11126 : /* GetExtent() */
11127 : /************************************************************************/
11128 :
11129 : /** Return extent of dataset in specified CRS.
11130 : *
11131 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
11132 : *
11133 : * For rasters, the base implementation of this method only succeeds if
11134 : * GetGeoTransform() and GetSpatialRef() succeed.
11135 : * For vectors, the base implementation of this method iterates over layers
11136 : * and call their OGRLayer::GetExtent() method.
11137 : *
11138 : * TestCapability(GDsCFastGetExtent) can be used to test if the execution
11139 : * time of this method is fast.
11140 : *
11141 : * This is the same as C function GDALGetExtent()
11142 : *
11143 : * @param[out] psExtent Pointer to output extent. Must NOT be null.
11144 : * @param poCRS CRS in which to express the extent. If not specified, this will
11145 : * be the raster CRS or the CRS of the first layer for a vector dataset.
11146 : * @return CE_None in case of success, CE_Failure otherwise
11147 : * @since GDAL 3.12
11148 : */
11149 :
11150 121 : CPLErr GDALDataset::GetExtent(OGREnvelope *psExtent,
11151 : const OGRSpatialReference *poCRS) const
11152 : {
11153 121 : const OGRSpatialReference *poThisCRS = GetSpatialRefRasterOnly();
11154 121 : int nLayerCount = 0;
11155 121 : if (!poThisCRS)
11156 : {
11157 93 : nLayerCount = GetLayerCount();
11158 93 : if (nLayerCount >= 1)
11159 : {
11160 3 : if (auto poLayer = GetLayer(0))
11161 3 : poThisCRS = poLayer->GetSpatialRef();
11162 : }
11163 : }
11164 121 : if (!poCRS)
11165 113 : poCRS = poThisCRS;
11166 8 : else if (!poThisCRS)
11167 3 : return CE_Failure;
11168 :
11169 118 : *psExtent = OGREnvelope();
11170 :
11171 118 : GDALGeoTransform gt;
11172 118 : auto poThisDS = const_cast<GDALDataset *>(this);
11173 118 : const bool bHasGT = poThisDS->GetGeoTransform(gt) == CE_None;
11174 118 : if (bHasGT)
11175 : {
11176 0 : std::unique_ptr<OGRCoordinateTransformation> poCT;
11177 113 : if (poCRS)
11178 : {
11179 28 : poCT.reset(OGRCreateCoordinateTransformation(poThisCRS, poCRS));
11180 : }
11181 :
11182 113 : constexpr int DENSIFY_POINT_COUNT = 21;
11183 113 : double dfULX = gt[0];
11184 113 : double dfULY = gt[3];
11185 113 : double dfURX = 0, dfURY = 0;
11186 113 : gt.Apply(nRasterXSize, 0, &dfURX, &dfURY);
11187 113 : double dfLLX = 0, dfLLY = 0;
11188 113 : gt.Apply(0, nRasterYSize, &dfLLX, &dfLLY);
11189 113 : double dfLRX = 0, dfLRY = 0;
11190 113 : gt.Apply(nRasterXSize, nRasterYSize, &dfLRX, &dfLRY);
11191 113 : const double xmin = std::min({dfULX, dfURX, dfLLX, dfLRX});
11192 113 : const double ymin = std::min({dfULY, dfURY, dfLLY, dfLRY});
11193 113 : const double xmax = std::max({dfULX, dfURX, dfLLX, dfLRX});
11194 113 : const double ymax = std::max({dfULY, dfURY, dfLLY, dfLRY});
11195 113 : if (poCT)
11196 : {
11197 28 : OGREnvelope sEnvTmp;
11198 56 : if (!poCT->TransformBounds(xmin, ymin, xmax, ymax, &(sEnvTmp.MinX),
11199 : &(sEnvTmp.MinY), &(sEnvTmp.MaxX),
11200 28 : &(sEnvTmp.MaxY), DENSIFY_POINT_COUNT))
11201 : {
11202 0 : return CE_Failure;
11203 : }
11204 28 : *psExtent = sEnvTmp;
11205 : }
11206 : else
11207 : {
11208 85 : psExtent->MinX = xmin;
11209 85 : psExtent->MinY = ymin;
11210 85 : psExtent->MaxX = xmax;
11211 85 : psExtent->MaxY = ymax;
11212 : }
11213 : }
11214 :
11215 118 : if (nLayerCount > 0)
11216 : {
11217 6 : for (auto &&poLayer : poThisDS->GetLayers())
11218 : {
11219 3 : auto poLayerCRS = poLayer->GetSpatialRef();
11220 3 : if (poLayerCRS)
11221 : {
11222 3 : OGREnvelope sLayerExtent;
11223 3 : if (poLayer->GetExtent(&sLayerExtent) == OGRERR_NONE)
11224 : {
11225 : auto poCT = std::unique_ptr<OGRCoordinateTransformation>(
11226 6 : OGRCreateCoordinateTransformation(poLayerCRS, poCRS));
11227 3 : if (poCT)
11228 : {
11229 3 : constexpr int DENSIFY_POINT_COUNT = 21;
11230 3 : OGREnvelope sEnvTmp;
11231 3 : if (poCT->TransformBounds(
11232 : sLayerExtent.MinX, sLayerExtent.MinY,
11233 : sLayerExtent.MaxX, sLayerExtent.MaxY,
11234 : &(sEnvTmp.MinX), &(sEnvTmp.MinY),
11235 : &(sEnvTmp.MaxX), &(sEnvTmp.MaxY),
11236 3 : DENSIFY_POINT_COUNT))
11237 : {
11238 3 : psExtent->Merge(sEnvTmp);
11239 : }
11240 : }
11241 : }
11242 : }
11243 : }
11244 : }
11245 :
11246 118 : return psExtent->IsInit() ? CE_None : CE_Failure;
11247 : }
11248 :
11249 : /************************************************************************/
11250 : /* GDALGetExtent() */
11251 : /************************************************************************/
11252 :
11253 : /** Return extent of dataset in specified CRS.
11254 : *
11255 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
11256 : *
11257 : * For rasters, the base implementation of this method only succeeds if
11258 : * GetGeoTransform() and GetSpatialRef() succeed.
11259 : * For vectors, the base implementation of this method iterates over layers
11260 : * and call their OGRLayer::GetExtent() method.
11261 : *
11262 : * TestCapability(GDsCFastGetExtent) can be used to test if the execution
11263 : * time of this method is fast.
11264 : *
11265 : * This is the same as C++ method GDALDataset::GetExtent()
11266 : *
11267 : * @param hDS Dataset handle. Must NOT be null.
11268 : * @param[out] psExtent Pointer to output extent. Must NOT be null.
11269 : * @param hCRS CRS in which to express the extent. If not specified, this will
11270 : * be the raster CRS or the CRS of the first layer for a vector dataset.
11271 : * @return extent in poCRS (valid only if IsInit() method returns true)
11272 : * @since GDAL 3.12
11273 : */
11274 :
11275 10 : CPLErr GDALGetExtent(GDALDatasetH hDS, OGREnvelope *psExtent,
11276 : OGRSpatialReferenceH hCRS)
11277 : {
11278 10 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
11279 10 : VALIDATE_POINTER1(psExtent, __func__, CE_Failure);
11280 20 : return GDALDataset::FromHandle(hDS)->GetExtent(
11281 10 : psExtent, OGRSpatialReference::FromHandle(hCRS));
11282 : }
11283 :
11284 : /************************************************************************/
11285 : /* GetExtentWGS84LongLat() */
11286 : /************************************************************************/
11287 :
11288 : /** Return extent of dataset in WGS84 longitude/latitude
11289 : *
11290 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
11291 : *
11292 : * TestCapability(GDsCFastGetExtentWGS84LongLat) can be used to test if the execution
11293 : * time of this method is fast.
11294 : *
11295 : * This is the same as C function GDALGetExtentWGS84LongLat()
11296 : *
11297 : * @return extent (valid only if IsInit() method returns true)
11298 : * @since GDAL 3.12
11299 : */
11300 :
11301 6 : CPLErr GDALDataset::GetExtentWGS84LongLat(OGREnvelope *psExtent) const
11302 : {
11303 12 : OGRSpatialReference oSRS_WGS84;
11304 6 : oSRS_WGS84.SetFromUserInput("WGS84");
11305 6 : oSRS_WGS84.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
11306 12 : return GetExtent(psExtent, &oSRS_WGS84);
11307 : }
11308 :
11309 : /************************************************************************/
11310 : /* GDALGetExtentWGS84LongLat() */
11311 : /************************************************************************/
11312 :
11313 : /** Return extent of dataset in WGS84 longitude/latitude
11314 : *
11315 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
11316 : *
11317 : * TestCapability(GDsCFastGetExtentWGS84LongLat) can be used to test if the execution
11318 : * time of this method is fast.
11319 : *
11320 : * This is the same as C++ method GDALDataset::GetExtentWGS84LongLat()
11321 : *
11322 : * @param hDS Dataset handle. Must NOT be null.
11323 : * @param[out] psExtent Pointer to output extent. Must NOT be null.
11324 : * @return extent (valid only if IsInit() method returns true)
11325 : * @since GDAL 3.12
11326 : */
11327 :
11328 4 : CPLErr GDALGetExtentWGS84LongLat(GDALDatasetH hDS, OGREnvelope *psExtent)
11329 : {
11330 4 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
11331 4 : VALIDATE_POINTER1(psExtent, __func__, CE_Failure);
11332 4 : return GDALDataset::FromHandle(hDS)->GetExtentWGS84LongLat(psExtent);
11333 : }
11334 :
11335 : /************************************************************************/
11336 : /* ReportUpdateNotSupportedByDriver() */
11337 : /************************************************************************/
11338 :
11339 : //! @cond Doxygen_Suppress
11340 :
11341 : /* static */
11342 1 : void GDALDataset::ReportUpdateNotSupportedByDriver(const char *pszDriverName)
11343 : {
11344 1 : CPLError(CE_Failure, CPLE_NotSupported,
11345 : "The %s driver does not support update access to existing "
11346 : "datasets.",
11347 : pszDriverName);
11348 1 : }
11349 :
11350 : //! @endcond
11351 :
11352 : /************************************************************************/
11353 : /* BuildFilename() */
11354 : /************************************************************************/
11355 :
11356 : /** Generates a filename, potentially relative to another one.
11357 : *
11358 : * Given the path to a reference directory, and a path to a file
11359 : * referenced from it, build a path to the file that the current application
11360 : * can use. If the file path is already absolute, rather than relative, or if
11361 : * bRelativeToReferencePath is false, then the filename of interest will be
11362 : * returned unaltered.
11363 : *
11364 : * This is enhanced version of CPLProjectRelativeFilenameSafe() that takes
11365 : * into account the subdataset syntax.
11366 : *
11367 : * Examples:
11368 : * \code{.cpp}
11369 : * BuildFilename("tmp/abc.gif", "abc/def", true) == "abc/def/tmp/abc.gif"
11370 : * BuildFilename("../abc.gif", "/abc/def") == "/abc/abc.gif"
11371 : * BuildFilename("abc.gif", "C:\WIN", true) == "C:\WIN\abc.gif"
11372 : * BuildFilename("abc.gif", "C:\WIN", false) == "abc.gif"
11373 : * BuildFilename("/home/even/foo.tif", "/home/even/workdir", true) == "/home/even/foo.tif"
11374 : * \endcode
11375 : *
11376 : * @param pszFilename Filename of interest.
11377 : * @param pszReferencePath Path to a reference directory.
11378 : * @param bRelativeToReferencePath Whether pszFilename, if a relative path, is
11379 : * relative to pszReferencePath
11380 : * @since 3.11
11381 : */
11382 :
11383 : /* static */
11384 104249 : std::string GDALDataset::BuildFilename(const char *pszFilename,
11385 : const char *pszReferencePath,
11386 : bool bRelativeToReferencePath)
11387 : {
11388 104249 : std::string osSrcDSName;
11389 104249 : if (pszReferencePath != nullptr && bRelativeToReferencePath)
11390 : {
11391 : // Try subdatasetinfo API first
11392 : // Note: this will become the only branch when subdatasetinfo will become
11393 : // available for NITF_IM, RASTERLITE and TILEDB
11394 2584 : const auto oSubDSInfo{GDALGetSubdatasetInfo(pszFilename)};
11395 2584 : if (oSubDSInfo && !oSubDSInfo->GetPathComponent().empty())
11396 : {
11397 8 : auto path{oSubDSInfo->GetPathComponent()};
11398 12 : osSrcDSName = oSubDSInfo->ModifyPathComponent(
11399 8 : CPLProjectRelativeFilenameSafe(pszReferencePath, path.c_str())
11400 4 : .c_str());
11401 4 : GDALDestroySubdatasetInfo(oSubDSInfo);
11402 : }
11403 : else
11404 : {
11405 2580 : bool bDone = false;
11406 15465 : for (const char *pszSyntax : apszSpecialSubDatasetSyntax)
11407 : {
11408 12888 : CPLString osPrefix(pszSyntax);
11409 12888 : osPrefix.resize(strchr(pszSyntax, ':') - pszSyntax + 1);
11410 12888 : if (pszSyntax[osPrefix.size()] == '"')
11411 2577 : osPrefix += '"';
11412 12888 : if (EQUALN(pszFilename, osPrefix, osPrefix.size()))
11413 : {
11414 3 : if (STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}"))
11415 : {
11416 3 : const char *pszLastPart = strrchr(pszFilename, ':') + 1;
11417 : // CSV:z:/foo.xyz
11418 3 : if ((pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
11419 0 : pszLastPart - pszFilename >= 3 &&
11420 0 : pszLastPart[-3] == ':')
11421 : {
11422 0 : pszLastPart -= 2;
11423 : }
11424 3 : CPLString osPrefixFilename = pszFilename;
11425 3 : osPrefixFilename.resize(pszLastPart - pszFilename);
11426 6 : osSrcDSName = osPrefixFilename +
11427 6 : CPLProjectRelativeFilenameSafe(
11428 3 : pszReferencePath, pszLastPart);
11429 3 : bDone = true;
11430 : }
11431 0 : else if (STARTS_WITH_CI(pszSyntax + osPrefix.size(),
11432 : "{FILENAME}"))
11433 : {
11434 0 : CPLString osFilename(pszFilename + osPrefix.size());
11435 0 : size_t nPos = 0;
11436 0 : if (osFilename.size() >= 3 && osFilename[1] == ':' &&
11437 0 : (osFilename[2] == '\\' || osFilename[2] == '/'))
11438 0 : nPos = 2;
11439 0 : nPos = osFilename.find(
11440 0 : pszSyntax[osPrefix.size() + strlen("{FILENAME}")],
11441 : nPos);
11442 0 : if (nPos != std::string::npos)
11443 : {
11444 0 : const CPLString osSuffix = osFilename.substr(nPos);
11445 0 : osFilename.resize(nPos);
11446 0 : osSrcDSName = osPrefix +
11447 0 : CPLProjectRelativeFilenameSafe(
11448 0 : pszReferencePath, osFilename) +
11449 0 : osSuffix;
11450 0 : bDone = true;
11451 : }
11452 : }
11453 3 : break;
11454 : }
11455 : }
11456 2580 : if (!bDone)
11457 : {
11458 2577 : std::string osReferencePath = pszReferencePath;
11459 2577 : if (!CPLIsFilenameRelative(pszReferencePath))
11460 : {
11461 : // Simplify path by replacing "foo/a/../b" with "foo/b"
11462 2288 : while (STARTS_WITH(pszFilename, "../"))
11463 : {
11464 : osReferencePath =
11465 5 : CPLGetPathSafe(osReferencePath.c_str());
11466 5 : pszFilename += strlen("../");
11467 : }
11468 : }
11469 :
11470 5154 : osSrcDSName = CPLProjectRelativeFilenameSafe(
11471 2577 : osReferencePath.c_str(), pszFilename);
11472 : }
11473 2584 : }
11474 : }
11475 : else
11476 : {
11477 101665 : osSrcDSName = pszFilename;
11478 : }
11479 104249 : return osSrcDSName;
11480 : }
11481 :
11482 : /************************************************************************/
11483 : /* GDALMDArrayFromDataset */
11484 : /************************************************************************/
11485 :
11486 : class GDALMDArrayFromDataset final : public GDALMDArray
11487 : {
11488 : CPL_DISALLOW_COPY_ASSIGN(GDALMDArrayFromDataset)
11489 :
11490 : GDALDataset *const m_poDS;
11491 : const GDALExtendedDataType m_dt;
11492 : std::vector<std::shared_ptr<GDALDimension>> m_dims{};
11493 : std::string m_osUnit{};
11494 : std::vector<GByte> m_abyNoData{};
11495 : std::shared_ptr<GDALMDArray> m_varX{};
11496 : std::shared_ptr<GDALMDArray> m_varY{};
11497 : std::shared_ptr<GDALMDArray> m_varBand{};
11498 : const std::string m_osFilename;
11499 : int m_iBandDim = 0;
11500 : int m_iYDim = 1;
11501 : int m_iXDim = 2;
11502 :
11503 : bool ReadWrite(GDALRWFlag eRWFlag, const GUInt64 *arrayStartIdx,
11504 : const size_t *count, const GInt64 *arrayStep,
11505 : const GPtrDiff_t *bufferStride,
11506 : const GDALExtendedDataType &bufferDataType,
11507 : void *pBuffer) const;
11508 :
11509 : protected:
11510 15 : GDALMDArrayFromDataset(GDALDataset *poDS, CSLConstList papszOptions)
11511 30 : : GDALAbstractMDArray(std::string(),
11512 30 : std::string(poDS->GetDescription())),
11513 30 : GDALMDArray(std::string(), std::string(poDS->GetDescription())),
11514 : m_poDS(poDS), m_dt(GDALExtendedDataType::Create(
11515 : poDS->GetRasterBand(1)->GetRasterDataType())),
11516 75 : m_osFilename(poDS->GetDescription())
11517 : {
11518 15 : m_poDS->Reference();
11519 :
11520 15 : const int nBandCount = poDS->GetRasterCount();
11521 43 : for (int i = 1; i <= nBandCount; ++i)
11522 : {
11523 28 : const auto poBand = poDS->GetRasterBand(i);
11524 28 : if (i == 1)
11525 15 : m_osUnit = poBand->GetUnitType();
11526 13 : else if (m_osUnit != poBand->GetUnitType())
11527 7 : m_osUnit.clear();
11528 :
11529 56 : std::vector<GByte> abyNoData;
11530 28 : int bHasNoData = false;
11531 28 : switch (poBand->GetRasterDataType())
11532 : {
11533 0 : case GDT_Int64:
11534 : {
11535 : const auto nNoData =
11536 0 : poBand->GetNoDataValueAsInt64(&bHasNoData);
11537 0 : if (bHasNoData)
11538 : {
11539 0 : abyNoData.resize(m_dt.GetSize());
11540 0 : GDALCopyWords64(&nNoData, GDT_Int64, 0, &abyNoData[0],
11541 : m_dt.GetNumericDataType(), 0, 1);
11542 : }
11543 0 : break;
11544 : }
11545 :
11546 0 : case GDT_UInt64:
11547 : {
11548 : const auto nNoData =
11549 0 : poBand->GetNoDataValueAsUInt64(&bHasNoData);
11550 0 : if (bHasNoData)
11551 : {
11552 0 : abyNoData.resize(m_dt.GetSize());
11553 0 : GDALCopyWords64(&nNoData, GDT_UInt64, 0, &abyNoData[0],
11554 : m_dt.GetNumericDataType(), 0, 1);
11555 : }
11556 0 : break;
11557 : }
11558 :
11559 28 : default:
11560 : {
11561 28 : const auto dfNoData = poBand->GetNoDataValue(&bHasNoData);
11562 28 : if (bHasNoData)
11563 : {
11564 11 : abyNoData.resize(m_dt.GetSize());
11565 22 : GDALCopyWords64(&dfNoData, GDT_Float64, 0,
11566 11 : &abyNoData[0],
11567 : m_dt.GetNumericDataType(), 0, 1);
11568 : }
11569 28 : break;
11570 : }
11571 : }
11572 :
11573 28 : if (i == 1)
11574 15 : m_abyNoData = std::move(abyNoData);
11575 13 : else if (m_abyNoData != abyNoData)
11576 7 : m_abyNoData.clear();
11577 : }
11578 :
11579 15 : const int nXSize = poDS->GetRasterXSize();
11580 15 : const int nYSize = poDS->GetRasterYSize();
11581 :
11582 15 : auto poSRS = poDS->GetSpatialRef();
11583 30 : std::string osTypeY;
11584 30 : std::string osTypeX;
11585 30 : std::string osDirectionY;
11586 30 : std::string osDirectionX;
11587 15 : if (poSRS && poSRS->GetAxesCount() == 2)
11588 : {
11589 8 : const auto &mapping = poSRS->GetDataAxisToSRSAxisMapping();
11590 8 : OGRAxisOrientation eOrientation1 = OAO_Other;
11591 8 : poSRS->GetAxis(nullptr, 0, &eOrientation1);
11592 8 : OGRAxisOrientation eOrientation2 = OAO_Other;
11593 8 : poSRS->GetAxis(nullptr, 1, &eOrientation2);
11594 8 : if (eOrientation1 == OAO_East && eOrientation2 == OAO_North)
11595 : {
11596 6 : if (mapping == std::vector<int>{1, 2})
11597 : {
11598 6 : osTypeY = GDAL_DIM_TYPE_HORIZONTAL_Y;
11599 6 : osDirectionY = "NORTH";
11600 6 : osTypeX = GDAL_DIM_TYPE_HORIZONTAL_X;
11601 6 : osDirectionX = "EAST";
11602 : }
11603 : }
11604 2 : else if (eOrientation1 == OAO_North && eOrientation2 == OAO_East)
11605 : {
11606 2 : if (mapping == std::vector<int>{2, 1})
11607 : {
11608 2 : osTypeY = GDAL_DIM_TYPE_HORIZONTAL_Y;
11609 2 : osDirectionY = "NORTH";
11610 2 : osTypeX = GDAL_DIM_TYPE_HORIZONTAL_X;
11611 2 : osDirectionX = "EAST";
11612 : }
11613 : }
11614 : }
11615 :
11616 41 : const bool bBandYX = [papszOptions, poDS, nBandCount]()
11617 : {
11618 : const char *pszDimOrder =
11619 15 : CSLFetchNameValueDef(papszOptions, "DIM_ORDER", "AUTO");
11620 15 : if (EQUAL(pszDimOrder, "AUTO"))
11621 : {
11622 : const char *pszInterleave =
11623 13 : poDS->GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE");
11624 22 : return nBandCount == 1 || !pszInterleave ||
11625 22 : !EQUAL(pszInterleave, "PIXEL");
11626 : }
11627 : else
11628 : {
11629 2 : return EQUAL(pszDimOrder, "BAND,Y,X");
11630 : }
11631 15 : }();
11632 : const char *const pszBandDimName =
11633 15 : CSLFetchNameValueDef(papszOptions, "BAND_DIM_NAME", "Band");
11634 : auto poBandDim = std::make_shared<GDALDimensionWeakIndexingVar>(
11635 45 : "/", pszBandDimName, std::string(), std::string(), nBandCount);
11636 : const char *const pszYDimName =
11637 15 : CSLFetchNameValueDef(papszOptions, "Y_DIM_NAME", "Y");
11638 : auto poYDim = std::make_shared<GDALDimensionWeakIndexingVar>(
11639 30 : "/", pszYDimName, osTypeY, osDirectionY, nYSize);
11640 : const char *const pszXDimName =
11641 15 : CSLFetchNameValueDef(papszOptions, "X_DIM_NAME", "X");
11642 : auto poXDim = std::make_shared<GDALDimensionWeakIndexingVar>(
11643 30 : "/", pszXDimName, osTypeX, osDirectionX, nXSize);
11644 :
11645 15 : const char *const pszBandIndexingVarItem = CSLFetchNameValueDef(
11646 : papszOptions, "BAND_INDEXING_VAR_ITEM", "{Description}");
11647 15 : if (EQUAL(pszBandIndexingVarItem, "{Description}"))
11648 : {
11649 : const auto oIndexingVarType =
11650 18 : GDALExtendedDataType::CreateString(strlen("Band 65535"));
11651 9 : auto poBandVar = MEMMDArray::Create("/", poBandDim->GetName(),
11652 36 : {poBandDim}, oIndexingVarType);
11653 9 : CPL_IGNORE_RET_VAL(poBandVar->Init());
11654 25 : for (int i = 0; i < nBandCount; ++i)
11655 : {
11656 : const char *pszDesc =
11657 16 : poDS->GetRasterBand(i + 1)->GetDescription();
11658 : const std::string osBandName =
11659 32 : pszDesc[0] ? pszDesc : CPLSPrintf("Band %d", i + 1);
11660 16 : const char *pszBandName = osBandName.c_str();
11661 16 : const char *const apszBandVal[] = {pszBandName};
11662 16 : const GUInt64 anStartIdx[] = {static_cast<GUInt64>(i)};
11663 16 : const size_t anCount[] = {1};
11664 16 : const GInt64 arrayStep[] = {1};
11665 16 : const GPtrDiff_t anBufferStride[] = {1};
11666 16 : poBandVar->Write(anStartIdx, anCount, arrayStep, anBufferStride,
11667 : oIndexingVarType, apszBandVal);
11668 : }
11669 9 : m_varBand = std::move(poBandVar);
11670 9 : poBandDim->SetIndexingVariable(m_varBand);
11671 : }
11672 6 : else if (EQUAL(pszBandIndexingVarItem, "{Index}"))
11673 : {
11674 : const auto oIndexingVarType =
11675 2 : GDALExtendedDataType::Create(GDT_Int32);
11676 1 : auto poBandVar = MEMMDArray::Create("/", poBandDim->GetName(),
11677 4 : {poBandDim}, oIndexingVarType);
11678 1 : CPL_IGNORE_RET_VAL(poBandVar->Init());
11679 3 : for (int i = 0; i < nBandCount; ++i)
11680 : {
11681 2 : const int anBandIdx[] = {i + 1};
11682 2 : const GUInt64 anStartIdx[] = {static_cast<GUInt64>(i)};
11683 2 : const size_t anCount[] = {1};
11684 2 : const GInt64 arrayStep[] = {1};
11685 2 : const GPtrDiff_t anBufferStride[] = {1};
11686 2 : poBandVar->Write(anStartIdx, anCount, arrayStep, anBufferStride,
11687 : oIndexingVarType, anBandIdx);
11688 : }
11689 1 : m_varBand = std::move(poBandVar);
11690 1 : poBandDim->SetIndexingVariable(m_varBand);
11691 : }
11692 5 : else if (EQUAL(pszBandIndexingVarItem, "{ColorInterpretation}"))
11693 : {
11694 1 : size_t nMaxLen = 0;
11695 3 : for (int i = 0; i < nBandCount; ++i)
11696 : {
11697 2 : const char *pszDesc = GDALGetColorInterpretationName(
11698 2 : poDS->GetRasterBand(i + 1)->GetColorInterpretation());
11699 2 : nMaxLen = std::max(nMaxLen, strlen(pszDesc));
11700 : }
11701 : const auto oIndexingVarType =
11702 2 : GDALExtendedDataType::CreateString(nMaxLen);
11703 1 : auto poBandVar = MEMMDArray::Create("/", poBandDim->GetName(),
11704 4 : {poBandDim}, oIndexingVarType);
11705 1 : CPL_IGNORE_RET_VAL(poBandVar->Init());
11706 3 : for (int i = 0; i < nBandCount; ++i)
11707 : {
11708 2 : const char *pszDesc = GDALGetColorInterpretationName(
11709 2 : poDS->GetRasterBand(i + 1)->GetColorInterpretation());
11710 2 : const char *const apszBandVal[] = {pszDesc};
11711 2 : const GUInt64 anStartIdx[] = {static_cast<GUInt64>(i)};
11712 2 : const size_t anCount[] = {1};
11713 2 : const GInt64 arrayStep[] = {1};
11714 2 : const GPtrDiff_t anBufferStride[] = {1};
11715 2 : poBandVar->Write(anStartIdx, anCount, arrayStep, anBufferStride,
11716 : oIndexingVarType, apszBandVal);
11717 : }
11718 1 : m_varBand = std::move(poBandVar);
11719 1 : poBandDim->SetIndexingVariable(m_varBand);
11720 : }
11721 4 : else if (!EQUAL(pszBandIndexingVarItem, "{None}"))
11722 : {
11723 3 : const char *const pszBandIndexingVarType = CSLFetchNameValueDef(
11724 : papszOptions, "BAND_INDEXING_VAR_TYPE", "String");
11725 3 : size_t nMaxLen = 0;
11726 3 : if (EQUAL(pszBandIndexingVarType, "String"))
11727 : {
11728 3 : for (int i = 0; i < nBandCount; ++i)
11729 : {
11730 : const char *pszVal =
11731 2 : poDS->GetRasterBand(i + 1)->GetMetadataItem(
11732 2 : pszBandIndexingVarItem);
11733 2 : if (pszVal)
11734 1 : nMaxLen = std::max(nMaxLen, strlen(pszVal));
11735 : }
11736 : }
11737 : const auto oIndexingVarType =
11738 3 : EQUAL(pszBandIndexingVarType, "String")
11739 : ? GDALExtendedDataType::CreateString(nMaxLen)
11740 2 : : EQUAL(pszBandIndexingVarType, "Integer")
11741 : ? GDALExtendedDataType::Create(GDT_Int32)
11742 6 : : GDALExtendedDataType::Create(GDT_Float64);
11743 3 : auto poBandVar = MEMMDArray::Create("/", poBandDim->GetName(),
11744 12 : {poBandDim}, oIndexingVarType);
11745 3 : CPL_IGNORE_RET_VAL(poBandVar->Init());
11746 9 : for (int i = 0; i < nBandCount; ++i)
11747 : {
11748 6 : const GUInt64 anStartIdx[] = {static_cast<GUInt64>(i)};
11749 6 : const size_t anCount[] = {1};
11750 6 : const GInt64 arrayStep[] = {1};
11751 6 : const GPtrDiff_t anBufferStride[] = {1};
11752 : const char *pszVal =
11753 6 : poDS->GetRasterBand(i + 1)->GetMetadataItem(
11754 6 : pszBandIndexingVarItem);
11755 6 : if (oIndexingVarType.GetClass() == GEDTC_STRING)
11756 : {
11757 2 : const char *const apszBandVal[] = {pszVal ? pszVal : ""};
11758 2 : poBandVar->Write(anStartIdx, anCount, arrayStep,
11759 : anBufferStride, oIndexingVarType,
11760 : apszBandVal);
11761 : }
11762 4 : else if (oIndexingVarType.GetNumericDataType() == GDT_Int32)
11763 : {
11764 2 : const int anVal[] = {pszVal ? atoi(pszVal) : 0};
11765 2 : poBandVar->Write(anStartIdx, anCount, arrayStep,
11766 : anBufferStride, oIndexingVarType, anVal);
11767 : }
11768 : else
11769 : {
11770 2 : const double adfVal[] = {pszVal ? CPLAtof(pszVal) : 0.0};
11771 2 : poBandVar->Write(anStartIdx, anCount, arrayStep,
11772 : anBufferStride, oIndexingVarType, adfVal);
11773 : }
11774 : }
11775 3 : m_varBand = std::move(poBandVar);
11776 3 : poBandDim->SetIndexingVariable(m_varBand);
11777 : }
11778 :
11779 15 : GDALGeoTransform gt;
11780 15 : if (m_poDS->GetGeoTransform(gt) == CE_None && gt[2] == 0 && gt[4] == 0)
11781 : {
11782 24 : m_varX = GDALMDArrayRegularlySpaced::Create(
11783 24 : "/", poBandDim->GetName(), poXDim, gt[0], gt[1], 0.5);
11784 8 : poXDim->SetIndexingVariable(m_varX);
11785 :
11786 24 : m_varY = GDALMDArrayRegularlySpaced::Create(
11787 24 : "/", poYDim->GetName(), poYDim, gt[3], gt[5], 0.5);
11788 8 : poYDim->SetIndexingVariable(m_varY);
11789 : }
11790 15 : if (bBandYX)
11791 : {
11792 84 : m_dims = {std::move(poBandDim), std::move(poYDim),
11793 70 : std::move(poXDim)};
11794 : }
11795 : else
11796 : {
11797 1 : m_iYDim = 0;
11798 1 : m_iXDim = 1;
11799 1 : m_iBandDim = 2;
11800 6 : m_dims = {std::move(poYDim), std::move(poXDim),
11801 5 : std::move(poBandDim)};
11802 : }
11803 15 : }
11804 :
11805 : bool IRead(const GUInt64 *arrayStartIdx, const size_t *count,
11806 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
11807 : const GDALExtendedDataType &bufferDataType,
11808 : void *pDstBuffer) const override;
11809 :
11810 1 : bool IWrite(const GUInt64 *arrayStartIdx, const size_t *count,
11811 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
11812 : const GDALExtendedDataType &bufferDataType,
11813 : const void *pSrcBuffer) override
11814 : {
11815 1 : return ReadWrite(GF_Write, arrayStartIdx, count, arrayStep,
11816 : bufferStride, bufferDataType,
11817 1 : const_cast<void *>(pSrcBuffer));
11818 : }
11819 :
11820 : public:
11821 30 : ~GDALMDArrayFromDataset() override
11822 15 : {
11823 15 : m_poDS->ReleaseRef();
11824 30 : }
11825 :
11826 15 : static std::shared_ptr<GDALMDArray> Create(GDALDataset *poDS,
11827 : CSLConstList papszOptions)
11828 : {
11829 : auto array(std::shared_ptr<GDALMDArrayFromDataset>(
11830 30 : new GDALMDArrayFromDataset(poDS, papszOptions)));
11831 15 : array->SetSelf(array);
11832 30 : return array;
11833 : }
11834 :
11835 2 : bool IsWritable() const override
11836 : {
11837 2 : return m_poDS->GetAccess() == GA_Update;
11838 : }
11839 :
11840 16 : const std::string &GetFilename() const override
11841 : {
11842 16 : return m_osFilename;
11843 : }
11844 :
11845 : const std::vector<std::shared_ptr<GDALDimension>> &
11846 99 : GetDimensions() const override
11847 : {
11848 99 : return m_dims;
11849 : }
11850 :
11851 38 : const GDALExtendedDataType &GetDataType() const override
11852 : {
11853 38 : return m_dt;
11854 : }
11855 :
11856 5 : const std::string &GetUnit() const override
11857 : {
11858 5 : return m_osUnit;
11859 : }
11860 :
11861 5 : const void *GetRawNoDataValue() const override
11862 : {
11863 5 : return m_abyNoData.empty() ? nullptr : m_abyNoData.data();
11864 : }
11865 :
11866 5 : double GetOffset(bool *pbHasOffset,
11867 : GDALDataType *peStorageType) const override
11868 : {
11869 5 : double dfRes = 0;
11870 5 : int bHasOffset = false;
11871 5 : auto poFirstBand = m_poDS->GetRasterBand(1);
11872 5 : if (poFirstBand) // to avoid -Wnull-dereference
11873 : {
11874 5 : dfRes = poFirstBand->GetOffset(&bHasOffset);
11875 7 : for (int i = 2; bHasOffset && i <= m_poDS->GetRasterCount(); ++i)
11876 : {
11877 : const double dfOtherRes =
11878 2 : m_poDS->GetRasterBand(i)->GetOffset(&bHasOffset);
11879 2 : bHasOffset = bHasOffset && (dfOtherRes == dfRes);
11880 : }
11881 : }
11882 5 : if (pbHasOffset)
11883 5 : *pbHasOffset = CPL_TO_BOOL(bHasOffset);
11884 5 : if (peStorageType)
11885 3 : *peStorageType = GDT_Unknown;
11886 5 : return dfRes;
11887 : }
11888 :
11889 5 : double GetScale(bool *pbHasScale,
11890 : GDALDataType *peStorageType) const override
11891 : {
11892 5 : double dfRes = 0;
11893 5 : int bHasScale = false;
11894 5 : auto poFirstBand = m_poDS->GetRasterBand(1);
11895 5 : if (poFirstBand) // to avoid -Wnull-dereference
11896 : {
11897 5 : dfRes = poFirstBand->GetScale(&bHasScale);
11898 7 : for (int i = 2; bHasScale && i <= m_poDS->GetRasterCount(); ++i)
11899 : {
11900 : const double dfOtherRes =
11901 2 : m_poDS->GetRasterBand(i)->GetScale(&bHasScale);
11902 2 : bHasScale = bHasScale && (dfOtherRes == dfRes);
11903 : }
11904 : }
11905 5 : if (pbHasScale)
11906 5 : *pbHasScale = CPL_TO_BOOL(bHasScale);
11907 5 : if (peStorageType)
11908 3 : *peStorageType = GDT_Unknown;
11909 5 : return dfRes;
11910 : }
11911 :
11912 9 : std::shared_ptr<OGRSpatialReference> GetSpatialRef() const override
11913 : {
11914 9 : auto poSrcSRS = m_poDS->GetSpatialRef();
11915 9 : if (!poSrcSRS)
11916 1 : return nullptr;
11917 16 : auto poSRS = std::shared_ptr<OGRSpatialReference>(poSrcSRS->Clone());
11918 :
11919 16 : auto axisMapping = poSRS->GetDataAxisToSRSAxisMapping();
11920 24 : for (auto &m : axisMapping)
11921 : {
11922 16 : if (m == 1)
11923 8 : m = m_iXDim + 1;
11924 8 : else if (m == 2)
11925 8 : m = m_iYDim + 1;
11926 : else
11927 0 : m = 0;
11928 : }
11929 8 : poSRS->SetDataAxisToSRSAxisMapping(axisMapping);
11930 8 : return poSRS;
11931 : }
11932 :
11933 7 : std::vector<GUInt64> GetBlockSize() const override
11934 : {
11935 7 : int nBlockXSize = 0;
11936 7 : int nBlockYSize = 0;
11937 7 : m_poDS->GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
11938 7 : if (m_iBandDim == 0)
11939 : {
11940 6 : return std::vector<GUInt64>{1, static_cast<GUInt64>(nBlockYSize),
11941 6 : static_cast<GUInt64>(nBlockXSize)};
11942 : }
11943 : else
11944 : {
11945 1 : return std::vector<GUInt64>{static_cast<GUInt64>(nBlockYSize),
11946 1 : static_cast<GUInt64>(nBlockXSize), 1};
11947 : }
11948 : }
11949 :
11950 : std::vector<std::shared_ptr<GDALAttribute>>
11951 7 : GetAttributes(CSLConstList) const override
11952 : {
11953 7 : std::vector<std::shared_ptr<GDALAttribute>> res;
11954 7 : auto papszMD = m_poDS->GetMetadata();
11955 14 : for (auto iter = papszMD; iter && iter[0]; ++iter)
11956 : {
11957 7 : char *pszKey = nullptr;
11958 7 : const char *pszValue = CPLParseNameValue(*iter, &pszKey);
11959 7 : if (pszKey && pszValue)
11960 : {
11961 : res.emplace_back(
11962 7 : std::make_shared<GDALMDIAsAttribute>(pszKey, pszValue));
11963 : }
11964 7 : CPLFree(pszKey);
11965 : }
11966 7 : return res;
11967 : }
11968 : };
11969 :
11970 10 : bool GDALMDArrayFromDataset::IRead(const GUInt64 *arrayStartIdx,
11971 : const size_t *count, const GInt64 *arrayStep,
11972 : const GPtrDiff_t *bufferStride,
11973 : const GDALExtendedDataType &bufferDataType,
11974 : void *pDstBuffer) const
11975 : {
11976 10 : return ReadWrite(GF_Read, arrayStartIdx, count, arrayStep, bufferStride,
11977 10 : bufferDataType, pDstBuffer);
11978 : }
11979 :
11980 : /************************************************************************/
11981 : /* ReadWrite() */
11982 : /************************************************************************/
11983 :
11984 11 : bool GDALMDArrayFromDataset::ReadWrite(
11985 : GDALRWFlag eRWFlag, const GUInt64 *arrayStartIdx, const size_t *count,
11986 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
11987 : const GDALExtendedDataType &bufferDataType, void *pBuffer) const
11988 : {
11989 11 : const auto eDT(bufferDataType.GetNumericDataType());
11990 11 : const auto nDTSize(GDALGetDataTypeSizeBytes(eDT));
11991 11 : const int nX =
11992 11 : arrayStep[m_iXDim] > 0
11993 11 : ? static_cast<int>(arrayStartIdx[m_iXDim])
11994 0 : : static_cast<int>(arrayStartIdx[m_iXDim] -
11995 0 : (count[m_iXDim] - 1) * -arrayStep[m_iXDim]);
11996 11 : const int nY =
11997 11 : arrayStep[m_iYDim] > 0
11998 11 : ? static_cast<int>(arrayStartIdx[m_iYDim])
11999 1 : : static_cast<int>(arrayStartIdx[m_iYDim] -
12000 1 : (count[m_iYDim] - 1) * -arrayStep[m_iYDim]);
12001 11 : const int nSizeX =
12002 11 : static_cast<int>(count[m_iXDim] * ABS(arrayStep[m_iXDim]));
12003 11 : const int nSizeY =
12004 11 : static_cast<int>(count[m_iYDim] * ABS(arrayStep[m_iYDim]));
12005 11 : GByte *pabyBuffer = static_cast<GByte *>(pBuffer);
12006 11 : int nStrideXSign = 1;
12007 11 : if (arrayStep[m_iXDim] < 0)
12008 : {
12009 0 : pabyBuffer += (count[m_iXDim] - 1) * bufferStride[m_iXDim] * nDTSize;
12010 0 : nStrideXSign = -1;
12011 : }
12012 11 : int nStrideYSign = 1;
12013 11 : if (arrayStep[m_iYDim] < 0)
12014 : {
12015 1 : pabyBuffer += (count[m_iYDim] - 1) * bufferStride[m_iYDim] * nDTSize;
12016 1 : nStrideYSign = -1;
12017 : }
12018 11 : const GSpacing nPixelSpace =
12019 11 : static_cast<GSpacing>(nStrideXSign * bufferStride[m_iXDim] * nDTSize);
12020 11 : const GSpacing nLineSpace =
12021 11 : static_cast<GSpacing>(nStrideYSign * bufferStride[m_iYDim] * nDTSize);
12022 11 : const GSpacing nBandSpace =
12023 11 : static_cast<GSpacing>(bufferStride[m_iBandDim] * nDTSize);
12024 11 : std::vector<int> anBandList;
12025 28 : for (int i = 0; i < static_cast<int>(count[m_iBandDim]); ++i)
12026 17 : anBandList.push_back(1 + static_cast<int>(arrayStartIdx[m_iBandDim]) +
12027 17 : i * static_cast<int>(arrayStep[m_iBandDim]));
12028 :
12029 33 : return m_poDS->RasterIO(eRWFlag, nX, nY, nSizeX, nSizeY, pabyBuffer,
12030 11 : static_cast<int>(count[m_iXDim]),
12031 11 : static_cast<int>(count[m_iYDim]), eDT,
12032 11 : static_cast<int>(count[m_iBandDim]),
12033 11 : anBandList.data(), nPixelSpace, nLineSpace,
12034 22 : nBandSpace, nullptr) == CE_None;
12035 : }
12036 :
12037 : /************************************************************************/
12038 : /* AsMDArray() */
12039 : /************************************************************************/
12040 :
12041 : /** Return a view of this dataset as a 3D multidimensional GDALMDArray.
12042 : *
12043 : * If this dataset is not already marked as shared, it will be, so that the
12044 : * returned array holds a reference to it.
12045 : *
12046 : * If the dataset has a geotransform attached, the X and Y dimensions of the
12047 : * returned array will have an associated indexing variable.
12048 : *
12049 : * The currently supported list of options is:
12050 : * <ul>
12051 : * <li>DIM_ORDER=<order> where order can be "AUTO", "Band,Y,X" or "Y,X,Band".
12052 : * "Band,Y,X" means that the first (slowest changing) dimension is Band
12053 : * and the last (fastest changing direction) is X
12054 : * "Y,X,Band" means that the first (slowest changing) dimension is Y
12055 : * and the last (fastest changing direction) is Band.
12056 : * "AUTO" (the default) selects "Band,Y,X" for single band datasets, or takes
12057 : * into account the INTERLEAVE metadata item in the IMAGE_STRUCTURE domain.
12058 : * If it equals BAND, then "Band,Y,X" is used. Otherwise (if it equals PIXEL),
12059 : * "Y,X,Band" is use.
12060 : * </li>
12061 : * <li>BAND_INDEXING_VAR_ITEM={Description}|{None}|{Index}|{ColorInterpretation}|<BandMetadataItem>:
12062 : * item from which to build the band indexing variable.
12063 : * <ul>
12064 : * <li>"{Description}", the default, means to use the band description (or "Band index" if empty).</li>
12065 : * <li>"{None}" means that no band indexing variable must be created.</li>
12066 : * <li>"{Index}" means that the band index (starting at one) is used.</li>
12067 : * <li>"{ColorInterpretation}" means that the band color interpretation is used (i.e. "Red", "Green", "Blue").</li>
12068 : * <li><BandMetadataItem> is the name of a band metadata item to use.</li>
12069 : * </ul>
12070 : * </li>
12071 : * <li>BAND_INDEXING_VAR_TYPE=String|Real|Integer: the data type of the band
12072 : * indexing variable, when BAND_INDEXING_VAR_ITEM corresponds to a band metadata item.
12073 : * Defaults to String.
12074 : * </li>
12075 : * <li>BAND_DIM_NAME=<string>: Name of the band dimension.
12076 : * Defaults to "Band".
12077 : * </li>
12078 : * <li>X_DIM_NAME=<string>: Name of the X dimension. Defaults to "X".
12079 : * </li>
12080 : * <li>Y_DIM_NAME=<string>: Name of the Y dimension. Defaults to "Y".
12081 : * </li>
12082 : * </ul>
12083 : *
12084 : * This is the same as the C function GDALDatasetAsMDArray().
12085 : *
12086 : * The "reverse" method is GDALMDArray::AsClassicDataset().
12087 : *
12088 : * @param papszOptions Null-terminated list of strings, or nullptr.
12089 : * @return a new array, or nullptr.
12090 : *
12091 : * @since GDAL 3.12
12092 : */
12093 18 : std::shared_ptr<GDALMDArray> GDALDataset::AsMDArray(CSLConstList papszOptions)
12094 : {
12095 18 : if (!GetShared())
12096 : {
12097 17 : MarkAsShared();
12098 : }
12099 18 : if (nBands == 0 || nRasterXSize == 0 || nRasterYSize == 0)
12100 : {
12101 1 : ReportError(
12102 : CE_Failure, CPLE_AppDefined,
12103 : "Degenerated array (band, Y and/or X dimension of size zero)");
12104 1 : return nullptr;
12105 : }
12106 17 : const GDALDataType eDT = papoBands[0]->GetRasterDataType();
12107 30 : for (int i = 1; i < nBands; ++i)
12108 : {
12109 14 : if (eDT != papoBands[i]->GetRasterDataType())
12110 : {
12111 1 : ReportError(CE_Failure, CPLE_AppDefined,
12112 : "Non-uniform data type amongst bands");
12113 1 : return nullptr;
12114 : }
12115 : }
12116 : const char *pszDimOrder =
12117 16 : CSLFetchNameValueDef(papszOptions, "DIM_ORDER", "AUTO");
12118 16 : if (!EQUAL(pszDimOrder, "AUTO") && !EQUAL(pszDimOrder, "Band,Y,X") &&
12119 2 : !EQUAL(pszDimOrder, "Y,X,Band"))
12120 : {
12121 1 : ReportError(CE_Failure, CPLE_IllegalArg,
12122 : "Illegal value for DIM_ORDER option");
12123 1 : return nullptr;
12124 : }
12125 15 : return GDALMDArrayFromDataset::Create(this, papszOptions);
12126 : }
|