Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Core
4 : * Purpose: Base class for raster file formats.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 1998, 2003, Frank Warmerdam
9 : * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_port.h"
15 : #include "gdal.h"
16 : #include "gdal_priv.h"
17 :
18 : #include <array>
19 : #include <climits>
20 : #include <cstdarg>
21 : #include <cstdio>
22 : #include <cstdlib>
23 : #include <cstring>
24 : #include <algorithm>
25 : #include <map>
26 : #include <mutex>
27 : #include <new>
28 : #include <set>
29 : #include <string>
30 : #include <utility>
31 :
32 : #include "cpl_conv.h"
33 : #include "cpl_error.h"
34 : #include "cpl_hash_set.h"
35 : #include "cpl_multiproc.h"
36 : #include "cpl_progress.h"
37 : #include "cpl_string.h"
38 : #include "cpl_vsi.h"
39 : #include "cpl_vsi_error.h"
40 : #include "gdal_alg.h"
41 : #include "ogr_api.h"
42 : #include "ogr_attrind.h"
43 : #include "ogr_core.h"
44 : #include "ogr_feature.h"
45 : #include "ogr_featurestyle.h"
46 : #include "ogr_gensql.h"
47 : #include "ogr_geometry.h"
48 : #include "ogr_p.h"
49 : #include "ogr_spatialref.h"
50 : #include "ogr_srs_api.h"
51 : #include "ograpispy.h"
52 : #include "ogrsf_frmts.h"
53 : #include "ogrunionlayer.h"
54 : #include "ogr_swq.h"
55 :
56 : #include "../frmts/derived/derivedlist.h"
57 :
58 : #ifdef SQLITE_ENABLED
59 : #include "../sqlite/ogrsqliteexecutesql.h"
60 : #endif
61 :
62 : extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
63 :
64 : CPL_C_START
65 : GDALAsyncReader *GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff,
66 : int nYOff, int nXSize, int nYSize,
67 : void *pBuf, int nBufXSize,
68 : int nBufYSize, GDALDataType eBufType,
69 : int nBandCount, int *panBandMap,
70 : int nPixelSpace, int nLineSpace,
71 : int nBandSpace, char **papszOptions);
72 : CPL_C_END
73 :
74 : enum class GDALAllowReadWriteMutexState
75 : {
76 : RW_MUTEX_STATE_UNKNOWN,
77 : RW_MUTEX_STATE_ALLOWED,
78 : RW_MUTEX_STATE_DISABLED
79 : };
80 :
81 : const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
82 : const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
83 :
84 : class GDALDataset::Private
85 : {
86 : CPL_DISALLOW_COPY_ASSIGN(Private)
87 :
88 : public:
89 : CPLMutex *hMutex = nullptr;
90 : std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
91 : #ifdef DEBUG_EXTRA
92 : std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
93 : #endif
94 : GDALAllowReadWriteMutexState eStateReadWriteMutex =
95 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
96 : int nCurrentLayerIdx = 0;
97 : int nLayerCount = -1;
98 : GIntBig nFeatureReadInLayer = 0;
99 : GIntBig nFeatureReadInDataset = 0;
100 : GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
101 : GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
102 : OGRLayer *poCurrentLayer = nullptr;
103 :
104 : std::mutex m_oMutexWKT{};
105 :
106 : char *m_pszWKTCached = nullptr;
107 : OGRSpatialReference *m_poSRSCached = nullptr;
108 : char *m_pszWKTGCPCached = nullptr;
109 : OGRSpatialReference *m_poSRSGCPCached = nullptr;
110 :
111 : GDALDataset *poParentDataset = nullptr;
112 :
113 : bool m_bOverviewsEnabled = true;
114 :
115 : std::vector<int>
116 : m_anBandMap{}; // used by RasterIO(). Values are 1, 2, etc.
117 :
118 147839 : Private() = default;
119 : };
120 :
121 : struct SharedDatasetCtxt
122 : {
123 : // PID of the thread that mark the dataset as shared
124 : // This may not be the actual PID, but the responsiblePID.
125 : GIntBig nPID;
126 : char *pszDescription;
127 : char *pszConcatenatedOpenOptions;
128 : int nOpenFlags;
129 :
130 : GDALDataset *poDS;
131 : };
132 :
133 : // Set of datasets opened as shared datasets (with GDALOpenShared)
134 : // The values in the set are of type SharedDatasetCtxt.
135 : static CPLHashSet *phSharedDatasetSet = nullptr;
136 :
137 : // Set of all datasets created in the constructor of GDALDataset.
138 : // In the case of a shared dataset, memorize the PID of the thread
139 : // that marked the dataset as shared, so that we can remove it from
140 : // the phSharedDatasetSet in the destructor of the dataset, even
141 : // if GDALClose is called from a different thread.
142 : static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
143 :
144 : static CPLMutex *hDLMutex = nullptr;
145 :
146 : // Static array of all datasets. Used by GDALGetOpenDatasets.
147 : // Not thread-safe. See GDALGetOpenDatasets.
148 : static GDALDataset **ppDatasets = nullptr;
149 :
150 8339 : static unsigned long GDALSharedDatasetHashFunc(const void *elt)
151 : {
152 8339 : const SharedDatasetCtxt *psStruct =
153 : static_cast<const SharedDatasetCtxt *>(elt);
154 : return static_cast<unsigned long>(
155 8339 : CPLHashSetHashStr(psStruct->pszDescription) ^
156 8339 : CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^
157 8339 : psStruct->nOpenFlags ^ psStruct->nPID);
158 : }
159 :
160 6936 : static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)
161 : {
162 6936 : const SharedDatasetCtxt *psStruct1 =
163 : static_cast<const SharedDatasetCtxt *>(elt1);
164 6936 : const SharedDatasetCtxt *psStruct2 =
165 : static_cast<const SharedDatasetCtxt *>(elt2);
166 13829 : return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
167 6893 : strcmp(psStruct1->pszConcatenatedOpenOptions,
168 6893 : psStruct2->pszConcatenatedOpenOptions) == 0 &&
169 20722 : psStruct1->nPID == psStruct2->nPID &&
170 13829 : psStruct1->nOpenFlags == psStruct2->nOpenFlags;
171 : }
172 :
173 394 : static void GDALSharedDatasetFreeFunc(void *elt)
174 : {
175 394 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
176 394 : CPLFree(psStruct->pszDescription);
177 394 : CPLFree(psStruct->pszConcatenatedOpenOptions);
178 394 : CPLFree(psStruct);
179 394 : }
180 :
181 : static std::string
182 7026 : GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)
183 : {
184 7026 : std::string osStr;
185 7039 : for (const char *pszOption : cpl::Iterate(papszOpenOptions))
186 13 : osStr += pszOption;
187 7026 : return osStr;
188 : }
189 :
190 : /************************************************************************/
191 : /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
192 : /************************************************************************/
193 :
194 : // The open-shared mutex must be used by the ProxyPool too.
195 481688 : CPLMutex **GDALGetphDLMutex()
196 : {
197 481688 : return &hDLMutex;
198 : }
199 :
200 : // The current thread will act in the behalf of the thread of PID
201 : // responsiblePID.
202 471368 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
203 : {
204 : GIntBig *pResponsiblePID =
205 471368 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
206 471367 : if (pResponsiblePID == nullptr)
207 : {
208 207 : pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
209 207 : CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
210 : }
211 471366 : *pResponsiblePID = responsiblePID;
212 471366 : }
213 :
214 : // Get the PID of the thread that the current thread will act in the behalf of
215 : // By default : the current thread acts in the behalf of itself.
216 596352 : GIntBig GDALGetResponsiblePIDForCurrentThread()
217 : {
218 : GIntBig *pResponsiblePID =
219 596352 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
220 596221 : if (pResponsiblePID == nullptr)
221 43371 : return CPLGetPID();
222 552850 : return *pResponsiblePID;
223 : }
224 :
225 : /************************************************************************/
226 : /* ==================================================================== */
227 : /* GDALDataset */
228 : /* ==================================================================== */
229 : /************************************************************************/
230 :
231 : /**
232 : * \class GDALDataset "gdal_priv.h"
233 : *
234 : * A dataset encapsulating one or more raster bands. Details are further
235 : * discussed in the <a href="https://gdal.org/user/raster_data_model.html">GDAL
236 : * Raster Data Model</a>.
237 : *
238 : * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
239 : * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
240 : * dataset.
241 : */
242 :
243 : /************************************************************************/
244 : /* GDALDataset() */
245 : /************************************************************************/
246 :
247 : //! @cond Doxygen_Suppress
248 128841 : GDALDataset::GDALDataset()
249 128841 : : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
250 : {
251 128737 : }
252 :
253 147865 : GDALDataset::GDALDataset(int bForceCachedIOIn)
254 147770 : : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
255 147865 : m_poPrivate(new(std::nothrow) GDALDataset::Private)
256 : {
257 147793 : }
258 :
259 : //! @endcond
260 :
261 : /************************************************************************/
262 : /* ~GDALDataset() */
263 : /************************************************************************/
264 :
265 : /**
266 : * \brief Destroy an open GDALDataset.
267 : *
268 : * This is the accepted method of closing a GDAL dataset and deallocating
269 : * all resources associated with it.
270 : *
271 : * Equivalent of the C callable GDALClose(). Except that GDALClose() first
272 : * decrements the reference count, and then closes only if it has dropped to
273 : * zero.
274 : *
275 : * For Windows users, it is not recommended to use the delete operator on the
276 : * dataset object because of known issues when allocating and freeing memory
277 : * across module boundaries. Calling GDALClose() is then a better option.
278 : */
279 :
280 147769 : GDALDataset::~GDALDataset()
281 :
282 : {
283 : // we don't want to report destruction of datasets that
284 : // were never really open or meant as internal
285 147755 : if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))
286 : {
287 69560 : if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
288 209 : CPLDebug("GDAL",
289 : "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
290 209 : GetDescription(), this, static_cast<int>(CPLGetPID()),
291 209 : static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
292 : else
293 69358 : CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
294 : }
295 :
296 147788 : if (IsMarkedSuppressOnClose())
297 : {
298 2326 : if (poDriver == nullptr ||
299 : // Someone issuing Create("foo.tif") on a
300 : // memory driver doesn't expect files with those names to be deleted
301 : // on a file system...
302 : // This is somewhat messy. Ideally there should be a way for the
303 : // driver to overload the default behavior
304 1158 : (!EQUAL(poDriver->GetDescription(), "MEM") &&
305 1119 : !EQUAL(poDriver->GetDescription(), "Memory")))
306 : {
307 1129 : VSIUnlink(GetDescription());
308 : }
309 : }
310 :
311 : /* -------------------------------------------------------------------- */
312 : /* Remove dataset from the "open" dataset list. */
313 : /* -------------------------------------------------------------------- */
314 147773 : if (!bIsInternal)
315 : {
316 140956 : CPLMutexHolderD(&hDLMutex);
317 70478 : if (poAllDatasetMap)
318 : {
319 : std::map<GDALDataset *, GIntBig>::iterator oIter =
320 70478 : poAllDatasetMap->find(this);
321 70478 : CPLAssert(oIter != poAllDatasetMap->end());
322 :
323 70478 : UnregisterFromSharedDataset();
324 :
325 70478 : poAllDatasetMap->erase(oIter);
326 :
327 70478 : if (poAllDatasetMap->empty())
328 : {
329 26699 : delete poAllDatasetMap;
330 26699 : poAllDatasetMap = nullptr;
331 26699 : if (phSharedDatasetSet)
332 : {
333 265 : CPLHashSetDestroy(phSharedDatasetSet);
334 : }
335 26699 : phSharedDatasetSet = nullptr;
336 26699 : CPLFree(ppDatasets);
337 26699 : ppDatasets = nullptr;
338 : }
339 : }
340 : }
341 :
342 : /* -------------------------------------------------------------------- */
343 : /* Destroy the raster bands if they exist. */
344 : /* -------------------------------------------------------------------- */
345 1675260 : for (int i = 0; i < nBands && papoBands != nullptr; ++i)
346 : {
347 1527490 : if (papoBands[i] != nullptr)
348 1527490 : delete papoBands[i];
349 1527490 : papoBands[i] = nullptr;
350 : }
351 :
352 147772 : CPLFree(papoBands);
353 :
354 147770 : if (m_poStyleTable)
355 : {
356 23 : delete m_poStyleTable;
357 23 : m_poStyleTable = nullptr;
358 : }
359 :
360 147770 : if (m_poPrivate != nullptr)
361 : {
362 147771 : if (m_poPrivate->hMutex != nullptr)
363 18581 : CPLDestroyMutex(m_poPrivate->hMutex);
364 :
365 : #if defined(__COVERITY__) || defined(DEBUG)
366 : // Not needed since at destruction there is no risk of concurrent use.
367 295542 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
368 : #endif
369 147771 : CPLFree(m_poPrivate->m_pszWKTCached);
370 147771 : if (m_poPrivate->m_poSRSCached)
371 : {
372 0 : m_poPrivate->m_poSRSCached->Release();
373 : }
374 147771 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
375 147771 : if (m_poPrivate->m_poSRSGCPCached)
376 : {
377 0 : m_poPrivate->m_poSRSGCPCached->Release();
378 : }
379 : }
380 :
381 147769 : delete m_poPrivate;
382 :
383 147768 : CSLDestroy(papszOpenOptions);
384 147771 : }
385 :
386 : /************************************************************************/
387 : /* Close() */
388 : /************************************************************************/
389 :
390 : /** Do final cleanup before a dataset is destroyed.
391 : *
392 : * This method is typically called by GDALClose() or the destructor of a
393 : * GDALDataset subclass. It might also be called by C++ users before
394 : * destroying a dataset. It should not be called on a shared dataset whose
395 : * reference count is greater than one.
396 : *
397 : * It gives a last chance to the closing process to return an error code if
398 : * something goes wrong, in particular in creation / update scenarios where
399 : * file write or network communication might occur when finalizing the dataset.
400 : *
401 : * Implementations should be robust to this method to be called several times
402 : * (on subsequent calls, it should do nothing and return CE_None).
403 : * Once it has been called, no other method than Close() or the dataset
404 : * destructor should be called. RasterBand or OGRLayer owned by the dataset
405 : * should be assumed as no longer being valid.
406 : *
407 : * If a driver implements this method, it must also call it from its
408 : * dataset destructor.
409 : *
410 : * A typical implementation might look as the following
411 : * \code{.cpp}
412 : *
413 : * MyDataset::~MyDataset()
414 : * {
415 : * try
416 : * {
417 : * MyDataset::Close();
418 : * }
419 : * catch (const std::exception &exc)
420 : * {
421 : * // If Close() can throw exception
422 : * CPLError(CE_Failure, CPLE_AppDefined,
423 : * "Exception thrown in MyDataset::Close(): %s",
424 : * exc.what());
425 : * }
426 : * catch (...)
427 : * {
428 : * // If Close() can throw exception
429 : * CPLError(CE_Failure, CPLE_AppDefined,
430 : * "Exception thrown in MyDataset::Close()");
431 : * }
432 : * }
433 : *
434 : * CPLErr MyDataset::Close()
435 : * {
436 : * CPLErr eErr = CE_None;
437 : * if( nOpenFlags != OPEN_FLAGS_CLOSED )
438 : * {
439 : * if( MyDataset::FlushCache(true) != CE_None )
440 : * eErr = CE_Failure;
441 : *
442 : * // Do something driver specific
443 : * if (m_fpImage)
444 : * {
445 : * if( VSIFCloseL(m_fpImage) != 0 )
446 : * {
447 : * CPLError(CE_Failure, CPLE_FileIO, "VSIFCloseL() failed");
448 : * eErr = CE_Failure;
449 : * }
450 : * }
451 : *
452 : * // Call parent Close() implementation.
453 : * if( MyParentDatasetClass::Close() != CE_None )
454 : * eErr = CE_Failure;
455 : * }
456 : * return eErr;
457 : * }
458 : * \endcode
459 : *
460 : * @since GDAL 3.7
461 : */
462 86496 : CPLErr GDALDataset::Close()
463 : {
464 : // Call UnregisterFromSharedDataset() before altering nOpenFlags
465 86496 : UnregisterFromSharedDataset();
466 :
467 86495 : nOpenFlags = OPEN_FLAGS_CLOSED;
468 86495 : return CE_None;
469 : }
470 :
471 : /************************************************************************/
472 : /* UnregisterFromSharedDataset() */
473 : /************************************************************************/
474 :
475 156972 : void GDALDataset::UnregisterFromSharedDataset()
476 : {
477 156972 : if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))
478 156578 : return;
479 :
480 788 : CPLMutexHolderD(&hDLMutex);
481 :
482 : std::map<GDALDataset *, GIntBig>::iterator oIter =
483 394 : poAllDatasetMap->find(this);
484 394 : CPLAssert(oIter != poAllDatasetMap->end());
485 394 : const GIntBig nPIDCreatorForShared = oIter->second;
486 394 : bShared = false;
487 : SharedDatasetCtxt sStruct;
488 394 : sStruct.nPID = nPIDCreatorForShared;
489 394 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
490 394 : sStruct.pszDescription = const_cast<char *>(GetDescription());
491 : std::string osConcatenatedOpenOptions =
492 788 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
493 394 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
494 394 : sStruct.poDS = nullptr;
495 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
496 394 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
497 394 : if (psStruct && psStruct->poDS == this)
498 : {
499 393 : CPLHashSetRemove(phSharedDatasetSet, psStruct);
500 : }
501 : else
502 : {
503 1 : CPLDebug("GDAL",
504 : "Should not happen. Cannot find %s, "
505 : "this=%p in phSharedDatasetSet",
506 1 : GetDescription(), this);
507 : }
508 : }
509 :
510 : /************************************************************************/
511 : /* AddToDatasetOpenList() */
512 : /************************************************************************/
513 :
514 71849 : void GDALDataset::AddToDatasetOpenList()
515 : {
516 : /* -------------------------------------------------------------------- */
517 : /* Add this dataset to the open dataset list. */
518 : /* -------------------------------------------------------------------- */
519 71849 : bIsInternal = false;
520 :
521 71849 : CPLMutexHolderD(&hDLMutex);
522 :
523 71849 : if (poAllDatasetMap == nullptr)
524 26708 : poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
525 71849 : (*poAllDatasetMap)[this] = -1;
526 71849 : }
527 :
528 : /************************************************************************/
529 : /* FlushCache() */
530 : /************************************************************************/
531 :
532 : /**
533 : * \brief Flush all write cached data to disk.
534 : *
535 : * Any raster (or other GDAL) data written via GDAL calls, but buffered
536 : * internally will be written to disk.
537 : *
538 : * The default implementation of this method just calls the FlushCache() method
539 : * on each of the raster bands and the SyncToDisk() method
540 : * on each of the layers. Conceptually, calling FlushCache() on a dataset
541 : * should include any work that might be accomplished by calling SyncToDisk()
542 : * on layers in that dataset.
543 : *
544 : * Using this method does not prevent use from calling GDALClose()
545 : * to properly close a dataset and ensure that important data not addressed
546 : * by FlushCache() is written in the file.
547 : *
548 : * This method is the same as the C function GDALFlushCache().
549 : *
550 : * @param bAtClosing Whether this is called from a GDALDataset destructor
551 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
552 : */
553 :
554 112232 : CPLErr GDALDataset::FlushCache(bool bAtClosing)
555 :
556 : {
557 112232 : CPLErr eErr = CE_None;
558 : // This sometimes happens if a dataset is destroyed before completely
559 : // built.
560 :
561 112232 : if (papoBands)
562 : {
563 1992930 : for (int i = 0; i < nBands; ++i)
564 : {
565 1890140 : if (papoBands[i])
566 : {
567 1890140 : if (papoBands[i]->FlushCache(bAtClosing) != CE_None)
568 7 : eErr = CE_Failure;
569 : }
570 : }
571 : }
572 :
573 112231 : const int nLayers = GetLayerCount();
574 : // cppcheck-suppress knownConditionTrueFalse
575 112231 : if (nLayers > 0)
576 : {
577 9840 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
578 14584 : for (int i = 0; i < nLayers; ++i)
579 : {
580 9664 : OGRLayer *poLayer = GetLayer(i);
581 :
582 9664 : if (poLayer)
583 : {
584 9664 : if (poLayer->SyncToDisk() != OGRERR_NONE)
585 0 : eErr = CE_Failure;
586 : }
587 : }
588 : }
589 :
590 112231 : return eErr;
591 : }
592 :
593 : /************************************************************************/
594 : /* GDALFlushCache() */
595 : /************************************************************************/
596 :
597 : /**
598 : * \brief Flush all write cached data to disk.
599 : *
600 : * @see GDALDataset::FlushCache().
601 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
602 : */
603 :
604 4741 : CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)
605 :
606 : {
607 4741 : VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);
608 :
609 4741 : return GDALDataset::FromHandle(hDS)->FlushCache(false);
610 : }
611 :
612 : /************************************************************************/
613 : /* DropCache() */
614 : /************************************************************************/
615 :
616 : /**
617 : * \brief Drop all write cached data
618 : *
619 : * This method is the same as the C function GDALDropCache().
620 : *
621 : * @return CE_None in case of success
622 : * @since 3.9
623 : */
624 :
625 1 : CPLErr GDALDataset::DropCache()
626 :
627 : {
628 1 : CPLErr eErr = CE_None;
629 :
630 1 : if (papoBands)
631 : {
632 2 : for (int i = 0; i < nBands; ++i)
633 : {
634 1 : if (papoBands[i])
635 : {
636 1 : if (papoBands[i]->DropCache() != CE_None)
637 0 : eErr = CE_Failure;
638 : }
639 : }
640 : }
641 :
642 1 : return eErr;
643 : }
644 :
645 : /************************************************************************/
646 : /* GDALDropCache() */
647 : /************************************************************************/
648 :
649 : /**
650 : * \brief Drop all write cached data
651 : *
652 : * @see GDALDataset::DropCache().
653 : * @return CE_None in case of success
654 : * @since 3.9
655 : */
656 :
657 0 : CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS)
658 :
659 : {
660 0 : VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure);
661 :
662 0 : return GDALDataset::FromHandle(hDS)->DropCache();
663 : }
664 :
665 : /************************************************************************/
666 : /* GetEstimatedRAMUsage() */
667 : /************************************************************************/
668 :
669 : /**
670 : * \brief Return the intrinsic RAM usage of this dataset.
671 : *
672 : * The returned value should take into account caches in the underlying driver
673 : * and decoding library, but not the usage related to the GDAL block cache.
674 : *
675 : * At time of writing, this method is only implemented in the JP2OpenJPEG
676 : * driver. For single-tiled JPEG2000 images, the decoding of the image,
677 : * even partially, involves allocating at least
678 : * width * height * number_of_bands * sizeof(uint32_t) bytes inside the libopenjp2
679 : * library.
680 : *
681 : * This method is used by the GDALDatasetPool class, itself used by the GDAL VRT
682 : * driver, to determine how long a dataset in the pool must be kept open, given
683 : * the RAM usage of the dataset with respect to the usable total RAM.
684 : *
685 : * @since GDAL 3.7
686 : * @return RAM usage in bytes, or -1 if unknown (the default implementation
687 : * returns -1)
688 : */
689 :
690 3305 : GIntBig GDALDataset::GetEstimatedRAMUsage()
691 : {
692 3305 : return -1;
693 : }
694 :
695 : /************************************************************************/
696 : /* BlockBasedFlushCache() */
697 : /* */
698 : /* This helper method can be called by the */
699 : /* GDALDataset::FlushCache() for particular drivers to ensure */
700 : /* that buffers will be flushed in a manner suitable for pixel */
701 : /* interleaved (by block) IO. That is, if all the bands have */
702 : /* the same size blocks then a given block will be flushed for */
703 : /* all bands before proceeding to the next block. */
704 : /************************************************************************/
705 :
706 : //! @cond Doxygen_Suppress
707 350 : CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)
708 :
709 : {
710 350 : GDALRasterBand *poBand1 = GetRasterBand(1);
711 350 : if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))
712 : {
713 7 : return GDALDataset::FlushCache(bAtClosing);
714 : }
715 :
716 343 : int nBlockXSize = 0;
717 343 : int nBlockYSize = 0;
718 343 : poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
719 :
720 : /* -------------------------------------------------------------------- */
721 : /* Verify that all bands match. */
722 : /* -------------------------------------------------------------------- */
723 1108 : for (int iBand = 1; iBand < nBands; ++iBand)
724 : {
725 765 : GDALRasterBand *poBand = GetRasterBand(iBand + 1);
726 :
727 : int nThisBlockXSize, nThisBlockYSize;
728 765 : poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
729 765 : if (nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize)
730 : {
731 0 : return GDALDataset::FlushCache(bAtClosing);
732 : }
733 : }
734 :
735 : /* -------------------------------------------------------------------- */
736 : /* Now flush writable data. */
737 : /* -------------------------------------------------------------------- */
738 794 : for (int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY)
739 : {
740 991 : for (int iX = 0; iX < poBand1->nBlocksPerRow; ++iX)
741 : {
742 1690 : for (int iBand = 0; iBand < nBands; ++iBand)
743 : {
744 1150 : const CPLErr eErr = papoBands[iBand]->FlushBlock(iX, iY);
745 :
746 1150 : if (eErr != CE_None)
747 0 : return CE_Failure;
748 : }
749 : }
750 : }
751 343 : return CE_None;
752 : }
753 :
754 : /************************************************************************/
755 : /* RasterInitialize() */
756 : /* */
757 : /* Initialize raster size */
758 : /************************************************************************/
759 :
760 0 : void GDALDataset::RasterInitialize(int nXSize, int nYSize)
761 :
762 : {
763 0 : CPLAssert(nXSize > 0 && nYSize > 0);
764 :
765 0 : nRasterXSize = nXSize;
766 0 : nRasterYSize = nYSize;
767 0 : }
768 :
769 : //! @endcond
770 :
771 : /************************************************************************/
772 : /* AddBand() */
773 : /************************************************************************/
774 :
775 : /**
776 : * \fn GDALDataset::AddBand(GDALDataType, char**)
777 : * \brief Add a band to a dataset.
778 : *
779 : * This method will add a new band to the dataset if the underlying format
780 : * supports this action. Most formats do not.
781 : *
782 : * Note that the new GDALRasterBand is not returned. It may be fetched
783 : * after successful completion of the method by calling
784 : * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
785 : * band will always be the last band.
786 : *
787 : * @param eType the data type of the pixels in the new band.
788 : *
789 : * @param papszOptions a list of NAME=VALUE option strings. The supported
790 : * options are format specific. NULL may be passed by default.
791 : *
792 : * @return CE_None on success or CE_Failure on failure.
793 : */
794 :
795 0 : CPLErr GDALDataset::AddBand(CPL_UNUSED GDALDataType eType,
796 : CPL_UNUSED char **papszOptions)
797 :
798 : {
799 0 : ReportError(CE_Failure, CPLE_NotSupported,
800 : "Dataset does not support the AddBand() method.");
801 :
802 0 : return CE_Failure;
803 : }
804 :
805 : /************************************************************************/
806 : /* GDALAddBand() */
807 : /************************************************************************/
808 :
809 : /**
810 : * \brief Add a band to a dataset.
811 : *
812 : * @see GDALDataset::AddBand().
813 : */
814 :
815 30 : CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,
816 : CSLConstList papszOptions)
817 :
818 : {
819 30 : VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
820 :
821 60 : return GDALDataset::FromHandle(hDataset)->AddBand(
822 30 : eType, const_cast<char **>(papszOptions));
823 : }
824 :
825 : /************************************************************************/
826 : /* SetBand() */
827 : /************************************************************************/
828 :
829 : //! @cond Doxygen_Suppress
830 : /** Set a band in the band array, updating the band count, and array size
831 : * appropriately.
832 : *
833 : * @param nNewBand new band number (indexing starts at 1)
834 : * @param poBand band object.
835 : */
836 :
837 1742910 : void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)
838 :
839 : {
840 : /* -------------------------------------------------------------------- */
841 : /* Do we need to grow the bands list? */
842 : /* -------------------------------------------------------------------- */
843 1742910 : if (nBands < nNewBand || papoBands == nullptr)
844 : {
845 1008770 : GDALRasterBand **papoNewBands = nullptr;
846 :
847 1008770 : if (papoBands == nullptr)
848 94583 : papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
849 94647 : sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
850 : else
851 : papoNewBands = static_cast<GDALRasterBand **>(
852 914079 : VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
853 914124 : std::max(nNewBand, nBands)));
854 1008660 : if (papoNewBands == nullptr)
855 : {
856 0 : ReportError(CE_Failure, CPLE_OutOfMemory,
857 : "Cannot allocate band array");
858 0 : return;
859 : }
860 :
861 1008660 : papoBands = papoNewBands;
862 :
863 1967200 : for (int i = nBands; i < nNewBand; ++i)
864 958538 : papoBands[i] = nullptr;
865 :
866 1008660 : nBands = std::max(nBands, nNewBand);
867 :
868 1008730 : if (m_poPrivate)
869 : {
870 1008850 : for (int i = static_cast<int>(m_poPrivate->m_anBandMap.size());
871 2751570 : i < nBands; ++i)
872 : {
873 1742830 : m_poPrivate->m_anBandMap.push_back(i + 1);
874 : }
875 : }
876 : }
877 :
878 : /* -------------------------------------------------------------------- */
879 : /* Set the band. Resetting the band is currently not permitted. */
880 : /* -------------------------------------------------------------------- */
881 1742750 : if (papoBands[nNewBand - 1] != nullptr)
882 : {
883 0 : ReportError(CE_Failure, CPLE_NotSupported,
884 : "Cannot set band %d as it is already set", nNewBand);
885 0 : return;
886 : }
887 :
888 1742750 : papoBands[nNewBand - 1] = poBand;
889 :
890 : /* -------------------------------------------------------------------- */
891 : /* Set back reference information on the raster band. Note */
892 : /* that the GDALDataset is a friend of the GDALRasterBand */
893 : /* specifically to allow this. */
894 : /* -------------------------------------------------------------------- */
895 1742750 : poBand->nBand = nNewBand;
896 1742750 : poBand->poDS = this;
897 1742750 : poBand->nRasterXSize = nRasterXSize;
898 1742750 : poBand->nRasterYSize = nRasterYSize;
899 1742750 : poBand->eAccess = eAccess; // Default access to be same as dataset.
900 : }
901 :
902 : //! @endcond
903 :
904 : /************************************************************************/
905 : /* SetBand() */
906 : /************************************************************************/
907 :
908 : //! @cond Doxygen_Suppress
909 : /** Set a band in the band array, updating the band count, and array size
910 : * appropriately.
911 : *
912 : * @param nNewBand new band number (indexing starts at 1)
913 : * @param poBand band object.
914 : */
915 :
916 76326 : void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)
917 : {
918 76326 : SetBand(nNewBand, poBand.release());
919 76325 : }
920 :
921 : //! @endcond
922 :
923 : /************************************************************************/
924 : /* GetRasterXSize() */
925 : /************************************************************************/
926 :
927 : /**
928 :
929 : \brief Fetch raster width in pixels.
930 :
931 : Equivalent of the C function GDALGetRasterXSize().
932 :
933 : @return the width in pixels of raster bands in this GDALDataset.
934 :
935 : */
936 :
937 703007 : int GDALDataset::GetRasterXSize() const
938 : {
939 703007 : return nRasterXSize;
940 : }
941 :
942 : /************************************************************************/
943 : /* GDALGetRasterXSize() */
944 : /************************************************************************/
945 :
946 : /**
947 : * \brief Fetch raster width in pixels.
948 : *
949 : * @see GDALDataset::GetRasterXSize().
950 : */
951 :
952 36862 : int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)
953 :
954 : {
955 36862 : VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
956 :
957 36862 : return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
958 : }
959 :
960 : /************************************************************************/
961 : /* GetRasterYSize() */
962 : /************************************************************************/
963 :
964 : /**
965 :
966 : \brief Fetch raster height in pixels.
967 :
968 : Equivalent of the C function GDALGetRasterYSize().
969 :
970 : @return the height in pixels of raster bands in this GDALDataset.
971 :
972 : */
973 :
974 584676 : int GDALDataset::GetRasterYSize() const
975 : {
976 584676 : return nRasterYSize;
977 : }
978 :
979 : /************************************************************************/
980 : /* GDALGetRasterYSize() */
981 : /************************************************************************/
982 :
983 : /**
984 : * \brief Fetch raster height in pixels.
985 : *
986 : * @see GDALDataset::GetRasterYSize().
987 : */
988 :
989 36519 : int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)
990 :
991 : {
992 36519 : VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
993 :
994 36519 : return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
995 : }
996 :
997 : /************************************************************************/
998 : /* GetRasterBand() */
999 : /************************************************************************/
1000 :
1001 : /**
1002 :
1003 : \brief Fetch a band object for a dataset.
1004 :
1005 : See GetBands() for a C++ iterator version of this method.
1006 :
1007 : Equivalent of the C function GDALGetRasterBand().
1008 :
1009 : @param nBandId the index number of the band to fetch, from 1 to
1010 : GetRasterCount().
1011 :
1012 : @return the nBandId th band object
1013 :
1014 : */
1015 :
1016 12010700 : GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)
1017 :
1018 : {
1019 12010700 : if (papoBands)
1020 : {
1021 12008000 : if (nBandId < 1 || nBandId > nBands)
1022 : {
1023 4910 : ReportError(CE_Failure, CPLE_IllegalArg,
1024 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1025 : nBandId);
1026 12 : return nullptr;
1027 : }
1028 :
1029 12003100 : return papoBands[nBandId - 1];
1030 : }
1031 2687 : return nullptr;
1032 : }
1033 :
1034 : /************************************************************************/
1035 : /* GetRasterBand() */
1036 : /************************************************************************/
1037 :
1038 : /**
1039 :
1040 : \brief Fetch a band object for a dataset.
1041 :
1042 : See GetBands() for a C++ iterator version of this method.
1043 :
1044 : Equivalent of the C function GDALGetRasterBand().
1045 :
1046 : @param nBandId the index number of the band to fetch, from 1 to
1047 : GetRasterCount().
1048 :
1049 : @return the nBandId th band object
1050 :
1051 : */
1052 :
1053 587 : const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const
1054 :
1055 : {
1056 587 : if (papoBands)
1057 : {
1058 587 : if (nBandId < 1 || nBandId > nBands)
1059 : {
1060 0 : ReportError(CE_Failure, CPLE_IllegalArg,
1061 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1062 : nBandId);
1063 0 : return nullptr;
1064 : }
1065 :
1066 587 : return papoBands[nBandId - 1];
1067 : }
1068 0 : return nullptr;
1069 : }
1070 :
1071 : /************************************************************************/
1072 : /* GDALGetRasterBand() */
1073 : /************************************************************************/
1074 :
1075 : /**
1076 : * \brief Fetch a band object for a dataset.
1077 : * @see GDALDataset::GetRasterBand().
1078 : */
1079 :
1080 398075 : GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)
1081 :
1082 : {
1083 398075 : VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
1084 :
1085 398075 : return GDALRasterBand::ToHandle(
1086 398075 : GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
1087 : }
1088 :
1089 : /************************************************************************/
1090 : /* GetRasterCount() */
1091 : /************************************************************************/
1092 :
1093 : /**
1094 : * \brief Fetch the number of raster bands on this dataset.
1095 : *
1096 : * Same as the C function GDALGetRasterCount().
1097 : *
1098 : * @return the number of raster bands.
1099 : */
1100 :
1101 5887750 : int GDALDataset::GetRasterCount() const
1102 : {
1103 5887750 : return papoBands ? nBands : 0;
1104 : }
1105 :
1106 : /************************************************************************/
1107 : /* GDALGetRasterCount() */
1108 : /************************************************************************/
1109 :
1110 : /**
1111 : * \brief Fetch the number of raster bands on this dataset.
1112 : *
1113 : * @see GDALDataset::GetRasterCount().
1114 : */
1115 :
1116 381291 : int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)
1117 :
1118 : {
1119 381291 : VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
1120 :
1121 381291 : return GDALDataset::FromHandle(hDS)->GetRasterCount();
1122 : }
1123 :
1124 : /************************************************************************/
1125 : /* GetProjectionRef() */
1126 : /************************************************************************/
1127 :
1128 : /**
1129 : * \brief Fetch the projection definition string for this dataset.
1130 : *
1131 : * Same as the C function GDALGetProjectionRef().
1132 : *
1133 : * The returned string defines the projection coordinate system of the
1134 : * image in OpenGIS WKT format. It should be suitable for use with the
1135 : * OGRSpatialReference class.
1136 : *
1137 : * When a projection definition is not available an empty (but not NULL)
1138 : * string is returned.
1139 : *
1140 : * \note Starting with GDAL 3.0, this is a compatibility layer around
1141 : * GetSpatialRef()
1142 : *
1143 : * @return a pointer to an internal projection reference string. It should
1144 : * not be altered, freed or expected to last for long.
1145 : *
1146 : * @see https://gdal.org/tutorials/osr_api_tut.html
1147 : */
1148 :
1149 5435 : const char *GDALDataset::GetProjectionRef() const
1150 : {
1151 5435 : const auto poSRS = GetSpatialRef();
1152 5435 : if (!poSRS || !m_poPrivate)
1153 : {
1154 2445 : return "";
1155 : }
1156 2990 : char *pszWKT = nullptr;
1157 2990 : poSRS->exportToWkt(&pszWKT);
1158 2990 : if (!pszWKT)
1159 : {
1160 0 : return "";
1161 : }
1162 :
1163 : // If called on a thread-safe dataset, we might be called by several
1164 : // threads, so make sure our accesses to m_pszWKTCached are protected
1165 : // by a mutex.
1166 5980 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1167 2990 : if (m_poPrivate->m_pszWKTCached &&
1168 822 : strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)
1169 : {
1170 821 : CPLFree(pszWKT);
1171 821 : return m_poPrivate->m_pszWKTCached;
1172 : }
1173 2169 : CPLFree(m_poPrivate->m_pszWKTCached);
1174 2169 : m_poPrivate->m_pszWKTCached = pszWKT;
1175 2169 : return m_poPrivate->m_pszWKTCached;
1176 : }
1177 :
1178 : /************************************************************************/
1179 : /* GetSpatialRef() */
1180 : /************************************************************************/
1181 :
1182 : /**
1183 : * \brief Fetch the spatial reference for this dataset.
1184 : *
1185 : * Same as the C function GDALGetSpatialRef().
1186 : *
1187 : * When a projection definition is not available, null is returned. If used on
1188 : * a dataset where there are GCPs and not a geotransform, this method returns
1189 : * null. Use GetGCPSpatialRef() instead.
1190 : *
1191 : * @since GDAL 3.0
1192 : *
1193 : * @return a pointer to an internal object. It should not be altered or freed.
1194 : * Its lifetime will be the one of the dataset object, or until the next
1195 : * call to this method.
1196 : *
1197 : * @see https://gdal.org/tutorials/osr_api_tut.html
1198 : */
1199 :
1200 17031 : const OGRSpatialReference *GDALDataset::GetSpatialRef() const
1201 : {
1202 17031 : return nullptr;
1203 : }
1204 :
1205 : /************************************************************************/
1206 : /* GDALGetSpatialRef() */
1207 : /************************************************************************/
1208 :
1209 : /**
1210 : * \brief Fetch the spatial reference for this dataset.
1211 : *
1212 : * @since GDAL 3.0
1213 : *
1214 : * @see GDALDataset::GetSpatialRef()
1215 : */
1216 :
1217 6597 : OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)
1218 :
1219 : {
1220 6597 : VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
1221 :
1222 6597 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1223 6597 : GDALDataset::FromHandle(hDS)->GetSpatialRef()));
1224 : }
1225 :
1226 : /************************************************************************/
1227 : /* GDALGetProjectionRef() */
1228 : /************************************************************************/
1229 :
1230 : /**
1231 : * \brief Fetch the projection definition string for this dataset.
1232 : *
1233 : * @see GDALDataset::GetProjectionRef()
1234 : */
1235 :
1236 1479 : const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)
1237 :
1238 : {
1239 1479 : VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
1240 :
1241 1479 : return GDALDataset::FromHandle(hDS)->GetProjectionRef();
1242 : }
1243 :
1244 : /************************************************************************/
1245 : /* SetProjection() */
1246 : /************************************************************************/
1247 :
1248 : /**
1249 : * \brief Set the projection reference string for this dataset.
1250 : *
1251 : * The string should be in OGC WKT or PROJ.4 format. An error may occur
1252 : * because of incorrectly specified projection strings, because the dataset
1253 : * is not writable, or because the dataset does not support the indicated
1254 : * projection. Many formats do not support writing projections.
1255 : *
1256 : * This method is the same as the C GDALSetProjection() function.
1257 : *
1258 : * \note Startig with GDAL 3.0, this is a compatibility layer around
1259 : * SetSpatialRef()
1260 :
1261 : * @param pszProjection projection reference string.
1262 : *
1263 : * @return CE_Failure if an error occurs, otherwise CE_None.
1264 : */
1265 :
1266 2386 : CPLErr GDALDataset::SetProjection(const char *pszProjection)
1267 : {
1268 2386 : if (pszProjection && pszProjection[0] != '\0')
1269 : {
1270 4404 : OGRSpatialReference oSRS;
1271 2202 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1272 2202 : if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)
1273 : {
1274 2 : return CE_Failure;
1275 : }
1276 2200 : return SetSpatialRef(&oSRS);
1277 : }
1278 : else
1279 : {
1280 184 : return SetSpatialRef(nullptr);
1281 : }
1282 : }
1283 :
1284 : /************************************************************************/
1285 : /* SetSpatialRef() */
1286 : /************************************************************************/
1287 :
1288 : /**
1289 : * \brief Set the spatial reference system for this dataset.
1290 : *
1291 : * An error may occur because the dataset
1292 : * is not writable, or because the dataset does not support the indicated
1293 : * projection. Many formats do not support writing projections.
1294 : *
1295 : * This method is the same as the C GDALSetSpatialRef() function.
1296 : *
1297 : * @since GDAL 3.0
1298 :
1299 : * @param poSRS spatial reference system object. nullptr can potentially be
1300 : * passed for drivers that support unsetting the SRS.
1301 : *
1302 : * @return CE_Failure if an error occurs, otherwise CE_None.
1303 : */
1304 :
1305 0 : CPLErr GDALDataset::SetSpatialRef(CPL_UNUSED const OGRSpatialReference *poSRS)
1306 : {
1307 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1308 0 : ReportError(CE_Failure, CPLE_NotSupported,
1309 : "Dataset does not support the SetSpatialRef() method.");
1310 0 : return CE_Failure;
1311 : }
1312 :
1313 : /************************************************************************/
1314 : /* GDALSetSpatialRef() */
1315 : /************************************************************************/
1316 :
1317 : /**
1318 : * \brief Set the spatial reference system for this dataset.
1319 : *
1320 : * @since GDAL 3.0
1321 : *
1322 : * @see GDALDataset::SetSpatialRef()
1323 : */
1324 :
1325 1125 : CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)
1326 :
1327 : {
1328 1125 : VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1329 :
1330 2250 : return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1331 1125 : OGRSpatialReference::FromHandle(hSRS));
1332 : }
1333 :
1334 : /************************************************************************/
1335 : /* GDALSetProjection() */
1336 : /************************************************************************/
1337 :
1338 : /**
1339 : * \brief Set the projection reference string for this dataset.
1340 : *
1341 : * @see GDALDataset::SetProjection()
1342 : */
1343 :
1344 1778 : CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,
1345 : const char *pszProjection)
1346 :
1347 : {
1348 1778 : VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1349 :
1350 1778 : return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
1351 : }
1352 :
1353 : /************************************************************************/
1354 : /* GetGeoTransform() */
1355 : /************************************************************************/
1356 :
1357 : /**
1358 : * \brief Fetch the affine transformation coefficients.
1359 : *
1360 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
1361 : * space, and projection coordinates (Xp,Yp) space.
1362 : *
1363 : * \code
1364 : * Xp = gt[0] + P*gt[1] + L*gt[2];
1365 : * Yp = gt[3] + P*padfTransform[4] + L*gt[5];
1366 : * \endcode
1367 : *
1368 : * In a north up image, gt[1] is the pixel width, and
1369 : * gt[5] is the pixel height. The upper left corner of the
1370 : * upper left pixel is at position (gt[0],gt[3]).
1371 : *
1372 : * The default transform is (0,1,0,0,0,1) and should be returned even when
1373 : * a CE_Failure error is returned, such as for formats that don't support
1374 : * transformation to projection coordinates.
1375 : *
1376 : * This method does the same thing as the C GDALGetGeoTransform() function.
1377 : *
1378 : * @param gt an existing six double buffer into which the
1379 : * transformation will be placed.
1380 : *
1381 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
1382 : *
1383 : * @since 3.12
1384 : */
1385 :
1386 15522 : CPLErr GDALDataset::GetGeoTransform(GDALGeoTransform >) const
1387 :
1388 : {
1389 15522 : gt = GDALGeoTransform();
1390 :
1391 15521 : return CE_Failure;
1392 : }
1393 :
1394 : /************************************************************************/
1395 : /* GetGeoTransform() */
1396 : /************************************************************************/
1397 :
1398 : /**
1399 : * \brief Fetch the affine transformation coefficients.
1400 : *
1401 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
1402 : * space, and projection coordinates (Xp,Yp) space.
1403 : *
1404 : * \code
1405 : * Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
1406 : * Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
1407 : * \endcode
1408 : *
1409 : * In a north up image, padfTransform[1] is the pixel width, and
1410 : * padfTransform[5] is the pixel height. The upper left corner of the
1411 : * upper left pixel is at position (padfTransform[0],padfTransform[3]).
1412 : *
1413 : * The default transform is (0,1,0,0,0,1) and should be returned even when
1414 : * a CE_Failure error is returned, such as for formats that don't support
1415 : * transformation to projection coordinates.
1416 : *
1417 : * This method does the same thing as the C GDALGetGeoTransform() function.
1418 : *
1419 : * @param padfTransform an existing six double buffer into which the
1420 : * transformation will be placed.
1421 : *
1422 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
1423 : *
1424 : * @deprecated since 3.12. Use GetGeoTransform(GDALGeoTransform&) instead
1425 : */
1426 :
1427 2 : CPLErr GDALDataset::GetGeoTransform(double *padfTransform) const
1428 :
1429 : {
1430 2 : return GetGeoTransform(
1431 2 : *reinterpret_cast<GDALGeoTransform *>(padfTransform));
1432 : }
1433 :
1434 : /************************************************************************/
1435 : /* GDALGetGeoTransform() */
1436 : /************************************************************************/
1437 :
1438 : /**
1439 : * \brief Fetch the affine transformation coefficients.
1440 : *
1441 : * @see GDALDataset::GetGeoTransform()
1442 : */
1443 :
1444 8675 : CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1445 :
1446 : {
1447 8675 : VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1448 :
1449 17350 : return GDALDataset::FromHandle(hDS)->GetGeoTransform(
1450 8675 : *reinterpret_cast<GDALGeoTransform *>(padfTransform));
1451 : }
1452 :
1453 : /************************************************************************/
1454 : /* SetGeoTransform() */
1455 : /************************************************************************/
1456 :
1457 : /**
1458 : * \fn GDALDataset::SetGeoTransform(const GDALGeoTransform&)
1459 : * \brief Set the affine transformation coefficients.
1460 : *
1461 : * See GetGeoTransform() for details on the meaning of the padfTransform
1462 : * coefficients.
1463 : *
1464 : * This method does the same thing as the C GDALSetGeoTransform() function.
1465 : *
1466 : * @param gt the transformation coefficients to be written with the dataset.
1467 : *
1468 : * @return CE_None on success, or CE_Failure if this transform cannot be
1469 : * written.
1470 : *
1471 : * @since 3.12
1472 : */
1473 :
1474 0 : CPLErr GDALDataset::SetGeoTransform(CPL_UNUSED const GDALGeoTransform >)
1475 :
1476 : {
1477 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1478 0 : ReportError(CE_Failure, CPLE_NotSupported,
1479 : "SetGeoTransform() not supported for this dataset.");
1480 :
1481 0 : return CE_Failure;
1482 : }
1483 :
1484 : /************************************************************************/
1485 : /* SetGeoTransform() */
1486 : /************************************************************************/
1487 :
1488 : /**
1489 : * \brief Set the affine transformation coefficients.
1490 : *
1491 : * See GetGeoTransform() for details on the meaning of the padfTransform
1492 : * coefficients.
1493 : *
1494 : * This method does the same thing as the C GDALSetGeoTransform() function.
1495 : *
1496 : * @param padfTransform a six double buffer containing the transformation
1497 : * coefficients to be written with the dataset.
1498 : *
1499 : * @return CE_None on success, or CE_Failure if this transform cannot be
1500 : * written.
1501 : *
1502 : * @deprecated since 3.12. Use SetGeoTransform(const GDALGeoTransform&) instead
1503 : */
1504 30 : CPLErr GDALDataset::SetGeoTransform(const double *padfTransform)
1505 :
1506 : {
1507 30 : return SetGeoTransform(
1508 30 : *reinterpret_cast<const GDALGeoTransform *>(padfTransform));
1509 : }
1510 :
1511 : /************************************************************************/
1512 : /* GDALSetGeoTransform() */
1513 : /************************************************************************/
1514 :
1515 : /**
1516 : * \brief Set the affine transformation coefficients.
1517 : *
1518 : * @see GDALDataset::SetGeoTransform()
1519 : */
1520 :
1521 3873 : CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS,
1522 : const double *padfTransform)
1523 :
1524 : {
1525 3873 : VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1526 3873 : VALIDATE_POINTER1(padfTransform, "GDALSetGeoTransform", CE_Failure);
1527 :
1528 7746 : return GDALDataset::FromHandle(hDS)->SetGeoTransform(
1529 3873 : *reinterpret_cast<const GDALGeoTransform *>(padfTransform));
1530 : }
1531 :
1532 : /************************************************************************/
1533 : /* GetInternalHandle() */
1534 : /************************************************************************/
1535 :
1536 : /**
1537 : * \fn GDALDataset::GetInternalHandle(const char*)
1538 : * \brief Fetch a format specific internally meaningful handle.
1539 : *
1540 : * This method is the same as the C GDALGetInternalHandle() method.
1541 : *
1542 : * @param pszHandleName the handle name desired. The meaningful names
1543 : * will be specific to the file format.
1544 : *
1545 : * @return the desired handle value, or NULL if not recognized/supported.
1546 : */
1547 :
1548 184 : void *GDALDataset::GetInternalHandle(CPL_UNUSED const char *pszHandleName)
1549 :
1550 : {
1551 184 : return nullptr;
1552 : }
1553 :
1554 : /************************************************************************/
1555 : /* GDALGetInternalHandle() */
1556 : /************************************************************************/
1557 :
1558 : /**
1559 : * \brief Fetch a format specific internally meaningful handle.
1560 : *
1561 : * @see GDALDataset::GetInternalHandle()
1562 : */
1563 :
1564 60 : void *CPL_STDCALL GDALGetInternalHandle(GDALDatasetH hDS,
1565 : const char *pszRequest)
1566 :
1567 : {
1568 60 : VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
1569 :
1570 60 : return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
1571 : }
1572 :
1573 : /************************************************************************/
1574 : /* GetDriver() */
1575 : /************************************************************************/
1576 :
1577 : /**
1578 : * \brief Fetch the driver to which this dataset relates.
1579 : *
1580 : * This method is the same as the C GDALGetDatasetDriver() function.
1581 : *
1582 : * @return the driver on which the dataset was created with GDALOpen() or
1583 : * GDALCreate().
1584 : */
1585 :
1586 30542 : GDALDriver *GDALDataset::GetDriver()
1587 : {
1588 30542 : return poDriver;
1589 : }
1590 :
1591 : /************************************************************************/
1592 : /* GDALGetDatasetDriver() */
1593 : /************************************************************************/
1594 :
1595 : /**
1596 : * \brief Fetch the driver to which this dataset relates.
1597 : *
1598 : * @see GDALDataset::GetDriver()
1599 : */
1600 :
1601 2686 : GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)
1602 :
1603 : {
1604 2686 : VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1605 :
1606 : return static_cast<GDALDriverH>(
1607 2686 : GDALDataset::FromHandle(hDataset)->GetDriver());
1608 : }
1609 :
1610 : /************************************************************************/
1611 : /* Reference() */
1612 : /************************************************************************/
1613 :
1614 : /**
1615 : * \brief Add one to dataset reference count.
1616 : *
1617 : * The reference is one after instantiation.
1618 : *
1619 : * This method is the same as the C GDALReferenceDataset() function.
1620 : *
1621 : * @return the post-increment reference count.
1622 : */
1623 :
1624 255199 : int GDALDataset::Reference()
1625 : {
1626 255199 : return ++nRefCount;
1627 : }
1628 :
1629 : /************************************************************************/
1630 : /* GDALReferenceDataset() */
1631 : /************************************************************************/
1632 :
1633 : /**
1634 : * \brief Add one to dataset reference count.
1635 : *
1636 : * @see GDALDataset::Reference()
1637 : */
1638 :
1639 1223 : int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)
1640 :
1641 : {
1642 1223 : VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1643 :
1644 1223 : return GDALDataset::FromHandle(hDataset)->Reference();
1645 : }
1646 :
1647 : /************************************************************************/
1648 : /* Dereference() */
1649 : /************************************************************************/
1650 :
1651 : /**
1652 : * \brief Subtract one from dataset reference count.
1653 : *
1654 : * The reference is one after instantiation. Generally when the reference
1655 : * count has dropped to zero the dataset may be safely deleted (closed).
1656 : *
1657 : * This method is the same as the C GDALDereferenceDataset() function.
1658 : *
1659 : * @return the post-decrement reference count.
1660 : */
1661 :
1662 312773 : int GDALDataset::Dereference()
1663 : {
1664 312773 : return --nRefCount;
1665 : }
1666 :
1667 : /************************************************************************/
1668 : /* GDALDereferenceDataset() */
1669 : /************************************************************************/
1670 :
1671 : /**
1672 : * \brief Subtract one from dataset reference count.
1673 : *
1674 : * @see GDALDataset::Dereference()
1675 : */
1676 :
1677 56352 : int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)
1678 :
1679 : {
1680 56352 : VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1681 :
1682 56352 : return GDALDataset::FromHandle(hDataset)->Dereference();
1683 : }
1684 :
1685 : /************************************************************************/
1686 : /* ReleaseRef() */
1687 : /************************************************************************/
1688 :
1689 : /**
1690 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1691 : * @return TRUE if the object has been destroyed.
1692 : * @since GDAL 2.2
1693 : */
1694 :
1695 250780 : int GDALDataset::ReleaseRef()
1696 :
1697 : {
1698 250780 : if (Dereference() <= 0)
1699 : {
1700 7288 : nRefCount = 1;
1701 7288 : delete this;
1702 7288 : return TRUE;
1703 : }
1704 243492 : return FALSE;
1705 : }
1706 :
1707 : /************************************************************************/
1708 : /* GDALReleaseDataset() */
1709 : /************************************************************************/
1710 :
1711 : /**
1712 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1713 : *
1714 : * @see GDALDataset::ReleaseRef()
1715 : * @since GDAL 2.2
1716 : */
1717 :
1718 1461 : int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)
1719 :
1720 : {
1721 1461 : VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1722 :
1723 1461 : return GDALDataset::FromHandle(hDataset)->ReleaseRef();
1724 : }
1725 :
1726 : /************************************************************************/
1727 : /* GetShared() */
1728 : /************************************************************************/
1729 :
1730 : /**
1731 : * \brief Returns shared flag.
1732 : *
1733 : * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1734 : */
1735 :
1736 306572 : int GDALDataset::GetShared() const
1737 : {
1738 306572 : return bShared;
1739 : }
1740 :
1741 : /************************************************************************/
1742 : /* MarkAsShared() */
1743 : /************************************************************************/
1744 :
1745 : /**
1746 : * \brief Mark this dataset as available for sharing.
1747 : */
1748 :
1749 409 : void GDALDataset::MarkAsShared()
1750 :
1751 : {
1752 409 : CPLAssert(!bShared);
1753 :
1754 409 : bShared = true;
1755 409 : if (bIsInternal)
1756 14 : return;
1757 :
1758 395 : GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1759 :
1760 : // Insert the dataset in the set of shared opened datasets.
1761 790 : CPLMutexHolderD(&hDLMutex);
1762 395 : if (phSharedDatasetSet == nullptr)
1763 267 : phSharedDatasetSet =
1764 267 : CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1765 : GDALSharedDatasetFreeFunc);
1766 :
1767 : SharedDatasetCtxt *psStruct =
1768 395 : static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1769 395 : psStruct->poDS = this;
1770 395 : psStruct->nPID = nPID;
1771 395 : psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
1772 395 : psStruct->pszDescription = CPLStrdup(GetDescription());
1773 : std::string osConcatenatedOpenOptions =
1774 790 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
1775 395 : psStruct->pszConcatenatedOpenOptions =
1776 395 : CPLStrdup(osConcatenatedOpenOptions.c_str());
1777 395 : if (CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
1778 : {
1779 1 : GDALSharedDatasetFreeFunc(psStruct);
1780 1 : ReportError(CE_Failure, CPLE_AppDefined,
1781 : "An existing shared dataset already has this description. "
1782 : "This should not happen.");
1783 : }
1784 : else
1785 : {
1786 394 : CPLHashSetInsert(phSharedDatasetSet, psStruct);
1787 :
1788 394 : (*poAllDatasetMap)[this] = nPID;
1789 : }
1790 : }
1791 :
1792 : /************************************************************************/
1793 : /* MarkSuppressOnClose() */
1794 : /************************************************************************/
1795 :
1796 : /** Set that the dataset must be deleted on close.
1797 : *
1798 : * This is the same as C function GDALDatasetMarkSuppressOnClose()
1799 : */
1800 1169 : void GDALDataset::MarkSuppressOnClose()
1801 : {
1802 1169 : bSuppressOnClose = true;
1803 1169 : }
1804 :
1805 : /************************************************************************/
1806 : /* GDALDatasetMarkSuppressOnClose() */
1807 : /************************************************************************/
1808 :
1809 : /** Set that the dataset must be deleted on close.
1810 : *
1811 : * This is the same as C++ method GDALDataset::MarkSuppressOnClose()
1812 : *
1813 : * @since GDAL 3.12
1814 : */
1815 :
1816 4 : void GDALDatasetMarkSuppressOnClose(GDALDatasetH hDS)
1817 : {
1818 4 : VALIDATE_POINTER0(hDS, "GDALDatasetMarkSuppressOnClose");
1819 :
1820 4 : return GDALDataset::FromHandle(hDS)->MarkSuppressOnClose();
1821 : }
1822 :
1823 : /************************************************************************/
1824 : /* UnMarkSuppressOnClose() */
1825 : /************************************************************************/
1826 :
1827 : /** Remove the flag requesting the dataset to be deleted on close. */
1828 1 : void GDALDataset::UnMarkSuppressOnClose()
1829 : {
1830 1 : bSuppressOnClose = false;
1831 1 : }
1832 :
1833 : /************************************************************************/
1834 : /* CleanupPostFileClosing() */
1835 : /************************************************************************/
1836 :
1837 : /** This method should be called by driver implementations in their destructor,
1838 : * after having closed all files, but before having freed resources that
1839 : * are needed for their GetFileList() implementation.
1840 : * This is used to implement MarkSuppressOnClose behavior.
1841 : */
1842 259 : void GDALDataset::CleanupPostFileClosing()
1843 : {
1844 259 : if (IsMarkedSuppressOnClose())
1845 : {
1846 1 : char **papszFileList = GetFileList();
1847 3 : for (int i = 0; papszFileList && papszFileList[i]; ++i)
1848 2 : VSIUnlink(papszFileList[i]);
1849 1 : CSLDestroy(papszFileList);
1850 : }
1851 259 : }
1852 :
1853 : /************************************************************************/
1854 : /* GetGCPCount() */
1855 : /************************************************************************/
1856 :
1857 : /**
1858 : * \brief Get number of GCPs.
1859 : *
1860 : * This method is the same as the C function GDALGetGCPCount().
1861 : *
1862 : * @return number of GCPs for this dataset. Zero if there are none.
1863 : */
1864 :
1865 16052 : int GDALDataset::GetGCPCount()
1866 : {
1867 16052 : return 0;
1868 : }
1869 :
1870 : /************************************************************************/
1871 : /* GDALGetGCPCount() */
1872 : /************************************************************************/
1873 :
1874 : /**
1875 : * \brief Get number of GCPs.
1876 : *
1877 : * @see GDALDataset::GetGCPCount()
1878 : */
1879 :
1880 2097 : int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)
1881 :
1882 : {
1883 2097 : VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
1884 :
1885 2097 : return GDALDataset::FromHandle(hDS)->GetGCPCount();
1886 : }
1887 :
1888 : /************************************************************************/
1889 : /* GetGCPProjection() */
1890 : /************************************************************************/
1891 :
1892 : /**
1893 : * \brief Get output projection for GCPs.
1894 : *
1895 : * This method is the same as the C function GDALGetGCPProjection().
1896 : *
1897 : * The projection string follows the normal rules from GetProjectionRef().
1898 : *
1899 : * \note Starting with GDAL 3.0, this is a compatibility layer around
1900 : * GetGCPSpatialRef()
1901 : *
1902 : * @return internal projection string or "" if there are no GCPs.
1903 : * It should not be altered, freed or expected to last for long.
1904 : */
1905 :
1906 874 : const char *GDALDataset::GetGCPProjection()
1907 : {
1908 874 : const auto poSRS = GetGCPSpatialRef();
1909 874 : if (!poSRS || !m_poPrivate)
1910 : {
1911 537 : return "";
1912 : }
1913 337 : char *pszWKT = nullptr;
1914 337 : poSRS->exportToWkt(&pszWKT);
1915 337 : if (!pszWKT)
1916 : {
1917 0 : return "";
1918 : }
1919 :
1920 : // If called on a thread-safe dataset, we might be called by several
1921 : // threads, so make sure our accesses to m_pszWKTCached are protected
1922 : // by a mutex.
1923 674 : std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1924 337 : if (m_poPrivate->m_pszWKTGCPCached &&
1925 256 : strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0)
1926 : {
1927 256 : CPLFree(pszWKT);
1928 256 : return m_poPrivate->m_pszWKTGCPCached;
1929 : }
1930 81 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
1931 81 : m_poPrivate->m_pszWKTGCPCached = pszWKT;
1932 81 : return m_poPrivate->m_pszWKTGCPCached;
1933 : }
1934 :
1935 : /************************************************************************/
1936 : /* GetGCPSpatialRef() */
1937 : /************************************************************************/
1938 :
1939 : /**
1940 : * \brief Get output spatial reference system for GCPs.
1941 : *
1942 : * Same as the C function GDALGetGCPSpatialRef().
1943 : *
1944 : * When a SRS is not available, null is returned. If used on
1945 : * a dataset where there is a geotransform, and not GCPs, this method returns
1946 : * null. Use GetSpatialRef() instead.
1947 : *
1948 : * @since GDAL 3.0
1949 : *
1950 : * @return a pointer to an internal object. It should not be altered or freed.
1951 : * Its lifetime will be the one of the dataset object, or until the next
1952 : * call to this method.
1953 : */
1954 :
1955 39 : const OGRSpatialReference *GDALDataset::GetGCPSpatialRef() const
1956 : {
1957 39 : return nullptr;
1958 : }
1959 :
1960 : /************************************************************************/
1961 : /* GDALGetGCPSpatialRef() */
1962 : /************************************************************************/
1963 :
1964 : /**
1965 : * \brief Get output spatial reference system for GCPs.
1966 : *
1967 : * @since GDAL 3.0
1968 : *
1969 : * @see GDALDataset::GetGCPSpatialRef()
1970 : */
1971 :
1972 468 : OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)
1973 :
1974 : {
1975 468 : VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
1976 :
1977 468 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1978 468 : GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
1979 : }
1980 :
1981 : /************************************************************************/
1982 : /* GDALGetGCPProjection() */
1983 : /************************************************************************/
1984 :
1985 : /**
1986 : * \brief Get output projection for GCPs.
1987 : *
1988 : * @see GDALDataset::GetGCPProjection()
1989 : */
1990 :
1991 803 : const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)
1992 :
1993 : {
1994 803 : VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
1995 :
1996 803 : return GDALDataset::FromHandle(hDS)->GetGCPProjection();
1997 : }
1998 :
1999 : /************************************************************************/
2000 : /* GetGCPs() */
2001 : /************************************************************************/
2002 :
2003 : /**
2004 : * \brief Fetch GCPs.
2005 : *
2006 : * This method is the same as the C function GDALGetGCPs().
2007 : *
2008 : * @return pointer to internal GCP structure list. It should not be modified,
2009 : * and may change on the next GDAL call.
2010 : */
2011 :
2012 10 : const GDAL_GCP *GDALDataset::GetGCPs()
2013 : {
2014 10 : return nullptr;
2015 : }
2016 :
2017 : /************************************************************************/
2018 : /* GDALGetGCPs() */
2019 : /************************************************************************/
2020 :
2021 : /**
2022 : * \brief Fetch GCPs.
2023 : *
2024 : * @see GDALDataset::GetGCPs()
2025 : */
2026 :
2027 580 : const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)
2028 :
2029 : {
2030 580 : VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
2031 :
2032 580 : return GDALDataset::FromHandle(hDS)->GetGCPs();
2033 : }
2034 :
2035 : /************************************************************************/
2036 : /* SetGCPs() */
2037 : /************************************************************************/
2038 :
2039 : /**
2040 : * \brief Assign GCPs.
2041 : *
2042 : * This method is the same as the C function GDALSetGCPs().
2043 : *
2044 : * This method assigns the passed set of GCPs to this dataset, as well as
2045 : * setting their coordinate system. Internally copies are made of the
2046 : * coordinate system and list of points, so the caller remains responsible for
2047 : * deallocating these arguments if appropriate.
2048 : *
2049 : * Most formats do not support setting of GCPs, even formats that can
2050 : * handle GCPs. These formats will return CE_Failure.
2051 : *
2052 : * \note Startig with GDAL 3.0, this is a compatibility layer around
2053 : * SetGCPs(int, const GDAL_GCP*, const char*)
2054 : *
2055 : * @param nGCPCount number of GCPs being assigned.
2056 : *
2057 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2058 : *
2059 : * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
2060 : * GCP output coordinates. This parameter should be "" if no output coordinate
2061 : * system is known.
2062 : *
2063 : * @return CE_None on success, CE_Failure on failure (including if action is
2064 : * not supported for this format).
2065 : */
2066 :
2067 53 : CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,
2068 : const char *pszGCPProjection)
2069 :
2070 : {
2071 53 : if (pszGCPProjection && pszGCPProjection[0] != '\0')
2072 : {
2073 68 : OGRSpatialReference oSRS;
2074 34 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
2075 34 : if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)
2076 : {
2077 0 : return CE_Failure;
2078 : }
2079 34 : return SetGCPs(nGCPCount, pasGCPList, &oSRS);
2080 : }
2081 : else
2082 : {
2083 19 : return SetGCPs(nGCPCount, pasGCPList,
2084 19 : static_cast<const OGRSpatialReference *>(nullptr));
2085 : }
2086 : }
2087 :
2088 : /************************************************************************/
2089 : /* SetGCPs() */
2090 : /************************************************************************/
2091 :
2092 : /**
2093 : * \brief Assign GCPs.
2094 : *
2095 : * This method is the same as the C function GDALSetGCPs().
2096 : *
2097 : * This method assigns the passed set of GCPs to this dataset, as well as
2098 : * setting their coordinate system. Internally copies are made of the
2099 : * coordinate system and list of points, so the caller remains responsible for
2100 : * deallocating these arguments if appropriate.
2101 : *
2102 : * Most formats do not support setting of GCPs, even formats that can
2103 : * handle GCPs. These formats will return CE_Failure.
2104 : *
2105 : * @since GDAL 3.0
2106 : *
2107 : * @param nGCPCount number of GCPs being assigned.
2108 : *
2109 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2110 : *
2111 : * @param poGCP_SRS the new coordinate reference system to assign for the
2112 : * GCP output coordinates. This parameter should be null if no output
2113 : * coordinate system is known.
2114 : *
2115 : * @return CE_None on success, CE_Failure on failure (including if action is
2116 : * not supported for this format).
2117 : */
2118 :
2119 1 : CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,
2120 : CPL_UNUSED const GDAL_GCP *pasGCPList,
2121 : CPL_UNUSED const OGRSpatialReference *poGCP_SRS)
2122 :
2123 : {
2124 1 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
2125 1 : ReportError(CE_Failure, CPLE_NotSupported,
2126 : "Dataset does not support the SetGCPs() method.");
2127 :
2128 1 : return CE_Failure;
2129 : }
2130 :
2131 : /************************************************************************/
2132 : /* GDALSetGCPs() */
2133 : /************************************************************************/
2134 :
2135 : /**
2136 : * \brief Assign GCPs.
2137 : *
2138 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
2139 : */
2140 :
2141 30 : CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,
2142 : const GDAL_GCP *pasGCPList,
2143 : const char *pszGCPProjection)
2144 :
2145 : {
2146 30 : VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
2147 :
2148 30 : return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,
2149 30 : pszGCPProjection);
2150 : }
2151 :
2152 : /************************************************************************/
2153 : /* GDALSetGCPs2() */
2154 : /************************************************************************/
2155 :
2156 : /**
2157 : * \brief Assign GCPs.
2158 : *
2159 : * @since GDAL 3.0
2160 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
2161 : */
2162 :
2163 9 : CPLErr GDALSetGCPs2(GDALDatasetH hDS, int nGCPCount, const GDAL_GCP *pasGCPList,
2164 : OGRSpatialReferenceH hSRS)
2165 :
2166 : {
2167 9 : VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
2168 :
2169 18 : return GDALDataset::FromHandle(hDS)->SetGCPs(
2170 9 : nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
2171 : }
2172 :
2173 : /************************************************************************/
2174 : /* BuildOverviews() */
2175 : /************************************************************************/
2176 :
2177 : /**
2178 : * \brief Build raster overview(s)
2179 : *
2180 : * If the operation is not supported for the indicated dataset, then
2181 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
2182 : * CPLE_NotSupported.
2183 : *
2184 : * Depending on the actual file format, all overviews level can be also
2185 : * deleted by specifying nOverviews == 0. This works at least for external
2186 : * overviews (.ovr), TIFF internal overviews, etc.
2187 : *
2188 : * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
2189 : * to "ALL_CPUS" or a integer value to specify the number of threads to use for
2190 : * overview computation.
2191 : *
2192 : * This method is the same as the C function GDALBuildOverviewsEx().
2193 : *
2194 : * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
2195 : * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
2196 : * or "NONE" controlling the downsampling method applied.
2197 : * @param nOverviews number of overviews to build, or 0 to clean overviews.
2198 : * @param panOverviewList the list of overview decimation factors (positive
2199 : * integers, normally larger or equal to 2) to build, or
2200 : * NULL if nOverviews == 0.
2201 : * @param nListBands number of bands to build overviews for in panBandList.
2202 : * Build for all bands if this is 0.
2203 : * @param panBandList list of band numbers.
2204 : * @param pfnProgress a function to call to report progress, or NULL.
2205 : * @param pProgressData application data to pass to the progress function.
2206 : * @param papszOptions (GDAL >= 3.6) NULL terminated list of options as
2207 : * key=value pairs, or NULL
2208 : *
2209 : * @return CE_None on success or CE_Failure if the operation doesn't work.
2210 : *
2211 : * For example, to build overview level 2, 4 and 8 on all bands the following
2212 : * call could be made:
2213 : * \code{.cpp}
2214 : * int anOverviewList[3] = { 2, 4, 8 };
2215 : *
2216 : * poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
2217 : * GDALDummyProgress, nullptr );
2218 : * \endcode
2219 : *
2220 : * @see GDALRegenerateOverviewsEx()
2221 : */
2222 :
2223 727 : CPLErr GDALDataset::BuildOverviews(const char *pszResampling, int nOverviews,
2224 : const int *panOverviewList, int nListBands,
2225 : const int *panBandList,
2226 : GDALProgressFunc pfnProgress,
2227 : void *pProgressData,
2228 : CSLConstList papszOptions)
2229 : {
2230 727 : int *panAllBandList = nullptr;
2231 :
2232 727 : if (nListBands == 0)
2233 : {
2234 716 : nListBands = GetRasterCount();
2235 : panAllBandList =
2236 716 : static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
2237 67427 : for (int i = 0; i < nListBands; ++i)
2238 66711 : panAllBandList[i] = i + 1;
2239 :
2240 716 : panBandList = panAllBandList;
2241 : }
2242 :
2243 727 : if (pfnProgress == nullptr)
2244 693 : pfnProgress = GDALDummyProgress;
2245 :
2246 1785 : for (int i = 0; i < nOverviews; ++i)
2247 : {
2248 1059 : if (panOverviewList[i] <= 0)
2249 : {
2250 1 : CPLError(CE_Failure, CPLE_IllegalArg,
2251 : "panOverviewList[%d] = %d is invalid. It must be a "
2252 : "positive value",
2253 1 : i, panOverviewList[i]);
2254 1 : CPLFree(panAllBandList);
2255 1 : return CE_Failure;
2256 : }
2257 : }
2258 :
2259 : // At time of writing, all overview generation options are actually
2260 : // expected to be passed as configuration options.
2261 726 : std::vector<std::unique_ptr<CPLConfigOptionSetter>> apoConfigOptionSetter;
2262 760 : for (const auto &[pszKey, pszValue] : cpl::IterateNameValue(papszOptions))
2263 : {
2264 : apoConfigOptionSetter.emplace_back(
2265 34 : std::make_unique<CPLConfigOptionSetter>(pszKey, pszValue, false));
2266 : }
2267 :
2268 : const CPLErr eErr =
2269 1452 : IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
2270 726 : panBandList, pfnProgress, pProgressData, papszOptions);
2271 :
2272 726 : if (panAllBandList != nullptr)
2273 714 : CPLFree(panAllBandList);
2274 :
2275 726 : return eErr;
2276 : }
2277 :
2278 : /************************************************************************/
2279 : /* GDALBuildOverviews() */
2280 : /************************************************************************/
2281 :
2282 : /**
2283 : * \brief Build raster overview(s)
2284 : *
2285 : * @see GDALDataset::BuildOverviews() and GDALBuildOverviews()
2286 : */
2287 :
2288 35 : CPLErr CPL_STDCALL GDALBuildOverviews(GDALDatasetH hDataset,
2289 : const char *pszResampling, int nOverviews,
2290 : const int *panOverviewList,
2291 : int nListBands, const int *panBandList,
2292 : GDALProgressFunc pfnProgress,
2293 : void *pProgressData)
2294 :
2295 : {
2296 35 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2297 :
2298 35 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2299 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2300 35 : pfnProgress, pProgressData, nullptr);
2301 : }
2302 :
2303 : /************************************************************************/
2304 : /* GDALBuildOverviews() */
2305 : /************************************************************************/
2306 :
2307 : /**
2308 : * \brief Build raster overview(s)
2309 : *
2310 : * @see GDALDataset::BuildOverviews()
2311 : * @since GDAL 3.6
2312 : */
2313 :
2314 : CPLErr CPL_STDCALL
2315 672 : GDALBuildOverviewsEx(GDALDatasetH hDataset, const char *pszResampling,
2316 : int nOverviews, const int *panOverviewList, int nListBands,
2317 : const int *panBandList, GDALProgressFunc pfnProgress,
2318 : void *pProgressData, CSLConstList papszOptions)
2319 :
2320 : {
2321 672 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2322 :
2323 672 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2324 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2325 672 : pfnProgress, pProgressData, papszOptions);
2326 : }
2327 :
2328 : /************************************************************************/
2329 : /* IBuildOverviews() */
2330 : /* */
2331 : /* Default implementation. */
2332 : /************************************************************************/
2333 :
2334 : //! @cond Doxygen_Suppress
2335 195 : CPLErr GDALDataset::IBuildOverviews(const char *pszResampling, int nOverviews,
2336 : const int *panOverviewList, int nListBands,
2337 : const int *panBandList,
2338 : GDALProgressFunc pfnProgress,
2339 : void *pProgressData,
2340 : CSLConstList papszOptions)
2341 :
2342 : {
2343 195 : if (oOvManager.IsInitialized())
2344 194 : return oOvManager.BuildOverviews(
2345 : nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2346 194 : panBandList, pfnProgress, pProgressData, papszOptions);
2347 : else
2348 : {
2349 1 : ReportError(CE_Failure, CPLE_NotSupported,
2350 : "BuildOverviews() not supported for this dataset.");
2351 :
2352 1 : return CE_Failure;
2353 : }
2354 : }
2355 :
2356 : //! @endcond
2357 :
2358 : /************************************************************************/
2359 : /* AddOverviews() */
2360 : /* */
2361 : /* Default implementation. */
2362 : /************************************************************************/
2363 :
2364 : /**
2365 : * \brief Add overview from existing dataset(s)
2366 : *
2367 : * This function creates new overview levels or refresh existing one from
2368 : * the list of provided overview datasets.
2369 : * Source overviews may come from any GDAL supported format, provided they
2370 : * have the same number of bands and geospatial extent than the target
2371 : * dataset.
2372 : *
2373 : * If the operation is not supported for the indicated dataset, then
2374 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
2375 : * CPLE_NotSupported.
2376 : *
2377 : * At time of writing, this method is only implemented for internal overviews
2378 : * of GeoTIFF datasets and external overviews in GeoTIFF format.
2379 : *
2380 : * @param apoSrcOvrDS Vector of source overviews.
2381 : * @param pfnProgress a function to call to report progress, or NULL.
2382 : * @param pProgressData application data to pass to the progress function.
2383 : * @param papszOptions NULL terminated list of options as
2384 : * key=value pairs, or NULL. None currently
2385 : *
2386 : * @return CE_None on success or CE_Failure if the operation doesn't work.
2387 : * @since 3.12
2388 : */
2389 5 : CPLErr GDALDataset::AddOverviews(const std::vector<GDALDataset *> &apoSrcOvrDS,
2390 : GDALProgressFunc pfnProgress,
2391 : void *pProgressData, CSLConstList papszOptions)
2392 : {
2393 5 : if (oOvManager.IsInitialized())
2394 : {
2395 4 : return oOvManager.AddOverviews(nullptr, apoSrcOvrDS, pfnProgress,
2396 4 : pProgressData, papszOptions);
2397 : }
2398 : else
2399 : {
2400 1 : ReportError(CE_Failure, CPLE_NotSupported,
2401 : "AddOverviews() not supported for this dataset.");
2402 1 : return CE_Failure;
2403 : }
2404 : }
2405 :
2406 : /************************************************************************/
2407 : /* IRasterIO() */
2408 : /* */
2409 : /* The default implementation of IRasterIO() is, in the general */
2410 : /* case to pass the request off to each band objects rasterio */
2411 : /* methods with appropriate arguments. In some cases, it might */
2412 : /* choose instead the BlockBasedRasterIO() implementation. */
2413 : /************************************************************************/
2414 :
2415 : //! @cond Doxygen_Suppress
2416 444586 : CPLErr GDALDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2417 : int nXSize, int nYSize, void *pData,
2418 : int nBufXSize, int nBufYSize,
2419 : GDALDataType eBufType, int nBandCount,
2420 : BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,
2421 : GSpacing nLineSpace, GSpacing nBandSpace,
2422 : GDALRasterIOExtraArg *psExtraArg)
2423 :
2424 : {
2425 444586 : const char *pszInterleave = nullptr;
2426 :
2427 444586 : CPLAssert(nullptr != pData);
2428 :
2429 444586 : const bool bHasSubpixelShift =
2430 446721 : psExtraArg->bFloatingPointWindowValidity &&
2431 445337 : psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2432 751 : (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2433 :
2434 444471 : if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&
2435 70303 : nBandCount > 1 &&
2436 70303 : (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2437 889057 : nullptr &&
2438 67233 : EQUAL(pszInterleave, "PIXEL"))
2439 : {
2440 63975 : return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2441 : nBufXSize, nBufYSize, eBufType, nBandCount,
2442 : panBandMap, nPixelSpace, nLineSpace,
2443 63976 : nBandSpace, psExtraArg);
2444 : }
2445 :
2446 380610 : if (eRWFlag == GF_Read &&
2447 201184 : (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2448 200439 : psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2449 200438 : psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2450 201184 : psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2451 908 : !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)
2452 : {
2453 887 : if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())
2454 : {
2455 677 : int bTried = FALSE;
2456 677 : const CPLErr eErr = TryOverviewRasterIO(
2457 : eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
2458 : nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
2459 : nLineSpace, nBandSpace, psExtraArg, &bTried);
2460 677 : if (bTried)
2461 1 : return eErr;
2462 : }
2463 :
2464 886 : GDALDataType eFirstBandDT = GDT_Unknown;
2465 886 : int nFirstMaskFlags = 0;
2466 886 : GDALRasterBand *poFirstMaskBand = nullptr;
2467 886 : int nOKBands = 0;
2468 :
2469 : // Check if bands share the same mask band
2470 2749 : for (int i = 0; i < nBandCount; ++i)
2471 : {
2472 2482 : GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2473 4291 : if ((nBufXSize < nXSize || nBufYSize < nYSize) &&
2474 1812 : poBand->GetOverviewCount())
2475 : {
2476 : // Could be improved to select the appropriate overview.
2477 3 : break;
2478 : }
2479 2476 : if (poBand->GetColorTable() != nullptr)
2480 : {
2481 0 : break;
2482 : }
2483 2480 : const GDALDataType eDT = poBand->GetRasterDataType();
2484 2480 : if (GDALDataTypeIsComplex(eDT))
2485 : {
2486 30 : break;
2487 : }
2488 2448 : if (i == 0)
2489 : {
2490 853 : eFirstBandDT = eDT;
2491 853 : nFirstMaskFlags = poBand->GetMaskFlags();
2492 854 : if (nFirstMaskFlags == GMF_NODATA)
2493 : {
2494 : // The dataset-level resampling code is not ready for nodata
2495 : // Fallback to band-level resampling
2496 10 : break;
2497 : }
2498 844 : poFirstMaskBand = poBand->GetMaskBand();
2499 : }
2500 : else
2501 : {
2502 1595 : if (eDT != eFirstBandDT)
2503 : {
2504 0 : break;
2505 : }
2506 1595 : int nMaskFlags = poBand->GetMaskFlags();
2507 1594 : if (nMaskFlags == GMF_NODATA)
2508 : {
2509 : // The dataset-level resampling code is not ready for nodata
2510 : // Fallback to band-level resampling
2511 0 : break;
2512 : }
2513 1594 : GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2514 1593 : if (nFirstMaskFlags == GMF_ALL_VALID &&
2515 : nMaskFlags == GMF_ALL_VALID)
2516 : {
2517 : // Ok.
2518 : }
2519 949 : else if (poFirstMaskBand == poMaskBand)
2520 : {
2521 : // Ok.
2522 : }
2523 : else
2524 : {
2525 573 : break;
2526 : }
2527 : }
2528 :
2529 1863 : ++nOKBands;
2530 : }
2531 :
2532 883 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2533 883 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2534 :
2535 883 : CPLErr eErr = CE_None;
2536 883 : if (nOKBands > 0)
2537 : {
2538 842 : if (nOKBands < nBandCount)
2539 : {
2540 573 : psExtraArg->pfnProgress = GDALScaledProgress;
2541 1147 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2542 573 : 0.0, static_cast<double>(nOKBands) / nBandCount,
2543 : pfnProgressGlobal, pProgressDataGlobal);
2544 574 : if (psExtraArg->pProgressData == nullptr)
2545 185 : psExtraArg->pfnProgress = nullptr;
2546 : }
2547 :
2548 843 : eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2549 : pData, nBufXSize, nBufYSize, eBufType,
2550 : nOKBands, panBandMap, nPixelSpace,
2551 : nLineSpace, nBandSpace, psExtraArg);
2552 :
2553 844 : if (nOKBands < nBandCount)
2554 : {
2555 575 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2556 : }
2557 : }
2558 885 : if (eErr == CE_None && nOKBands < nBandCount)
2559 : {
2560 615 : if (nOKBands > 0)
2561 : {
2562 572 : psExtraArg->pfnProgress = GDALScaledProgress;
2563 1144 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2564 572 : static_cast<double>(nOKBands) / nBandCount, 1.0,
2565 : pfnProgressGlobal, pProgressDataGlobal);
2566 572 : if (psExtraArg->pProgressData == nullptr)
2567 183 : psExtraArg->pfnProgress = nullptr;
2568 : }
2569 1230 : eErr = BandBasedRasterIO(
2570 : eRWFlag, nXOff, nYOff, nXSize, nYSize,
2571 615 : static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,
2572 : nBufYSize, eBufType, nBandCount - nOKBands,
2573 615 : panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,
2574 : psExtraArg);
2575 615 : if (nOKBands > 0)
2576 : {
2577 572 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2578 : }
2579 : }
2580 :
2581 887 : psExtraArg->pfnProgress = pfnProgressGlobal;
2582 887 : psExtraArg->pProgressData = pProgressDataGlobal;
2583 :
2584 887 : return eErr;
2585 : }
2586 :
2587 379723 : return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2588 : nBufXSize, nBufYSize, eBufType, nBandCount,
2589 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2590 379723 : psExtraArg);
2591 : }
2592 :
2593 : //! @endcond
2594 :
2595 : /************************************************************************/
2596 : /* BandBasedRasterIO() */
2597 : /* */
2598 : /* Pass the request off to each band objects rasterio methods with */
2599 : /* appropriate arguments. */
2600 : /************************************************************************/
2601 :
2602 : //! @cond Doxygen_Suppress
2603 685373 : CPLErr GDALDataset::BandBasedRasterIO(
2604 : GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
2605 : void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
2606 : int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
2607 : GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
2608 :
2609 : {
2610 : int iBandIndex;
2611 685373 : CPLErr eErr = CE_None;
2612 :
2613 685373 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2614 685373 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2615 :
2616 1738950 : for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
2617 : ++iBandIndex)
2618 : {
2619 1053570 : GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2620 :
2621 1053570 : if (poBand == nullptr)
2622 : {
2623 0 : eErr = CE_Failure;
2624 0 : break;
2625 : }
2626 :
2627 1053570 : GByte *pabyBandData =
2628 1053570 : static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2629 :
2630 1053570 : if (nBandCount > 1)
2631 : {
2632 543467 : psExtraArg->pfnProgress = GDALScaledProgress;
2633 1086930 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2634 : 1.0 * iBandIndex / nBandCount,
2635 543467 : 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2636 : pProgressDataGlobal);
2637 543460 : if (psExtraArg->pProgressData == nullptr)
2638 540687 : psExtraArg->pfnProgress = nullptr;
2639 : }
2640 :
2641 2107140 : eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2642 : pabyBandData, nBufXSize, nBufYSize, eBufType,
2643 1053560 : nPixelSpace, nLineSpace, psExtraArg);
2644 :
2645 1053580 : if (nBandCount > 1)
2646 543473 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2647 : }
2648 :
2649 685381 : psExtraArg->pfnProgress = pfnProgressGlobal;
2650 685381 : psExtraArg->pProgressData = pProgressDataGlobal;
2651 :
2652 685381 : return eErr;
2653 : }
2654 :
2655 : //! @endcond
2656 :
2657 : /************************************************************************/
2658 : /* ValidateRasterIOOrAdviseReadParameters() */
2659 : /************************************************************************/
2660 :
2661 : //! @cond Doxygen_Suppress
2662 782723 : CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
2663 : const char *pszCallingFunc, int *pbStopProcessingOnCENone, int nXOff,
2664 : int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize,
2665 : int nBandCount, const int *panBandMap)
2666 : {
2667 :
2668 : /* -------------------------------------------------------------------- */
2669 : /* Some size values are "noop". Lets just return to avoid */
2670 : /* stressing lower level functions. */
2671 : /* -------------------------------------------------------------------- */
2672 782723 : if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)
2673 : {
2674 25 : CPLDebug("GDAL",
2675 : "%s skipped for odd window or buffer size.\n"
2676 : " Window = (%d,%d)x%dx%d\n"
2677 : " Buffer = %dx%d",
2678 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2679 : nBufYSize);
2680 :
2681 24 : *pbStopProcessingOnCENone = TRUE;
2682 24 : return CE_None;
2683 : }
2684 :
2685 782698 : CPLErr eErr = CE_None;
2686 782698 : *pbStopProcessingOnCENone = FALSE;
2687 :
2688 782698 : if (nXOff < 0 || nXOff > INT_MAX - nXSize ||
2689 782695 : nXOff + nXSize > nRasterXSize || nYOff < 0 ||
2690 782695 : nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)
2691 : {
2692 3 : ReportError(CE_Failure, CPLE_IllegalArg,
2693 : "Access window out of range in %s. Requested "
2694 : "(%d,%d) of size %dx%d on raster of %dx%d.",
2695 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
2696 : nRasterYSize);
2697 2 : eErr = CE_Failure;
2698 : }
2699 :
2700 782697 : if (panBandMap == nullptr && nBandCount > GetRasterCount())
2701 : {
2702 0 : ReportError(CE_Failure, CPLE_IllegalArg,
2703 : "%s: nBandCount cannot be greater than %d", pszCallingFunc,
2704 : GetRasterCount());
2705 0 : eErr = CE_Failure;
2706 : }
2707 :
2708 2295100 : for (int i = 0; i < nBandCount && eErr == CE_None; ++i)
2709 : {
2710 1512410 : int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2711 1512410 : if (iBand < 1 || iBand > GetRasterCount())
2712 : {
2713 3 : ReportError(
2714 : CE_Failure, CPLE_IllegalArg,
2715 : "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
2716 : pszCallingFunc, i, iBand);
2717 3 : eErr = CE_Failure;
2718 : }
2719 :
2720 1512410 : if (eErr == CE_None && GetRasterBand(iBand) == nullptr)
2721 : {
2722 0 : ReportError(
2723 : CE_Failure, CPLE_IllegalArg,
2724 : "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
2725 : pszCallingFunc, i, iBand);
2726 0 : eErr = CE_Failure;
2727 : }
2728 : }
2729 :
2730 782696 : return eErr;
2731 : }
2732 :
2733 : //! @endcond
2734 :
2735 : /************************************************************************/
2736 : /* RasterIO() */
2737 : /************************************************************************/
2738 :
2739 : /**
2740 : * \brief Read/write a region of image data from multiple bands.
2741 : *
2742 : * This method allows reading a region of one or more GDALRasterBands from
2743 : * this dataset into a buffer, or writing data from a buffer into a region
2744 : * of the GDALRasterBands. It automatically takes care of data type
2745 : * translation if the data type (eBufType) of the buffer is different than
2746 : * that of the GDALRasterBand.
2747 : * The method also takes care of image decimation / replication if the
2748 : * buffer size (nBufXSize x nBufYSize) is different than the size of the
2749 : * region being accessed (nXSize x nYSize).
2750 : *
2751 : * The window of interest expressed by (nXOff, nYOff, nXSize, nYSize) should be
2752 : * fully within the raster space, that is nXOff >= 0, nYOff >= 0,
2753 : * nXOff + nXSize <= GetRasterXSize() and nYOff + nYSize <= GetRasterYSize().
2754 : * If reads larger than the raster space are wished, GDALTranslate() might be used.
2755 : * Or use nLineSpace and a possibly shifted pData value.
2756 : *
2757 : * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
2758 : * writing from various organization of buffers.
2759 : *
2760 : * Some formats may efficiently implement decimation into a buffer by
2761 : * reading from lower resolution overview images. The logic of the default
2762 : * implementation in the base class GDALRasterBand is the following one. It
2763 : * computes a target_downscaling_factor from the window of interest and buffer
2764 : * size which is min(nXSize/nBufXSize, nYSize/nBufYSize).
2765 : * It then walks through overviews and will select the first one whose
2766 : * downscaling factor is greater than target_downscaling_factor / 1.2.
2767 : *
2768 : * Let's assume we have overviews at downscaling factors 2, 4 and 8.
2769 : * The relationship between target_downscaling_factor and the select overview
2770 : * level is the following one:
2771 : *
2772 : * target_downscaling_factor | selected_overview
2773 : * ------------------------- | -----------------
2774 : * ]0, 2 / 1.2] | full resolution band
2775 : * ]2 / 1.2, 4 / 1.2] | 2x downsampled band
2776 : * ]4 / 1.2, 8 / 1.2] | 4x downsampled band
2777 : * ]8 / 1.2, infinity[ | 8x downsampled band
2778 : *
2779 : * Note that starting with GDAL 3.9, this 1.2 oversampling factor can be
2780 : * modified by setting the GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD configuration
2781 : * option. Also note that starting with GDAL 3.9, when the resampling algorithm
2782 : * specified in psExtraArg->eResampleAlg is different from GRIORA_NearestNeighbour,
2783 : * this oversampling threshold defaults to 1. Consequently if there are overviews
2784 : * of downscaling factor 2, 4 and 8, and the desired downscaling factor is
2785 : * 7.99, the overview of factor 4 will be selected for a non nearest resampling.
2786 : *
2787 : * For highest performance full resolution data access, read and write
2788 : * on "block boundaries" as returned by GetBlockSize(), or use the
2789 : * ReadBlock() and WriteBlock() methods.
2790 : *
2791 : * This method is the same as the C GDALDatasetRasterIO() or
2792 : * GDALDatasetRasterIOEx() functions.
2793 : *
2794 : * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
2795 : * write a region of data.
2796 : *
2797 : * @param nXOff The pixel offset to the top left corner of the region
2798 : * of the band to be accessed. This would be zero to start from the left side.
2799 : *
2800 : * @param nYOff The line offset to the top left corner of the region
2801 : * of the band to be accessed. This would be zero to start from the top.
2802 : *
2803 : * @param nXSize The width of the region of the band to be accessed in pixels.
2804 : *
2805 : * @param nYSize The height of the region of the band to be accessed in lines.
2806 : *
2807 : * @param pData The buffer into which the data should be read, or from which
2808 : * it should be written. This buffer must contain at least
2809 : * nBufXSize * nBufYSize * nBandCount words of type eBufType. It is organized
2810 : * in left to right,top to bottom pixel order. Spacing is controlled by the
2811 : * nPixelSpace, and nLineSpace parameters.
2812 : * Note that even with eRWFlag==GF_Write, the content of the buffer might be
2813 : * temporarily modified during the execution of this method (and eventually
2814 : * restored back to its original content), so it is not safe to use a buffer
2815 : * stored in a read-only section of the calling program.
2816 : *
2817 : * @param nBufXSize the width of the buffer image into which the desired region
2818 : * is to be read, or from which it is to be written.
2819 : *
2820 : * @param nBufYSize the height of the buffer image into which the desired
2821 : * region is to be read, or from which it is to be written.
2822 : *
2823 : * @param eBufType the type of the pixel values in the pData data buffer. The
2824 : * pixel values will automatically be translated to/from the GDALRasterBand
2825 : * data type as needed. Most driver implementations will use GDALCopyWords64()
2826 : * to perform data type translation.
2827 : *
2828 : * @param nBandCount the number of bands being read or written.
2829 : *
2830 : * @param panBandMap the list of nBandCount band numbers being read/written.
2831 : * Note band numbers are 1 based. This may be NULL to select the first
2832 : * nBandCount bands. (Note: before GDAL 3.10, argument type was "int*", and
2833 : * not "const int*")
2834 : *
2835 : * @param nPixelSpace The byte offset from the start of one pixel value in
2836 : * pData to the start of the next pixel value within a scanline. If defaulted
2837 : * (0) the size of the datatype eBufType is used.
2838 : *
2839 : * @param nLineSpace The byte offset from the start of one scanline in
2840 : * pData to the start of the next. If defaulted (0) the size of the datatype
2841 : * eBufType * nBufXSize is used.
2842 : *
2843 : * @param nBandSpace the byte offset from the start of one bands data to the
2844 : * start of the next. If defaulted (0) the value will be
2845 : * nLineSpace * nBufYSize implying band sequential organization
2846 : * of the data buffer.
2847 : *
2848 : * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
2849 : * structure with additional arguments to specify resampling and progress
2850 : * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
2851 : * configuration option can also be defined to override the default resampling
2852 : * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
2853 : *
2854 : * @return CE_Failure if the access fails, otherwise CE_None.
2855 : */
2856 :
2857 767999 : CPLErr GDALDataset::RasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2858 : int nXSize, int nYSize, void *pData, int nBufXSize,
2859 : int nBufYSize, GDALDataType eBufType,
2860 : int nBandCount, const int *panBandMap,
2861 : GSpacing nPixelSpace, GSpacing nLineSpace,
2862 : GSpacing nBandSpace,
2863 : GDALRasterIOExtraArg *psExtraArg)
2864 :
2865 : {
2866 : GDALRasterIOExtraArg sExtraArg;
2867 767999 : if (psExtraArg == nullptr)
2868 : {
2869 575808 : INIT_RASTERIO_EXTRA_ARG(sExtraArg);
2870 :
2871 : // 4 below inits are not strictly needed but make Coverity Scan
2872 : // happy
2873 575808 : sExtraArg.dfXOff = nXOff;
2874 575808 : sExtraArg.dfYOff = nYOff;
2875 575808 : sExtraArg.dfXSize = nXSize;
2876 575808 : sExtraArg.dfYSize = nYSize;
2877 :
2878 575808 : psExtraArg = &sExtraArg;
2879 : }
2880 192191 : else if (CPL_UNLIKELY(psExtraArg->nVersion >
2881 : RASTERIO_EXTRA_ARG_CURRENT_VERSION))
2882 : {
2883 0 : ReportError(CE_Failure, CPLE_AppDefined,
2884 : "Unhandled version of GDALRasterIOExtraArg");
2885 0 : return CE_Failure;
2886 : }
2887 :
2888 767999 : GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
2889 : nBufYSize);
2890 :
2891 767994 : if (CPL_UNLIKELY(nullptr == pData))
2892 : {
2893 0 : ReportError(CE_Failure, CPLE_AppDefined,
2894 : "The buffer into which the data should be read is null");
2895 0 : return CE_Failure;
2896 : }
2897 :
2898 : /* -------------------------------------------------------------------- */
2899 : /* Do some validation of parameters. */
2900 : /* -------------------------------------------------------------------- */
2901 :
2902 767994 : if (CPL_UNLIKELY(eRWFlag != GF_Read && eRWFlag != GF_Write))
2903 : {
2904 0 : ReportError(
2905 : CE_Failure, CPLE_IllegalArg,
2906 : "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
2907 : eRWFlag);
2908 0 : return CE_Failure;
2909 : }
2910 :
2911 767994 : if (eRWFlag == GF_Write)
2912 : {
2913 215975 : if (CPL_UNLIKELY(eAccess != GA_Update))
2914 : {
2915 2 : ReportError(CE_Failure, CPLE_AppDefined,
2916 : "Write operation not permitted on dataset opened "
2917 : "in read-only mode");
2918 2 : return CE_Failure;
2919 : }
2920 : }
2921 :
2922 767992 : int bStopProcessing = FALSE;
2923 767992 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2924 : "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2925 : nBufYSize, nBandCount, panBandMap);
2926 767997 : if (eErr != CE_None || bStopProcessing)
2927 9 : return eErr;
2928 767988 : if (CPL_UNLIKELY(eBufType == GDT_Unknown || eBufType == GDT_TypeCount))
2929 : {
2930 2 : ReportError(CE_Failure, CPLE_AppDefined,
2931 : "Illegal GDT_Unknown/GDT_TypeCount argument");
2932 2 : return CE_Failure;
2933 : }
2934 :
2935 : /* -------------------------------------------------------------------- */
2936 : /* If pixel and line spacing are defaulted assign reasonable */
2937 : /* value assuming a packed buffer. */
2938 : /* -------------------------------------------------------------------- */
2939 767986 : if (nPixelSpace == 0)
2940 423068 : nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
2941 :
2942 767987 : if (nLineSpace == 0)
2943 : {
2944 526147 : nLineSpace = nPixelSpace * nBufXSize;
2945 : }
2946 :
2947 767987 : if (nBandSpace == 0 && nBandCount > 1)
2948 : {
2949 66639 : nBandSpace = nLineSpace * nBufYSize;
2950 : }
2951 :
2952 767987 : if (panBandMap == nullptr)
2953 : {
2954 393284 : if (!m_poPrivate)
2955 0 : return CE_Failure;
2956 393284 : CPLAssert(static_cast<int>(m_poPrivate->m_anBandMap.size()) == nBands);
2957 393284 : panBandMap = m_poPrivate->m_anBandMap.data();
2958 : }
2959 :
2960 767987 : int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
2961 :
2962 : /* -------------------------------------------------------------------- */
2963 : /* We are being forced to use cached IO instead of a driver */
2964 : /* specific implementation. */
2965 : /* -------------------------------------------------------------------- */
2966 767987 : if (bForceCachedIO)
2967 : {
2968 18 : eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2969 : nBufXSize, nBufYSize, eBufType, nBandCount,
2970 : panBandMap, nPixelSpace, nLineSpace,
2971 18 : nBandSpace, psExtraArg);
2972 : }
2973 :
2974 : /* -------------------------------------------------------------------- */
2975 : /* Call the format specific function. */
2976 : /* -------------------------------------------------------------------- */
2977 : else
2978 : {
2979 767969 : eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2980 : nBufXSize, nBufYSize, eBufType, nBandCount,
2981 : // TODO: remove this const_cast once IRasterIO()
2982 : // takes a const int*
2983 : const_cast<int *>(panBandMap), nPixelSpace, nLineSpace,
2984 767969 : nBandSpace, psExtraArg);
2985 : }
2986 :
2987 767987 : if (bCallLeaveReadWrite)
2988 407465 : LeaveReadWrite();
2989 :
2990 767987 : return eErr;
2991 : }
2992 :
2993 : /************************************************************************/
2994 : /* GDALDatasetRasterIO() */
2995 : /************************************************************************/
2996 :
2997 : /**
2998 : * \brief Read/write a region of image data from multiple bands.
2999 : *
3000 : * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
3001 : * resolution, progress callback, etc. are needed)
3002 : *
3003 : * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
3004 : *
3005 : * @see GDALDataset::RasterIO()
3006 : */
3007 :
3008 4762 : CPLErr CPL_STDCALL GDALDatasetRasterIO(GDALDatasetH hDS, GDALRWFlag eRWFlag,
3009 : int nXOff, int nYOff, int nXSize,
3010 : int nYSize, void *pData, int nBufXSize,
3011 : int nBufYSize, GDALDataType eBufType,
3012 : int nBandCount, const int *panBandMap,
3013 : int nPixelSpace, int nLineSpace,
3014 : int nBandSpace)
3015 :
3016 : {
3017 4762 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
3018 :
3019 4762 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
3020 :
3021 4762 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3022 : nBufXSize, nBufYSize, eBufType, nBandCount,
3023 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
3024 4762 : nullptr);
3025 : }
3026 :
3027 : /************************************************************************/
3028 : /* GDALDatasetRasterIOEx() */
3029 : /************************************************************************/
3030 :
3031 : /**
3032 : * \brief Read/write a region of image data from multiple bands.
3033 : *
3034 : * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
3035 : *
3036 : * @see GDALDataset::RasterIO()
3037 : * @since GDAL 2.0
3038 : */
3039 :
3040 352799 : CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
3041 : GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
3042 : int nYSize, void *pData, int nBufXSize, int nBufYSize,
3043 : GDALDataType eBufType, int nBandCount, const int *panBandMap,
3044 : GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
3045 : GDALRasterIOExtraArg *psExtraArg)
3046 :
3047 : {
3048 352799 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
3049 :
3050 352799 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
3051 :
3052 352799 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3053 : nBufXSize, nBufYSize, eBufType, nBandCount,
3054 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
3055 352799 : psExtraArg);
3056 : }
3057 :
3058 : /************************************************************************/
3059 : /* GetOpenDatasets() */
3060 : /************************************************************************/
3061 :
3062 : /**
3063 : * \brief Fetch all open GDAL dataset handles.
3064 : *
3065 : * This method is the same as the C function GDALGetOpenDatasets().
3066 : *
3067 : * NOTE: This method is not thread safe. The returned list may change
3068 : * at any time and it should not be freed.
3069 : *
3070 : * @param pnCount integer into which to place the count of dataset pointers
3071 : * being returned.
3072 : *
3073 : * @return a pointer to an array of dataset handles.
3074 : */
3075 :
3076 2260 : GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)
3077 :
3078 : {
3079 4520 : CPLMutexHolderD(&hDLMutex);
3080 :
3081 2260 : if (poAllDatasetMap == nullptr)
3082 : {
3083 2238 : *pnCount = 0;
3084 2238 : return nullptr;
3085 : }
3086 :
3087 22 : *pnCount = static_cast<int>(poAllDatasetMap->size());
3088 22 : ppDatasets = static_cast<GDALDataset **>(
3089 22 : CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
3090 22 : std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();
3091 599 : for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)
3092 577 : ppDatasets[i] = oIter->first;
3093 22 : return ppDatasets;
3094 : }
3095 :
3096 : /************************************************************************/
3097 : /* GDALGetOpenDatasets() */
3098 : /************************************************************************/
3099 :
3100 : /**
3101 : * \brief Fetch all open GDAL dataset handles.
3102 : *
3103 : * @see GDALDataset::GetOpenDatasets()
3104 : */
3105 :
3106 0 : void CPL_STDCALL GDALGetOpenDatasets(GDALDatasetH **ppahDSList, int *pnCount)
3107 :
3108 : {
3109 0 : VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
3110 0 : VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
3111 :
3112 0 : *ppahDSList =
3113 0 : reinterpret_cast<GDALDatasetH *>(GDALDataset::GetOpenDatasets(pnCount));
3114 : }
3115 :
3116 : /************************************************************************/
3117 : /* GDALCleanOpenDatasetsList() */
3118 : /************************************************************************/
3119 :
3120 : // Useful when called from the child of a fork(), to avoid closing
3121 : // the datasets of the parent at the child termination.
3122 0 : void GDALNullifyOpenDatasetsList()
3123 : {
3124 0 : poAllDatasetMap = nullptr;
3125 0 : phSharedDatasetSet = nullptr;
3126 0 : ppDatasets = nullptr;
3127 0 : hDLMutex = nullptr;
3128 0 : }
3129 :
3130 : /************************************************************************/
3131 : /* GDALGetAccess() */
3132 : /************************************************************************/
3133 :
3134 : /**
3135 : * \brief Return access flag
3136 : *
3137 : * @see GDALDataset::GetAccess()
3138 : */
3139 :
3140 0 : int CPL_STDCALL GDALGetAccess(GDALDatasetH hDS)
3141 : {
3142 0 : VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
3143 :
3144 0 : return GDALDataset::FromHandle(hDS)->GetAccess();
3145 : }
3146 :
3147 : /************************************************************************/
3148 : /* AdviseRead() */
3149 : /************************************************************************/
3150 :
3151 : /**
3152 : * \brief Advise driver of upcoming read requests.
3153 : *
3154 : * Some GDAL drivers operate more efficiently if they know in advance what
3155 : * set of upcoming read requests will be made. The AdviseRead() method allows
3156 : * an application to notify the driver of the region and bands of interest,
3157 : * and at what resolution the region will be read.
3158 : *
3159 : * Many drivers just ignore the AdviseRead() call, but it can dramatically
3160 : * accelerate access via some drivers.
3161 : *
3162 : * Depending on call paths, drivers might receive several calls to
3163 : * AdviseRead() with the same parameters.
3164 : *
3165 : * @param nXOff The pixel offset to the top left corner of the region
3166 : * of the band to be accessed. This would be zero to start from the left side.
3167 : *
3168 : * @param nYOff The line offset to the top left corner of the region
3169 : * of the band to be accessed. This would be zero to start from the top.
3170 : *
3171 : * @param nXSize The width of the region of the band to be accessed in pixels.
3172 : *
3173 : * @param nYSize The height of the region of the band to be accessed in lines.
3174 : *
3175 : * @param nBufXSize the width of the buffer image into which the desired region
3176 : * is to be read, or from which it is to be written.
3177 : *
3178 : * @param nBufYSize the height of the buffer image into which the desired
3179 : * region is to be read, or from which it is to be written.
3180 : *
3181 : * @param eBufType the type of the pixel values in the pData data buffer. The
3182 : * pixel values will automatically be translated to/from the GDALRasterBand
3183 : * data type as needed.
3184 : *
3185 : * @param nBandCount the number of bands being read or written.
3186 : *
3187 : * @param panBandMap the list of nBandCount band numbers being read/written.
3188 : * Note band numbers are 1 based. This may be NULL to select the first
3189 : * nBandCount bands.
3190 : *
3191 : * @param papszOptions a list of name=value strings with special control
3192 : * options. Normally this is NULL.
3193 : *
3194 : * @return CE_Failure if the request is invalid and CE_None if it works or
3195 : * is ignored.
3196 : */
3197 :
3198 14476 : CPLErr GDALDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
3199 : int nBufXSize, int nBufYSize,
3200 : GDALDataType eBufType, int nBandCount,
3201 : int *panBandMap, char **papszOptions)
3202 :
3203 : {
3204 : /* -------------------------------------------------------------------- */
3205 : /* Do some validation of parameters. */
3206 : /* -------------------------------------------------------------------- */
3207 14476 : int bStopProcessing = FALSE;
3208 14476 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3209 : "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
3210 : nBufXSize, nBufYSize, nBandCount, panBandMap);
3211 14476 : if (eErr != CE_None || bStopProcessing)
3212 20 : return eErr;
3213 :
3214 127853 : for (int iBand = 0; iBand < nBandCount; ++iBand)
3215 : {
3216 113397 : GDALRasterBand *poBand = nullptr;
3217 :
3218 113397 : if (panBandMap == nullptr)
3219 112076 : poBand = GetRasterBand(iBand + 1);
3220 : else
3221 1321 : poBand = GetRasterBand(panBandMap[iBand]);
3222 :
3223 113397 : if (poBand == nullptr)
3224 0 : return CE_Failure;
3225 :
3226 226794 : eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
3227 113397 : nBufYSize, eBufType, papszOptions);
3228 :
3229 113397 : if (eErr != CE_None)
3230 0 : return eErr;
3231 : }
3232 :
3233 14456 : return CE_None;
3234 : }
3235 :
3236 : /************************************************************************/
3237 : /* GDALDatasetAdviseRead() */
3238 : /************************************************************************/
3239 :
3240 : /**
3241 : * \brief Advise driver of upcoming read requests.
3242 : *
3243 : * @see GDALDataset::AdviseRead()
3244 : */
3245 1 : CPLErr CPL_STDCALL GDALDatasetAdviseRead(GDALDatasetH hDS, int nXOff, int nYOff,
3246 : int nXSize, int nYSize, int nBufXSize,
3247 : int nBufYSize, GDALDataType eDT,
3248 : int nBandCount, int *panBandMap,
3249 : CSLConstList papszOptions)
3250 :
3251 : {
3252 1 : VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
3253 :
3254 2 : return GDALDataset::FromHandle(hDS)->AdviseRead(
3255 : nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount,
3256 1 : panBandMap, const_cast<char **>(papszOptions));
3257 : }
3258 :
3259 : /************************************************************************/
3260 : /* GDALAntiRecursionStruct */
3261 : /************************************************************************/
3262 :
3263 : // Prevent infinite recursion.
3264 : struct GDALAntiRecursionStruct
3265 : {
3266 : struct DatasetContext
3267 : {
3268 : std::string osFilename;
3269 : int nOpenFlags;
3270 : std::string osAllowedDrivers;
3271 :
3272 80115 : DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,
3273 : const std::string &osAllowedDriversIn)
3274 80115 : : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),
3275 80115 : osAllowedDrivers(osAllowedDriversIn)
3276 : {
3277 80109 : }
3278 : };
3279 :
3280 : struct DatasetContextCompare
3281 : {
3282 919665 : bool operator()(const DatasetContext &lhs,
3283 : const DatasetContext &rhs) const
3284 : {
3285 2684790 : return lhs.osFilename < rhs.osFilename ||
3286 889291 : (lhs.osFilename == rhs.osFilename &&
3287 875960 : (lhs.nOpenFlags < rhs.nOpenFlags ||
3288 1751740 : (lhs.nOpenFlags == rhs.nOpenFlags &&
3289 1795490 : lhs.osAllowedDrivers < rhs.osAllowedDrivers)));
3290 : }
3291 : };
3292 :
3293 : std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
3294 : int nRecLevel = 0;
3295 : std::map<std::string, int> m_oMapDepth{};
3296 : };
3297 :
3298 : #ifdef _WIN32
3299 : // Currently thread_local and C++ objects don't work well with DLL on Windows
3300 : static void FreeAntiRecursionOpen(void *pData)
3301 : {
3302 : delete static_cast<GDALAntiRecursionStruct *>(pData);
3303 : }
3304 :
3305 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3306 : {
3307 : static GDALAntiRecursionStruct dummy;
3308 : int bMemoryErrorOccurred = false;
3309 : void *pData =
3310 : CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
3311 : if (bMemoryErrorOccurred)
3312 : {
3313 : return dummy;
3314 : }
3315 : if (pData == nullptr)
3316 : {
3317 : auto pAntiRecursion = new GDALAntiRecursionStruct();
3318 : CPLSetTLSWithFreeFuncEx(CTLS_GDALOPEN_ANTIRECURSION, pAntiRecursion,
3319 : FreeAntiRecursionOpen, &bMemoryErrorOccurred);
3320 : if (bMemoryErrorOccurred)
3321 : {
3322 : delete pAntiRecursion;
3323 : return dummy;
3324 : }
3325 : return *pAntiRecursion;
3326 : }
3327 : return *static_cast<GDALAntiRecursionStruct *>(pData);
3328 : }
3329 : #else
3330 : static thread_local GDALAntiRecursionStruct g_tls_antiRecursion;
3331 :
3332 339948 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3333 : {
3334 339948 : return g_tls_antiRecursion;
3335 : }
3336 : #endif
3337 :
3338 : //! @cond Doxygen_Suppress
3339 259832 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)
3340 259832 : : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),
3341 : m_osIdentifier(osIdentifier),
3342 259832 : m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3343 : {
3344 259832 : CPLAssert(!osIdentifier.empty());
3345 259832 : }
3346 :
3347 259832 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(
3348 259832 : const GDALAntiRecursionGuard &other, const std::string &osIdentifier)
3349 259832 : : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),
3350 259832 : m_osIdentifier(osIdentifier.empty()
3351 : ? osIdentifier
3352 26866 : : other.m_osIdentifier + osIdentifier),
3353 259832 : m_nDepth(m_osIdentifier.empty()
3354 259832 : ? 0
3355 286698 : : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3356 : {
3357 259832 : }
3358 :
3359 519664 : GDALAntiRecursionGuard::~GDALAntiRecursionGuard()
3360 : {
3361 519664 : if (!m_osIdentifier.empty())
3362 : {
3363 286698 : --m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier];
3364 : }
3365 519664 : }
3366 :
3367 : //! @endcond
3368 :
3369 : /************************************************************************/
3370 : /* GetFileList() */
3371 : /************************************************************************/
3372 :
3373 : /**
3374 : * \brief Fetch files forming dataset.
3375 : *
3376 : * Returns a list of files believed to be part of this dataset. If it returns
3377 : * an empty list of files it means there is believed to be no local file
3378 : * system files associated with the dataset (for instance a virtual dataset).
3379 : * The returned file list is owned by the caller and should be deallocated
3380 : * with CSLDestroy().
3381 : *
3382 : * The returned filenames will normally be relative or absolute paths
3383 : * depending on the path used to originally open the dataset. The strings
3384 : * will be UTF-8 encoded.
3385 : *
3386 : * This method is the same as the C GDALGetFileList() function.
3387 : *
3388 : * @return NULL or a NULL terminated array of file names.
3389 : */
3390 :
3391 4768 : char **GDALDataset::GetFileList()
3392 :
3393 : {
3394 9536 : CPLString osMainFilename = GetDescription();
3395 : VSIStatBufL sStat;
3396 :
3397 4768 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3398 : GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,
3399 9536 : std::string());
3400 4768 : auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
3401 4768 : if (cpl::contains(aosDatasetList, datasetCtxt))
3402 0 : return nullptr;
3403 :
3404 : /* -------------------------------------------------------------------- */
3405 : /* Is the main filename even a real filesystem object? */
3406 : /* -------------------------------------------------------------------- */
3407 : int bMainFileReal =
3408 4768 : VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
3409 :
3410 : /* -------------------------------------------------------------------- */
3411 : /* Form new list. */
3412 : /* -------------------------------------------------------------------- */
3413 4768 : char **papszList = nullptr;
3414 :
3415 4768 : if (bMainFileReal)
3416 4705 : papszList = CSLAddString(papszList, osMainFilename);
3417 :
3418 4768 : if (sAntiRecursion.nRecLevel == 100)
3419 : {
3420 0 : CPLError(CE_Failure, CPLE_AppDefined,
3421 : "GetFileList() called with too many recursion levels");
3422 0 : return papszList;
3423 : }
3424 4768 : ++sAntiRecursion.nRecLevel;
3425 :
3426 : /* -------------------------------------------------------------------- */
3427 : /* Do we have a known overview file? */
3428 : /* -------------------------------------------------------------------- */
3429 4768 : if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
3430 : {
3431 61 : auto iter = aosDatasetList.insert(datasetCtxt).first;
3432 61 : char **papszOvrList = oOvManager.poODS->GetFileList();
3433 61 : papszList = CSLInsertStrings(papszList, -1, papszOvrList);
3434 61 : CSLDestroy(papszOvrList);
3435 61 : aosDatasetList.erase(iter);
3436 : }
3437 :
3438 : /* -------------------------------------------------------------------- */
3439 : /* Do we have a known mask file? */
3440 : /* -------------------------------------------------------------------- */
3441 4768 : if (oOvManager.HaveMaskFile())
3442 : {
3443 9 : auto iter = aosDatasetList.insert(std::move(datasetCtxt)).first;
3444 9 : for (const char *pszFile :
3445 18 : CPLStringList(oOvManager.poMaskDS->GetFileList()))
3446 : {
3447 9 : if (CSLFindString(papszList, pszFile) < 0)
3448 9 : papszList = CSLAddString(papszList, pszFile);
3449 : }
3450 9 : aosDatasetList.erase(iter);
3451 : }
3452 :
3453 4768 : --sAntiRecursion.nRecLevel;
3454 :
3455 4768 : return papszList;
3456 : }
3457 :
3458 : /************************************************************************/
3459 : /* GDALGetFileList() */
3460 : /************************************************************************/
3461 :
3462 : /**
3463 : * \brief Fetch files forming dataset.
3464 : *
3465 : * @see GDALDataset::GetFileList()
3466 : */
3467 :
3468 3977 : char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)
3469 :
3470 : {
3471 3977 : VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3472 :
3473 3977 : return GDALDataset::FromHandle(hDS)->GetFileList();
3474 : }
3475 :
3476 : /************************************************************************/
3477 : /* CreateMaskBand() */
3478 : /************************************************************************/
3479 :
3480 : /**
3481 : * \brief Adds a mask band to the dataset
3482 : *
3483 : * The default implementation of the CreateMaskBand() method is implemented
3484 : * based on similar rules to the .ovr handling implemented using the
3485 : * GDALDefaultOverviews object. A TIFF file with the extension .msk will
3486 : * be created with the same basename as the original file, and it will have
3487 : * one band.
3488 : * The mask images will be deflate compressed tiled images with the same
3489 : * block size as the original image if possible.
3490 : * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
3491 : * level, where xx matches the band number of a band of the main dataset. The
3492 : * value of those items will be the one of the nFlagsIn parameter.
3493 : *
3494 : * Note that if you got a mask band with a previous call to GetMaskBand(), it
3495 : * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
3496 : * again.
3497 : *
3498 : * @since GDAL 1.5.0
3499 : *
3500 : * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
3501 : * GMF_PER_DATASET will be always set, even if not explicitly
3502 : * specified.
3503 : * @return CE_None on success or CE_Failure on an error.
3504 : *
3505 : * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
3506 : * @see GDALRasterBand::CreateMaskBand()
3507 : *
3508 : */
3509 17 : CPLErr GDALDataset::CreateMaskBand(int nFlagsIn)
3510 :
3511 : {
3512 17 : if (oOvManager.IsInitialized())
3513 : {
3514 17 : CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
3515 17 : if (eErr != CE_None)
3516 0 : return eErr;
3517 :
3518 : // Invalidate existing raster band masks.
3519 45 : for (int i = 0; i < nBands; ++i)
3520 : {
3521 28 : GDALRasterBand *poBand = papoBands[i];
3522 28 : poBand->poMask.reset();
3523 : }
3524 :
3525 17 : return CE_None;
3526 : }
3527 :
3528 0 : ReportError(CE_Failure, CPLE_NotSupported,
3529 : "CreateMaskBand() not supported for this dataset.");
3530 :
3531 0 : return CE_Failure;
3532 : }
3533 :
3534 : /************************************************************************/
3535 : /* GDALCreateDatasetMaskBand() */
3536 : /************************************************************************/
3537 :
3538 : /**
3539 : * \brief Adds a mask band to the dataset
3540 : * @see GDALDataset::CreateMaskBand()
3541 : */
3542 90 : CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)
3543 :
3544 : {
3545 90 : VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3546 :
3547 90 : return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
3548 : }
3549 :
3550 : /************************************************************************/
3551 : /* GDALOpen() */
3552 : /************************************************************************/
3553 :
3554 : /**
3555 : * \brief Open a raster file as a GDALDataset.
3556 : *
3557 : * This function will try to open the passed file, or virtual dataset
3558 : * name by invoking the Open method of each registered GDALDriver in turn.
3559 : * The first successful open will result in a returned dataset. If all
3560 : * drivers fail then NULL is returned and an error is issued.
3561 : *
3562 : * Several recommendations :
3563 : * <ul>
3564 : * <li>If you open a dataset object with GA_Update access, it is not recommended
3565 : * to open a new dataset on the same underlying file.</li>
3566 : * <li>The returned dataset should only be accessed by one thread at a time. If
3567 : * you want to use it from different threads, you must add all necessary code
3568 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3569 : * as GeoTIFF, maintain internal state variables that are updated each time a
3570 : * new block is read, thus preventing concurrent use.) </li>
3571 : * </ul>
3572 : *
3573 : * For drivers supporting the VSI virtual file API, it is possible to open a
3574 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3575 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3576 : * server (see VSIInstallCurlFileHandler())
3577 : *
3578 : * \sa GDALOpenShared()
3579 : * \sa GDALOpenEx()
3580 : *
3581 : * @param pszFilename the name of the file to access. In the case of
3582 : * exotic drivers this may not refer to a physical file, but instead contain
3583 : * information for the driver on how to access a dataset. It should be in UTF-8
3584 : * encoding.
3585 : *
3586 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
3587 : * drivers support only read only access.
3588 : *
3589 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3590 : * this handle can be cast to a GDALDataset *.
3591 : */
3592 :
3593 25250 : GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)
3594 :
3595 : {
3596 25250 : const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3597 25250 : const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3598 : GDALDatasetH hDataset =
3599 25250 : GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3600 25251 : return hDataset;
3601 : }
3602 :
3603 : /************************************************************************/
3604 : /* GetSharedDS() */
3605 : /************************************************************************/
3606 :
3607 6486 : static GDALDataset *GetSharedDS(const char *pszFilename,
3608 : unsigned int nOpenFlags,
3609 : const char *const *papszOpenOptions)
3610 : {
3611 12972 : CPLMutexHolderD(&hDLMutex);
3612 :
3613 6486 : if (phSharedDatasetSet != nullptr)
3614 : {
3615 6237 : const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3616 : SharedDatasetCtxt sStruct;
3617 :
3618 6237 : sStruct.nPID = nThisPID;
3619 6237 : sStruct.pszDescription = const_cast<char *>(pszFilename);
3620 6237 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
3621 : std::string osConcatenatedOpenOptions =
3622 6237 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
3623 6237 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
3624 6237 : sStruct.poDS = nullptr;
3625 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3626 6237 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3627 6237 : if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3628 : {
3629 132 : sStruct.nOpenFlags |= GDAL_OF_UPDATE;
3630 : psStruct = static_cast<SharedDatasetCtxt *>(
3631 132 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3632 : }
3633 6237 : if (psStruct)
3634 : {
3635 6106 : return psStruct->poDS;
3636 : }
3637 : }
3638 380 : return nullptr;
3639 : }
3640 :
3641 : /************************************************************************/
3642 : /* GDALOpenEx() */
3643 : /************************************************************************/
3644 :
3645 : /**
3646 : * \brief Open a raster or vector file as a GDALDataset.
3647 : *
3648 : * This function will try to open the passed file, or virtual dataset
3649 : * name by invoking the Open method of each registered GDALDriver in turn.
3650 : * The first successful open will result in a returned dataset. If all
3651 : * drivers fail then NULL is returned and an error is issued.
3652 : *
3653 : * Several recommendations :
3654 : * <ul>
3655 : * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
3656 : * recommended to open a new dataset on the same underlying file.</li>
3657 : * <li>The returned dataset should only be accessed by one thread at a time. If
3658 : * you want to use it from different threads, you must add all necessary code
3659 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3660 : * as GeoTIFF, maintain internal state variables that are updated each time a
3661 : * new block is read, thus preventing concurrent use.) </li>
3662 : * </ul>
3663 : *
3664 : * For drivers supporting the VSI virtual file API, it is possible to open a
3665 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3666 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3667 : * server (see VSIInstallCurlFileHandler())
3668 : *
3669 : * In order to reduce the need for searches through the operating system
3670 : * file system machinery, it is possible to give an optional list of files with
3671 : * the papszSiblingFiles parameter.
3672 : * This is the list of all files at the same level in the file system as the
3673 : * target file, including the target file. The filenames must not include any
3674 : * path components, are essentially just the output of VSIReadDir() on the
3675 : * parent directory. If the target object does not have filesystem semantics
3676 : * then the file list should be NULL.
3677 : *
3678 : * @param pszFilename the name of the file to access. In the case of
3679 : * exotic drivers this may not refer to a physical file, but instead contain
3680 : * information for the driver on how to access a dataset. It should be in UTF-8
3681 : * encoding.
3682 : *
3683 : * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
3684 : * through logical or operator.
3685 : * <ul>
3686 : * <li>Driver kind:
3687 : * <ul>
3688 : * <li>GDAL_OF_RASTER for raster drivers,</li>
3689 : * <li>GDAL_OF_MULTIDIM_RASTER for multidimensional raster drivers,</li>
3690 : * <li>GDAL_OF_VECTOR for vector drivers,</li>
3691 : * <li>GDAL_OF_GNM for Geographic Network Model drivers.</li>
3692 : * </ul>
3693 : * GDAL_OF_RASTER and GDAL_OF_MULTIDIM_RASTER are generally mutually
3694 : * exclusive. If none of the value is specified, GDAL_OF_RASTER | GDAL_OF_VECTOR
3695 : * | GDAL_OF_GNM is implied.
3696 : * </li>
3697 : * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.
3698 : * </li>
3699 : * <li>Shared mode: GDAL_OF_SHARED. If set,
3700 : * it allows the sharing of GDALDataset handles for a dataset with other callers
3701 : * that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will first consult
3702 : * its list of currently open and shared GDALDataset's, and if the
3703 : * GetDescription() name for one exactly matches the pszFilename passed to
3704 : * GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called
3705 : * from the same thread.
3706 : * </li>
3707 : * <li>Thread safe mode: GDAL_OF_THREAD_SAFE (added in 3.10).
3708 : * This must be use in combination with GDAL_OF_RASTER, and is mutually
3709 : * exclusive with GDAL_OF_UPDATE, GDAL_OF_VECTOR, GDAL_OF_MULTIDIM_RASTER or
3710 : * GDAL_OF_GNM.
3711 : * </li>
3712 : * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set,
3713 : * a failed attempt to open the file will lead to an error message to be
3714 : * reported.
3715 : * </li>
3716 : * </ul>
3717 : *
3718 : * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
3719 : * terminated list of strings with the driver short names that must be
3720 : * considered.
3721 : *
3722 : * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
3723 : * options passed to candidate drivers. An option exists for all drivers,
3724 : * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
3725 : * The level index starts at 0. The level number can be suffixed by "only" to
3726 : * specify that only this overview level must be visible, and not sub-levels.
3727 : * Open options are validated by default, and a warning is emitted in case the
3728 : * option is not recognized. In some scenarios, it might be not desirable (e.g.
3729 : * when not knowing which driver will open the file), so the special open option
3730 : * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
3731 : * since GDAL 2.1, an option name can be preceded by the @ character to indicate
3732 : * that it may not cause a warning if the driver doesn't declare this option.
3733 : * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
3734 : * no overviews should be exposed.
3735 : *
3736 : * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
3737 : * filenames that are auxiliary to the main filename. If NULL is passed, a
3738 : * probing of the file system will be done.
3739 : *
3740 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3741 : * this handle can be cast to a GDALDataset *.
3742 : *
3743 : * @since GDAL 2.0
3744 : */
3745 :
3746 81456 : GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
3747 : unsigned int nOpenFlags,
3748 : const char *const *papszAllowedDrivers,
3749 : const char *const *papszOpenOptions,
3750 : const char *const *papszSiblingFiles)
3751 : {
3752 81456 : VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
3753 :
3754 : // Hack for the ZARR driver. We translate the CACHE_KERCHUNK_JSON
3755 : // into VSIKERCHUNK_USE_CACHE config option
3756 81445 : std::unique_ptr<CPLConfigOptionSetter> poVSIKERCHUNK_USE_CACHESetter;
3757 81456 : if (CPLFetchBool(papszOpenOptions, "CACHE_KERCHUNK_JSON", false))
3758 : {
3759 13 : poVSIKERCHUNK_USE_CACHESetter = std::make_unique<CPLConfigOptionSetter>(
3760 26 : "VSIKERCHUNK_USE_CACHE", "YES", false);
3761 : }
3762 :
3763 : // Do some sanity checks on incompatible flags with thread-safe mode.
3764 81457 : if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3765 : {
3766 : const struct
3767 : {
3768 : int nFlag;
3769 : const char *pszFlagName;
3770 128 : } asFlags[] = {
3771 : {GDAL_OF_UPDATE, "GDAL_OF_UPDATE"},
3772 : {GDAL_OF_VECTOR, "GDAL_OF_VECTOR"},
3773 : {GDAL_OF_MULTIDIM_RASTER, "GDAL_OF_MULTIDIM_RASTER"},
3774 : {GDAL_OF_GNM, "GDAL_OF_GNM"},
3775 : };
3776 :
3777 630 : for (const auto &asFlag : asFlags)
3778 : {
3779 506 : if ((nOpenFlags & asFlag.nFlag) != 0)
3780 : {
3781 4 : CPLError(CE_Failure, CPLE_IllegalArg,
3782 : "GDAL_OF_THREAD_SAFE and %s are mutually "
3783 : "exclusive",
3784 4 : asFlag.pszFlagName);
3785 4 : return nullptr;
3786 : }
3787 : }
3788 : }
3789 :
3790 : // If no driver kind is specified, assume all are to be probed.
3791 81453 : if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)
3792 7545 : nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
3793 :
3794 : /* -------------------------------------------------------------------- */
3795 : /* In case of shared dataset, first scan the existing list to see */
3796 : /* if it could already contain the requested dataset. */
3797 : /* -------------------------------------------------------------------- */
3798 81453 : if (nOpenFlags & GDAL_OF_SHARED)
3799 : {
3800 6486 : if (nOpenFlags & GDAL_OF_INTERNAL)
3801 : {
3802 0 : CPLError(CE_Failure, CPLE_IllegalArg,
3803 : "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
3804 0 : return nullptr;
3805 : }
3806 :
3807 : auto poSharedDS =
3808 6486 : GetSharedDS(pszFilename, nOpenFlags, papszOpenOptions);
3809 6486 : if (poSharedDS)
3810 : {
3811 6106 : poSharedDS->Reference();
3812 6106 : return poSharedDS;
3813 : }
3814 : }
3815 :
3816 75347 : GDALDriverManager *poDM = GetGDALDriverManager();
3817 : // CPLLocaleC oLocaleForcer;
3818 :
3819 75348 : CPLErrorReset();
3820 75347 : VSIErrorReset();
3821 75347 : CPLAssert(nullptr != poDM);
3822 :
3823 : // Build GDALOpenInfo just now to avoid useless file stat'ing if a
3824 : // shared dataset was asked before.
3825 : GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
3826 150685 : const_cast<char **>(papszSiblingFiles));
3827 75348 : oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3828 :
3829 75348 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3830 75347 : if (sAntiRecursion.nRecLevel == 100)
3831 : {
3832 0 : CPLError(CE_Failure, CPLE_AppDefined,
3833 : "GDALOpen() called with too many recursion levels");
3834 0 : return nullptr;
3835 : }
3836 :
3837 150687 : std::string osAllowedDrivers;
3838 165355 : for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
3839 90007 : osAllowedDrivers += pszDriverName;
3840 : auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(
3841 226025 : std::string(pszFilename), nOpenFlags, osAllowedDrivers);
3842 75345 : if (cpl::contains(sAntiRecursion.aosDatasetNamesWithFlags, dsCtxt))
3843 : {
3844 0 : CPLError(CE_Failure, CPLE_AppDefined,
3845 : "GDALOpen() called on %s recursively", pszFilename);
3846 0 : return nullptr;
3847 : }
3848 :
3849 : // Remove leading @ if present.
3850 : char **papszOpenOptionsCleaned =
3851 75333 : CSLDuplicate(const_cast<char **>(papszOpenOptions));
3852 80875 : for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
3853 : ++papszIter)
3854 : {
3855 5540 : char *pszOption = *papszIter;
3856 5540 : if (pszOption[0] == '@')
3857 203 : memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
3858 : }
3859 :
3860 75335 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3861 75335 : oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;
3862 :
3863 : #ifdef OGRAPISPY_ENABLED
3864 75335 : const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
3865 : const int iSnapshot =
3866 18784 : (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0
3867 94119 : ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)
3868 75335 : : INT_MIN;
3869 : #endif
3870 :
3871 75335 : const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);
3872 75338 : GDALDriver *poMissingPluginDriver = nullptr;
3873 150683 : std::vector<GDALDriver *> apoSecondPassDrivers;
3874 :
3875 : // Lookup of matching driver for dataset can involve up to 2 passes:
3876 : // - in the first pass, all drivers that are compabile of the request mode
3877 : // (raster/vector/etc.) are probed using their Identify() method if it
3878 : // exists. If the Identify() method returns FALSE, the driver is skipped.
3879 : // If the Identify() methods returns GDAL_IDENTIFY_UNKNOWN and that the
3880 : // driver is a deferred-loading plugin, it is added to the
3881 : // apoSecondPassDrivers list for potential later probing, and execution
3882 : // continues to the next driver in the list.
3883 : // Otherwise if Identify() returns non-FALSE, the Open() method is used.
3884 : // If Open() returns a non-NULL dataset, the loop stops and it is
3885 : // returned. Otherwise looping over remaining drivers continues.
3886 : // - the second pass is optional, only if at least one driver was added
3887 : // into apoSecondPassDrivers during the first pass. It is similar
3888 : // to the first pass except it runs only on apoSecondPassDrivers drivers.
3889 : // And the Open() method of such drivers is used, causing them to be
3890 : // loaded for real.
3891 75330 : int iPass = 1;
3892 75339 : retry:
3893 7673730 : for (int iDriver = 0;
3894 7673760 : iDriver < (iPass == 1 ? nDriverCount
3895 30 : : static_cast<int>(apoSecondPassDrivers.size()));
3896 : ++iDriver)
3897 : {
3898 : GDALDriver *poDriver =
3899 7658180 : iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
3900 1753 : : apoSecondPassDrivers[iDriver];
3901 11167600 : if (papszAllowedDrivers != nullptr &&
3902 3508420 : CSLFindString(papszAllowedDrivers,
3903 : GDALGetDriverShortName(poDriver)) == -1)
3904 : {
3905 7220640 : continue;
3906 : }
3907 :
3908 4235760 : if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)
3909 39202 : continue;
3910 :
3911 11139000 : if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&
3912 6072700 : (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
3913 1885450 : poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
3914 452955 : continue;
3915 10944600 : if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3916 5475450 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3917 1741160 : poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
3918 1313080 : continue;
3919 5124780 : if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
3920 2565770 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3921 144554 : poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)
3922 135957 : continue;
3923 :
3924 : // Remove general OVERVIEW_LEVEL open options from list before passing
3925 : // it to the driver, if it isn't a driver specific option already.
3926 2285260 : char **papszTmpOpenOptions = nullptr;
3927 2285260 : char **papszTmpOpenOptionsToValidate = nullptr;
3928 2285260 : char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
3929 2285260 : if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
3930 2290180 : nullptr &&
3931 183 : !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
3932 : {
3933 183 : papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
3934 : papszTmpOpenOptions =
3935 183 : CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
3936 183 : oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
3937 :
3938 183 : papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
3939 183 : papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate,
3940 : "OVERVIEW_LEVEL", nullptr);
3941 183 : papszTmpOpenOptionsToValidate = papszOptionsToValidate;
3942 : }
3943 :
3944 : const int nIdentifyRes =
3945 2290000 : poDriver->pfnIdentifyEx
3946 4585070 : ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)
3947 2289990 : : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)
3948 2295080 : : GDAL_IDENTIFY_UNKNOWN;
3949 2295080 : if (nIdentifyRes == FALSE)
3950 : {
3951 1857730 : CSLDestroy(papszTmpOpenOptions);
3952 1855430 : CSLDestroy(papszTmpOpenOptionsToValidate);
3953 1855940 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3954 1855940 : continue;
3955 : }
3956 438200 : else if (iPass == 1 && nIdentifyRes < 0 &&
3957 875654 : poDriver->pfnOpen == nullptr &&
3958 107 : poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN"))
3959 : {
3960 : // Not loaded plugin
3961 101 : apoSecondPassDrivers.push_back(poDriver);
3962 101 : CSLDestroy(papszTmpOpenOptions);
3963 101 : CSLDestroy(papszTmpOpenOptionsToValidate);
3964 101 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3965 101 : continue;
3966 : }
3967 :
3968 437246 : const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;
3969 437246 : if (bIdentifyRes)
3970 : {
3971 56059 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3972 : }
3973 :
3974 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3975 : const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
3976 : CPLErrorReset();
3977 : #endif
3978 :
3979 437234 : sAntiRecursion.nRecLevel++;
3980 437234 : sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
3981 :
3982 437663 : GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
3983 :
3984 438198 : sAntiRecursion.nRecLevel--;
3985 438198 : sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
3986 :
3987 437818 : if (poDriver->pfnOpen != nullptr)
3988 : {
3989 : // If we couldn't determine for sure with Identify() (it returned
3990 : // -1), but Open() managed to open the file, post validate options.
3991 437673 : if (poDS != nullptr &&
3992 55971 : (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&
3993 55436 : !bIdentifyRes)
3994 : {
3995 783 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3996 : }
3997 : }
3998 145 : else if (poDriver->pfnOpenWithDriverArg != nullptr)
3999 : {
4000 : // do nothing
4001 : }
4002 0 : else if (bIdentifyRes &&
4003 0 : poDriver->GetMetadataItem("MISSING_PLUGIN_FILENAME"))
4004 : {
4005 0 : if (!poMissingPluginDriver)
4006 : {
4007 0 : poMissingPluginDriver = poDriver;
4008 : }
4009 : }
4010 : else
4011 : {
4012 : // should not happen given the GDAL_DCAP_OPEN check
4013 0 : CSLDestroy(papszTmpOpenOptions);
4014 0 : CSLDestroy(papszTmpOpenOptionsToValidate);
4015 0 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4016 0 : continue;
4017 : }
4018 :
4019 437818 : CSLDestroy(papszTmpOpenOptions);
4020 437383 : CSLDestroy(papszTmpOpenOptionsToValidate);
4021 437377 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4022 :
4023 437377 : if (poDS != nullptr)
4024 : {
4025 55970 : if (poDS->papszOpenOptions == nullptr)
4026 : {
4027 55704 : poDS->papszOpenOptions = papszOpenOptionsCleaned;
4028 55704 : papszOpenOptionsCleaned = nullptr;
4029 : }
4030 :
4031 : // Deal with generic OVERVIEW_LEVEL open option, unless it is
4032 : // driver specific.
4033 55970 : if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
4034 56013 : nullptr &&
4035 39 : !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
4036 : {
4037 : CPLString osVal(
4038 78 : CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
4039 39 : const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
4040 : const bool bThisLevelOnly =
4041 39 : nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
4042 : GDALDataset *poOvrDS =
4043 39 : GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly);
4044 39 : if (poOvrDS && (nOpenFlags & GDAL_OF_SHARED) != 0)
4045 : {
4046 4 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
4047 : {
4048 0 : CPLError(
4049 : CE_Warning, CPLE_NotSupported,
4050 : "A dataset opened by GDALOpenShared should have "
4051 : "the same filename (%s) "
4052 : "and description (%s)",
4053 0 : pszFilename, poDS->GetDescription());
4054 : }
4055 : else
4056 : {
4057 4 : CSLDestroy(poDS->papszOpenOptions);
4058 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
4059 4 : poDS->papszOpenOptions = CSLSetNameValue(
4060 : poDS->papszOpenOptions, "OVERVIEW_LEVEL", nullptr);
4061 : }
4062 : }
4063 39 : poDS->ReleaseRef();
4064 39 : poDS = poOvrDS;
4065 39 : if (poDS == nullptr)
4066 : {
4067 1 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4068 : {
4069 1 : CPLError(CE_Failure, CPLE_OpenFailed,
4070 : "Cannot open overview level %d of %s",
4071 : nOvrLevel, pszFilename);
4072 : }
4073 : }
4074 : else
4075 : {
4076 : // For thread-safe opening, currently poDS is what will be
4077 : // the "master" dataset owned by the thread-safe dataset
4078 : // returned to the user, hence we do not register it as a
4079 : // visible one in the open dataset list, or mark it as shared.
4080 38 : if (!(nOpenFlags & GDAL_OF_INTERNAL) &&
4081 36 : !(nOpenFlags & GDAL_OF_THREAD_SAFE))
4082 : {
4083 35 : poDS->AddToDatasetOpenList();
4084 : }
4085 38 : if (nOpenFlags & GDAL_OF_SHARED)
4086 : {
4087 4 : CSLDestroy(poDS->papszOpenOptions);
4088 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
4089 4 : poDS->nOpenFlags = nOpenFlags;
4090 4 : if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
4091 4 : poDS->MarkAsShared();
4092 : }
4093 : }
4094 : }
4095 55935 : else if (nOpenFlags & GDAL_OF_SHARED)
4096 : {
4097 370 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
4098 : {
4099 2 : CPLError(CE_Warning, CPLE_NotSupported,
4100 : "A dataset opened by GDALOpenShared should have "
4101 : "the same filename (%s) "
4102 : "and description (%s)",
4103 2 : pszFilename, poDS->GetDescription());
4104 : }
4105 368 : else if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
4106 : {
4107 : // For thread-safe opening, currently poDS is what will be
4108 : // the "master" dataset owned by the thread-safe dataset
4109 : // returned to the user, hence we do not or mark it as shared.
4110 368 : poDS->MarkAsShared();
4111 : }
4112 : }
4113 :
4114 55974 : VSIErrorReset();
4115 :
4116 55974 : CSLDestroy(papszOpenOptionsCleaned);
4117 :
4118 : #ifdef OGRAPISPY_ENABLED
4119 55971 : if (iSnapshot != INT_MIN)
4120 : {
4121 11101 : GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
4122 11101 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4123 11101 : poDS = GDALDataset::FromHandle(hDS);
4124 : }
4125 : #endif
4126 :
4127 55971 : if (poDS)
4128 : {
4129 55971 : poDS->m_bCanBeReopened = true;
4130 :
4131 55971 : if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
4132 : {
4133 : poDS =
4134 248 : GDALGetThreadSafeDataset(
4135 248 : std::unique_ptr<GDALDataset>(poDS), GDAL_OF_RASTER)
4136 124 : .release();
4137 124 : if (poDS)
4138 : {
4139 124 : poDS->m_bCanBeReopened = true;
4140 124 : poDS->poDriver = poDriver;
4141 124 : poDS->nOpenFlags = nOpenFlags;
4142 124 : if (!(nOpenFlags & GDAL_OF_INTERNAL))
4143 124 : poDS->AddToDatasetOpenList();
4144 124 : if (nOpenFlags & GDAL_OF_SHARED)
4145 0 : poDS->MarkAsShared();
4146 : }
4147 : }
4148 : }
4149 :
4150 56977 : return poDS;
4151 : }
4152 :
4153 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
4154 : if (bFpAvailableBefore && oOpenInfo.fpL == nullptr)
4155 : {
4156 : // In case the file descriptor was "consumed" by a driver
4157 : // that ultimately failed, re-open it for next drivers.
4158 : oOpenInfo.fpL = VSIFOpenL(
4159 : pszFilename, (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
4160 : }
4161 : #else
4162 381407 : if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
4163 : {
4164 3892 : CSLDestroy(papszOpenOptionsCleaned);
4165 :
4166 : #ifdef OGRAPISPY_ENABLED
4167 1003 : if (iSnapshot != INT_MIN)
4168 : {
4169 187 : GDALDatasetH hDS = nullptr;
4170 187 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4171 : }
4172 : #endif
4173 1003 : return nullptr;
4174 : }
4175 : #endif
4176 : }
4177 :
4178 : // cppcheck-suppress knownConditionTrueFalse
4179 15580 : if (iPass == 1 && !apoSecondPassDrivers.empty())
4180 : {
4181 11 : CPLDebugOnly("GDAL", "GDALOpen(): Second pass");
4182 9 : iPass = 2;
4183 9 : goto retry;
4184 : }
4185 :
4186 15568 : CSLDestroy(papszOpenOptionsCleaned);
4187 :
4188 : #ifdef OGRAPISPY_ENABLED
4189 18367 : if (iSnapshot != INT_MIN)
4190 : {
4191 648 : GDALDatasetH hDS = nullptr;
4192 648 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4193 : }
4194 : #endif
4195 :
4196 18367 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4197 : {
4198 5587 : if (nDriverCount == 0)
4199 : {
4200 0 : CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");
4201 : }
4202 5587 : else if (poMissingPluginDriver)
4203 : {
4204 0 : std::string osMsg("`");
4205 0 : osMsg += pszFilename;
4206 : osMsg += "' not recognized as being in a supported file format. "
4207 0 : "It could have been recognized by driver ";
4208 0 : osMsg += poMissingPluginDriver->GetDescription();
4209 0 : osMsg += ", but plugin ";
4210 : osMsg +=
4211 0 : GDALGetMessageAboutMissingPluginDriver(poMissingPluginDriver);
4212 :
4213 0 : CPLError(CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str());
4214 : }
4215 : // Check to see if there was a filesystem error, and report it if so.
4216 : // If not, return a more generic error.
4217 5587 : else if (!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
4218 : {
4219 350 : if (oOpenInfo.bStatOK)
4220 : {
4221 347 : CPLError(CE_Failure, CPLE_OpenFailed,
4222 : "`%s' not recognized as being in a supported file "
4223 : "format.",
4224 : pszFilename);
4225 : }
4226 : else
4227 : {
4228 : // If Stat failed and no VSI error was set, assume it is because
4229 : // the file did not exist on the filesystem.
4230 3 : CPLError(CE_Failure, CPLE_OpenFailed,
4231 : "`%s' does not exist in the file system, "
4232 : "and is not recognized as a supported dataset name.",
4233 : pszFilename);
4234 : }
4235 : }
4236 : }
4237 :
4238 18368 : return nullptr;
4239 : }
4240 :
4241 : /************************************************************************/
4242 : /* GDALOpenShared() */
4243 : /************************************************************************/
4244 :
4245 : /**
4246 : * \brief Open a raster file as a GDALDataset.
4247 : *
4248 : * This function works the same as GDALOpen(), but allows the sharing of
4249 : * GDALDataset handles for a dataset with other callers to GDALOpenShared().
4250 : *
4251 : * In particular, GDALOpenShared() will first consult its list of currently
4252 : * open and shared GDALDataset's, and if the GetDescription() name for one
4253 : * exactly matches the pszFilename passed to GDALOpenShared() it will be
4254 : * referenced and returned.
4255 : *
4256 : * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
4257 : * pszFilename from two different threads, a different GDALDataset object will
4258 : * be returned as it is not safe to use the same dataset from different threads,
4259 : * unless the user does explicitly use mutexes in its code.
4260 : *
4261 : * For drivers supporting the VSI virtual file API, it is possible to open a
4262 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
4263 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
4264 : * server (see VSIInstallCurlFileHandler())
4265 : *
4266 : * \sa GDALOpen()
4267 : * \sa GDALOpenEx()
4268 : *
4269 : * @param pszFilename the name of the file to access. In the case of
4270 : * exotic drivers this may not refer to a physical file, but instead contain
4271 : * information for the driver on how to access a dataset. It should be in
4272 : * UTF-8 encoding.
4273 : *
4274 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
4275 : * drivers support only read only access.
4276 : *
4277 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
4278 : * this handle can be cast to a GDALDataset *.
4279 : */
4280 :
4281 5224 : GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,
4282 : GDALAccess eAccess)
4283 : {
4284 5224 : VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
4285 5224 : return GDALOpenEx(pszFilename,
4286 : GDAL_OF_RASTER |
4287 : (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
4288 : GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
4289 5224 : nullptr, nullptr, nullptr);
4290 : }
4291 :
4292 : /************************************************************************/
4293 : /* GDALClose() */
4294 : /************************************************************************/
4295 :
4296 : /**
4297 : * \brief Close GDAL dataset.
4298 : *
4299 : * For non-shared datasets (opened with GDALOpen()) the dataset is closed
4300 : * using the C++ "delete" operator, recovering all dataset related resources.
4301 : * For shared datasets (opened with GDALOpenShared()) the dataset is
4302 : * dereferenced, and closed only if the referenced count has dropped below 1.
4303 : *
4304 : * @param hDS The dataset to close. May be cast from a "GDALDataset *".
4305 : * @return CE_None in case of success (return value since GDAL 3.7). On a
4306 : * shared dataset whose reference count is not dropped below 1, CE_None will
4307 : * be returned.
4308 : */
4309 :
4310 74845 : CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)
4311 :
4312 : {
4313 74845 : if (!hDS)
4314 397 : return CE_None;
4315 :
4316 : #ifdef OGRAPISPY_ENABLED
4317 74448 : if (bOGRAPISpyEnabled)
4318 11 : OGRAPISpyPreClose(hDS);
4319 : #endif
4320 :
4321 74448 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
4322 :
4323 74448 : if (poDS->GetShared())
4324 : {
4325 : /* --------------------------------------------------------------------
4326 : */
4327 : /* If this file is in the shared dataset list then dereference */
4328 : /* it, and only delete/remote it if the reference count has */
4329 : /* dropped to zero. */
4330 : /* --------------------------------------------------------------------
4331 : */
4332 231 : if (poDS->Dereference() > 0)
4333 15 : return CE_None;
4334 :
4335 216 : CPLErr eErr = poDS->Close();
4336 216 : delete poDS;
4337 :
4338 : #ifdef OGRAPISPY_ENABLED
4339 216 : if (bOGRAPISpyEnabled)
4340 0 : OGRAPISpyPostClose();
4341 : #endif
4342 :
4343 216 : return eErr;
4344 : }
4345 :
4346 : /* -------------------------------------------------------------------- */
4347 : /* This is not shared dataset, so directly delete it. */
4348 : /* -------------------------------------------------------------------- */
4349 74217 : CPLErr eErr = poDS->Close();
4350 74217 : delete poDS;
4351 :
4352 : #ifdef OGRAPISPY_ENABLED
4353 74216 : if (bOGRAPISpyEnabled)
4354 11 : OGRAPISpyPostClose();
4355 : #endif
4356 74214 : return eErr;
4357 : }
4358 :
4359 : /************************************************************************/
4360 : /* GDALDumpOpenDataset() */
4361 : /************************************************************************/
4362 :
4363 0 : static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
4364 : {
4365 0 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
4366 0 : FILE *fp = static_cast<FILE *>(user_data);
4367 0 : GDALDataset *poDS = psStruct->poDS;
4368 :
4369 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4370 0 : ? "DriverIsNULL"
4371 0 : : poDS->GetDriver()->GetDescription();
4372 :
4373 0 : poDS->Reference();
4374 0 : CPL_IGNORE_RET_VAL(
4375 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4376 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName,
4377 0 : static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
4378 : poDS->GetRasterYSize(), poDS->GetRasterCount(),
4379 0 : poDS->GetDescription()));
4380 :
4381 0 : return TRUE;
4382 : }
4383 :
4384 0 : static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
4385 : {
4386 :
4387 : // Don't list shared datasets. They have already been listed by
4388 : // GDALDumpOpenSharedDatasetsForeach.
4389 0 : if (poDS->GetShared())
4390 0 : return TRUE;
4391 :
4392 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4393 0 : ? "DriverIsNULL"
4394 0 : : poDS->GetDriver()->GetDescription();
4395 :
4396 0 : poDS->Reference();
4397 0 : CPL_IGNORE_RET_VAL(
4398 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4399 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
4400 : poDS->GetRasterXSize(), poDS->GetRasterYSize(),
4401 0 : poDS->GetRasterCount(), poDS->GetDescription()));
4402 :
4403 0 : return TRUE;
4404 : }
4405 :
4406 : /**
4407 : * \brief List open datasets.
4408 : *
4409 : * Dumps a list of all open datasets (shared or not) to the indicated
4410 : * text file (may be stdout or stderr). This function is primarily intended
4411 : * to assist in debugging "dataset leaks" and reference counting issues.
4412 : * The information reported includes the dataset name, referenced count,
4413 : * shared status, driver name, size, and band count.
4414 : */
4415 :
4416 272 : int CPL_STDCALL GDALDumpOpenDatasets(FILE *fp)
4417 :
4418 : {
4419 272 : VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
4420 :
4421 544 : CPLMutexHolderD(&hDLMutex);
4422 :
4423 272 : if (poAllDatasetMap == nullptr)
4424 272 : return 0;
4425 :
4426 0 : CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
4427 :
4428 0 : for (const auto &oIter : *poAllDatasetMap)
4429 : {
4430 0 : GDALDumpOpenDatasetsForeach(oIter.first, fp);
4431 : }
4432 :
4433 0 : if (phSharedDatasetSet != nullptr)
4434 : {
4435 0 : CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach,
4436 : fp);
4437 : }
4438 0 : return static_cast<int>(poAllDatasetMap->size());
4439 : }
4440 :
4441 : /************************************************************************/
4442 : /* BeginAsyncReader() */
4443 : /************************************************************************/
4444 :
4445 : /**
4446 : * \brief Sets up an asynchronous data request
4447 : *
4448 : * This method establish an asynchronous raster read request for the
4449 : * indicated window on the dataset into the indicated buffer. The parameters
4450 : * for windowing, buffer size, buffer type and buffer organization are similar
4451 : * to those for GDALDataset::RasterIO(); however, this call only launches
4452 : * the request and filling the buffer is accomplished via calls to
4453 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4454 : *
4455 : * Once all processing for the created session is complete, or if no further
4456 : * refinement of the request is required, the GDALAsyncReader object should
4457 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4458 : *
4459 : * Note that the data buffer (pData) will potentially continue to be
4460 : * updated as long as the session lives, but it is not deallocated when
4461 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4462 : * should be deallocated by the application at that point.
4463 : *
4464 : * Additional information on asynchronous IO in GDAL may be found at:
4465 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4466 : *
4467 : * This method is the same as the C GDALBeginAsyncReader() function.
4468 : *
4469 : * @param nXOff The pixel offset to the top left corner of the region
4470 : * of the band to be accessed. This would be zero to start from the left side.
4471 : *
4472 : * @param nYOff The line offset to the top left corner of the region
4473 : * of the band to be accessed. This would be zero to start from the top.
4474 : *
4475 : * @param nXSize The width of the region of the band to be accessed in pixels.
4476 : *
4477 : * @param nYSize The height of the region of the band to be accessed in lines.
4478 : *
4479 : * @param pBuf The buffer into which the data should be read. This buffer must
4480 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4481 : * It is organized in left to right,top to bottom pixel order. Spacing is
4482 : * controlled by the nPixelSpace, and nLineSpace parameters.
4483 : *
4484 : * @param nBufXSize the width of the buffer image into which the desired region
4485 : * is to be read, or from which it is to be written.
4486 : *
4487 : * @param nBufYSize the height of the buffer image into which the desired
4488 : * region is to be read, or from which it is to be written.
4489 : *
4490 : * @param eBufType the type of the pixel values in the pData data buffer. The
4491 : * pixel values will automatically be translated to/from the GDALRasterBand
4492 : * data type as needed.
4493 : *
4494 : * @param nBandCount the number of bands being read or written.
4495 : *
4496 : * @param panBandMap the list of nBandCount band numbers being read/written.
4497 : * Note band numbers are 1 based. This may be NULL to select the first
4498 : * nBandCount bands.
4499 : *
4500 : * @param nPixelSpace The byte offset from the start of one pixel value in
4501 : * pData to the start of the next pixel value within a scanline. If defaulted
4502 : * (0) the size of the datatype eBufType is used.
4503 : *
4504 : * @param nLineSpace The byte offset from the start of one scanline in
4505 : * pData to the start of the next. If defaulted the size of the datatype
4506 : * eBufType * nBufXSize is used.
4507 : *
4508 : * @param nBandSpace the byte offset from the start of one bands data to the
4509 : * start of the next. If defaulted (zero) the value will be
4510 : * nLineSpace * nBufYSize implying band sequential organization
4511 : * of the data buffer.
4512 : *
4513 : * @param papszOptions Driver specific control options in a string list or NULL.
4514 : * Consult driver documentation for options supported.
4515 : *
4516 : * @return The GDALAsyncReader object representing the request.
4517 : */
4518 :
4519 1 : GDALAsyncReader *GDALDataset::BeginAsyncReader(
4520 : int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
4521 : int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
4522 : int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions)
4523 : {
4524 : // See gdaldefaultasync.cpp
4525 :
4526 1 : return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
4527 : nBufXSize, nBufYSize, eBufType, nBandCount,
4528 : panBandMap, nPixelSpace, nLineSpace,
4529 1 : nBandSpace, papszOptions);
4530 : }
4531 :
4532 : /************************************************************************/
4533 : /* GDALBeginAsyncReader() */
4534 : /************************************************************************/
4535 :
4536 : /**
4537 : * \brief Sets up an asynchronous data request
4538 : *
4539 : * This method establish an asynchronous raster read request for the
4540 : * indicated window on the dataset into the indicated buffer. The parameters
4541 : * for windowing, buffer size, buffer type and buffer organization are similar
4542 : * to those for GDALDataset::RasterIO(); however, this call only launches
4543 : * the request and filling the buffer is accomplished via calls to
4544 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4545 : *
4546 : * Once all processing for the created session is complete, or if no further
4547 : * refinement of the request is required, the GDALAsyncReader object should
4548 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4549 : *
4550 : * Note that the data buffer (pData) will potentially continue to be
4551 : * updated as long as the session lives, but it is not deallocated when
4552 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4553 : * should be deallocated by the application at that point.
4554 : *
4555 : * Additional information on asynchronous IO in GDAL may be found at:
4556 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4557 : *
4558 : * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
4559 : *
4560 : * @param hDS handle to the dataset object.
4561 : *
4562 : * @param nXOff The pixel offset to the top left corner of the region
4563 : * of the band to be accessed. This would be zero to start from the left side.
4564 : *
4565 : * @param nYOff The line offset to the top left corner of the region
4566 : * of the band to be accessed. This would be zero to start from the top.
4567 : *
4568 : * @param nXSize The width of the region of the band to be accessed in pixels.
4569 : *
4570 : * @param nYSize The height of the region of the band to be accessed in lines.
4571 : *
4572 : * @param pBuf The buffer into which the data should be read. This buffer must
4573 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4574 : * It is organized in left to right,top to bottom pixel order. Spacing is
4575 : * controlled by the nPixelSpace, and nLineSpace parameters.
4576 : *
4577 : * @param nBufXSize the width of the buffer image into which the desired region
4578 : * is to be read, or from which it is to be written.
4579 : *
4580 : * @param nBufYSize the height of the buffer image into which the desired
4581 : * region is to be read, or from which it is to be written.
4582 : *
4583 : * @param eBufType the type of the pixel values in the pData data buffer. The
4584 : * pixel values will automatically be translated to/from the GDALRasterBand
4585 : * data type as needed.
4586 : *
4587 : * @param nBandCount the number of bands being read or written.
4588 : *
4589 : * @param panBandMap the list of nBandCount band numbers being read/written.
4590 : * Note band numbers are 1 based. This may be NULL to select the first
4591 : * nBandCount bands.
4592 : *
4593 : * @param nPixelSpace The byte offset from the start of one pixel value in
4594 : * pData to the start of the next pixel value within a scanline. If defaulted
4595 : * (0) the size of the datatype eBufType is used.
4596 : *
4597 : * @param nLineSpace The byte offset from the start of one scanline in
4598 : * pData to the start of the next. If defaulted the size of the datatype
4599 : * eBufType * nBufXSize is used.
4600 : *
4601 : * @param nBandSpace the byte offset from the start of one bands data to the
4602 : * start of the next. If defaulted (zero) the value will be
4603 : * nLineSpace * nBufYSize implying band sequential organization
4604 : * of the data buffer.
4605 : *
4606 : * @param papszOptions Driver specific control options in a string list or NULL.
4607 : * Consult driver documentation for options supported.
4608 : *
4609 : * @return handle representing the request.
4610 : */
4611 :
4612 2 : GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(
4613 : GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf,
4614 : int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount,
4615 : int *panBandMap, int nPixelSpace, int nLineSpace, int nBandSpace,
4616 : CSLConstList papszOptions)
4617 :
4618 : {
4619 2 : VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
4620 : return static_cast<GDALAsyncReaderH>(
4621 2 : GDALDataset::FromHandle(hDS)->BeginAsyncReader(
4622 : nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
4623 : nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
4624 2 : const_cast<char **>(papszOptions)));
4625 : }
4626 :
4627 : /************************************************************************/
4628 : /* EndAsyncReader() */
4629 : /************************************************************************/
4630 :
4631 : /**
4632 : * End asynchronous request.
4633 : *
4634 : * This method destroys an asynchronous io request and recovers all
4635 : * resources associated with it.
4636 : *
4637 : * This method is the same as the C function GDALEndAsyncReader().
4638 : *
4639 : * @param poARIO pointer to a GDALAsyncReader
4640 : */
4641 :
4642 1 : void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO)
4643 : {
4644 1 : delete poARIO;
4645 1 : }
4646 :
4647 : /************************************************************************/
4648 : /* GDALEndAsyncReader() */
4649 : /************************************************************************/
4650 :
4651 : /**
4652 : * End asynchronous request.
4653 : *
4654 : * This method destroys an asynchronous io request and recovers all
4655 : * resources associated with it.
4656 : *
4657 : * This method is the same as the C++ method GDALDataset::EndAsyncReader().
4658 : *
4659 : * @param hDS handle to the dataset object.
4660 : * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
4661 : */
4662 :
4663 1 : void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS,
4664 : GDALAsyncReaderH hAsyncReaderH)
4665 : {
4666 1 : VALIDATE_POINTER0(hDS, "GDALDataset");
4667 1 : VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
4668 1 : GDALDataset::FromHandle(hDS)->EndAsyncReader(
4669 1 : static_cast<GDALAsyncReader *>(hAsyncReaderH));
4670 : }
4671 :
4672 : /************************************************************************/
4673 : /* CloseDependentDatasets() */
4674 : /************************************************************************/
4675 :
4676 : /**
4677 : * Drop references to any other datasets referenced by this dataset.
4678 : *
4679 : * This method should release any reference to other datasets (e.g. a VRT
4680 : * dataset to its sources), but not close the current dataset itself.
4681 : *
4682 : * If at least, one reference to a dependent dataset has been dropped,
4683 : * this method should return TRUE. Otherwise it *should* return FALSE.
4684 : * (Failure to return the proper value might result in infinite loop)
4685 : *
4686 : * This method can be called several times on a given dataset. After
4687 : * the first time, it should not do anything and return FALSE.
4688 : *
4689 : * The driver implementation may choose to destroy its raster bands,
4690 : * so be careful not to call any method on the raster bands afterwards.
4691 : *
4692 : * Basically the only safe action you can do after calling
4693 : * CloseDependentDatasets() is to call the destructor.
4694 : *
4695 : * Note: the only legitimate caller of CloseDependentDatasets() is
4696 : * GDALDriverManager::~GDALDriverManager()
4697 : *
4698 : * @return TRUE if at least one reference to another dataset has been dropped.
4699 : */
4700 18883 : int GDALDataset::CloseDependentDatasets()
4701 : {
4702 18883 : return oOvManager.CloseDependentDatasets();
4703 : }
4704 :
4705 : /************************************************************************/
4706 : /* ReportError() */
4707 : /************************************************************************/
4708 :
4709 : #ifndef DOXYGEN_XML
4710 : /**
4711 : * \brief Emits an error related to a dataset.
4712 : *
4713 : * This function is a wrapper for regular CPLError(). The only difference
4714 : * with CPLError() is that it prepends the error message with the dataset
4715 : * name.
4716 : *
4717 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4718 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4719 : * @param fmt a printf() style format string. Any additional arguments
4720 : * will be treated as arguments to fill in this format in a manner
4721 : * similar to printf().
4722 : *
4723 : * @since GDAL 1.9.0
4724 : */
4725 :
4726 98 : void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4727 : const char *fmt, ...) const
4728 : {
4729 : va_list args;
4730 98 : va_start(args, fmt);
4731 98 : ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4732 98 : va_end(args);
4733 98 : }
4734 :
4735 : /**
4736 : * \brief Emits an error related to a dataset (static method)
4737 : *
4738 : * This function is a wrapper for regular CPLError(). The only difference
4739 : * with CPLError() is that it prepends the error message with the dataset
4740 : * name.
4741 : *
4742 : * @param pszDSName dataset name.
4743 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4744 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4745 : * @param fmt a printf() style format string. Any additional arguments
4746 : * will be treated as arguments to fill in this format in a manner
4747 : * similar to printf().
4748 : *
4749 : * @since GDAL 3.2.0
4750 : */
4751 :
4752 122 : void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,
4753 : CPLErrorNum err_no, const char *fmt, ...)
4754 : {
4755 : va_list args;
4756 122 : va_start(args, fmt);
4757 122 : ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4758 122 : va_end(args);
4759 122 : }
4760 :
4761 220 : void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,
4762 : CPLErrorNum err_no, const char *fmt,
4763 : va_list args)
4764 : {
4765 220 : pszDSName = CPLGetFilename(pszDSName);
4766 220 : if (pszDSName[0] != '\0')
4767 : {
4768 207 : CPLError(eErrClass, err_no, "%s",
4769 414 : std::string(pszDSName)
4770 207 : .append(": ")
4771 414 : .append(CPLString().vPrintf(fmt, args))
4772 : .c_str());
4773 : }
4774 : else
4775 : {
4776 13 : CPLErrorV(eErrClass, err_no, fmt, args);
4777 : }
4778 220 : }
4779 : #endif
4780 :
4781 : /************************************************************************/
4782 : /* GetMetadata() */
4783 : /************************************************************************/
4784 68680 : char **GDALDataset::GetMetadata(const char *pszDomain)
4785 : {
4786 : #ifndef WITHOUT_DERIVED
4787 68680 : if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
4788 : {
4789 10 : oDerivedMetadataList.Clear();
4790 :
4791 : // First condition: at least one raster band.
4792 10 : if (GetRasterCount() > 0)
4793 : {
4794 : // Check if there is at least one complex band.
4795 10 : bool hasAComplexBand = false;
4796 :
4797 19 : for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4798 : {
4799 11 : if (GDALDataTypeIsComplex(
4800 11 : GetRasterBand(rasterId)->GetRasterDataType()))
4801 : {
4802 2 : hasAComplexBand = true;
4803 2 : break;
4804 : }
4805 : }
4806 :
4807 10 : unsigned int nbSupportedDerivedDS = 0;
4808 : const DerivedDatasetDescription *poDDSDesc =
4809 10 : GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4810 :
4811 10 : int nNumDataset = 1;
4812 80 : for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4813 : ++derivedId)
4814 : {
4815 126 : if (hasAComplexBand ||
4816 126 : CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4817 : "complex")
4818 : {
4819 : oDerivedMetadataList.SetNameValue(
4820 : CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4821 : CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4822 22 : poDDSDesc[derivedId].pszDatasetName,
4823 22 : GetDescription()));
4824 :
4825 : CPLString osDesc(
4826 : CPLSPrintf("%s from %s",
4827 22 : poDDSDesc[derivedId].pszDatasetDescription,
4828 22 : GetDescription()));
4829 : oDerivedMetadataList.SetNameValue(
4830 : CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4831 22 : osDesc.c_str());
4832 :
4833 22 : nNumDataset++;
4834 : }
4835 : }
4836 : }
4837 10 : return oDerivedMetadataList.List();
4838 : }
4839 : #endif
4840 :
4841 68670 : return GDALMajorObject::GetMetadata(pszDomain);
4842 : }
4843 :
4844 : // clang-format off
4845 :
4846 : /**
4847 : * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
4848 : * \brief Set metadata.
4849 : *
4850 : * CAUTION: depending on the format, older values of the updated information
4851 : * might still be found in the file in a "ghost" state, even if no longer
4852 : * accessible through the GDAL API. This is for example the case of the GTiff
4853 : * format (this is not a exhaustive list)
4854 : *
4855 : * The C function GDALSetMetadata() does the same thing as this method.
4856 : *
4857 : * @param papszMetadata the metadata in name=value string list format to
4858 : * apply.
4859 : * @param pszDomain the domain of interest. Use "" or NULL for the default
4860 : * domain.
4861 : * @return CE_None on success, CE_Failure on failure and CE_Warning if the
4862 : * metadata has been accepted, but is likely not maintained persistently
4863 : * by the underlying object between sessions.
4864 : */
4865 :
4866 : /**
4867 : * \fn GDALDataset::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
4868 : * \brief Set single metadata item.
4869 : *
4870 : * CAUTION: depending on the format, older values of the updated information
4871 : * might still be found in the file in a "ghost" state, even if no longer
4872 : * accessible through the GDAL API. This is for example the case of the GTiff
4873 : * format (this is not a exhaustive list)
4874 : *
4875 : * The C function GDALSetMetadataItem() does the same thing as this method.
4876 : *
4877 : * @param pszName the key for the metadata item to fetch.
4878 : * @param pszValue the value to assign to the key.
4879 : * @param pszDomain the domain to set within, use NULL for the default domain.
4880 : *
4881 : * @return CE_None on success, or an error code on failure.
4882 : */
4883 :
4884 : // clang-format on
4885 :
4886 : /************************************************************************/
4887 : /* GetMetadataDomainList() */
4888 : /************************************************************************/
4889 :
4890 947 : char **GDALDataset::GetMetadataDomainList()
4891 : {
4892 947 : char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
4893 :
4894 : // Ensure that we do not duplicate DERIVED domain.
4895 1089 : if (GetRasterCount() > 0 &&
4896 142 : CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
4897 : {
4898 : currentDomainList =
4899 142 : CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
4900 : }
4901 947 : return currentDomainList;
4902 : }
4903 :
4904 : /************************************************************************/
4905 : /* GetDriverName() */
4906 : /************************************************************************/
4907 :
4908 : /** Return driver name.
4909 : * @return driver name.
4910 : */
4911 2056 : const char *GDALDataset::GetDriverName()
4912 : {
4913 2056 : if (poDriver)
4914 2044 : return poDriver->GetDescription();
4915 12 : return "";
4916 : }
4917 :
4918 : /************************************************************************/
4919 : /* GDALDatasetReleaseResultSet() */
4920 : /************************************************************************/
4921 :
4922 : /**
4923 : \brief Release results of ExecuteSQL().
4924 :
4925 : This function should only be used to deallocate OGRLayers resulting from
4926 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
4927 : results set before destroying the GDALDataset may cause errors.
4928 :
4929 : This function is the same as the C++ method GDALDataset::ReleaseResultSet()
4930 :
4931 : @since GDAL 2.0
4932 :
4933 : @param hDS the dataset handle.
4934 : @param hLayer the result of a previous ExecuteSQL() call.
4935 :
4936 : */
4937 3409 : void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)
4938 :
4939 : {
4940 3409 : VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
4941 :
4942 : #ifdef OGRAPISPY_ENABLED
4943 3409 : if (bOGRAPISpyEnabled)
4944 6 : OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
4945 : #endif
4946 :
4947 6818 : GDALDataset::FromHandle(hDS)->ReleaseResultSet(
4948 3409 : OGRLayer::FromHandle(hLayer));
4949 : }
4950 :
4951 : /************************************************************************/
4952 : /* GDALDatasetGetLayerCount() */
4953 : /************************************************************************/
4954 :
4955 : /**
4956 : \brief Get the number of layers in this dataset.
4957 :
4958 : This function is the same as the C++ method GDALDataset::GetLayerCount()
4959 :
4960 : @since GDAL 2.0
4961 :
4962 : @param hDS the dataset handle.
4963 : @return layer count.
4964 : */
4965 :
4966 1463 : int GDALDatasetGetLayerCount(GDALDatasetH hDS)
4967 :
4968 : {
4969 1463 : VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
4970 :
4971 : #ifdef OGRAPISPY_ENABLED
4972 1463 : if (bOGRAPISpyEnabled)
4973 2 : OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
4974 : #endif
4975 :
4976 1463 : return GDALDataset::FromHandle(hDS)->GetLayerCount();
4977 : }
4978 :
4979 : /************************************************************************/
4980 : /* GDALDatasetGetLayer() */
4981 : /************************************************************************/
4982 :
4983 : /**
4984 : \brief Fetch a layer by index.
4985 :
4986 : The returned layer remains owned by the
4987 : GDALDataset and should not be deleted by the application.
4988 :
4989 : This function is the same as the C++ method GDALDataset::GetLayer()
4990 :
4991 : @since GDAL 2.0
4992 :
4993 : @param hDS the dataset handle.
4994 : @param iLayer a layer number between 0 and GetLayerCount()-1.
4995 :
4996 : @return the layer, or NULL if iLayer is out of range or an error occurs.
4997 : */
4998 :
4999 9263 : OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)
5000 :
5001 : {
5002 9263 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
5003 :
5004 : OGRLayerH hLayer =
5005 9263 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
5006 :
5007 : #ifdef OGRAPISPY_ENABLED
5008 9263 : if (bOGRAPISpyEnabled)
5009 3 : OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
5010 : #endif
5011 :
5012 9263 : return hLayer;
5013 : }
5014 :
5015 : /************************************************************************/
5016 : /* GDALDatasetGetLayerByName() */
5017 : /************************************************************************/
5018 :
5019 : /**
5020 : \brief Fetch a layer by name.
5021 :
5022 : The returned layer remains owned by the
5023 : GDALDataset and should not be deleted by the application.
5024 :
5025 : This function is the same as the C++ method GDALDataset::GetLayerByName()
5026 :
5027 : @since GDAL 2.0
5028 :
5029 : @param hDS the dataset handle.
5030 : @param pszName the layer name of the layer to fetch.
5031 :
5032 : @return the layer, or NULL if Layer is not found or an error occurs.
5033 : */
5034 :
5035 3387 : OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)
5036 :
5037 : {
5038 3387 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
5039 :
5040 3387 : OGRLayerH hLayer = OGRLayer::ToHandle(
5041 3387 : GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
5042 :
5043 : #ifdef OGRAPISPY_ENABLED
5044 3387 : if (bOGRAPISpyEnabled)
5045 4 : OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
5046 : #endif
5047 :
5048 3387 : return hLayer;
5049 : }
5050 :
5051 : /************************************************************************/
5052 : /* GDALDatasetIsLayerPrivate() */
5053 : /************************************************************************/
5054 :
5055 : /**
5056 : \brief Returns true if the layer at the specified index is deemed a private or
5057 : system table, or an internal detail only.
5058 :
5059 : This function is the same as the C++ method GDALDataset::IsLayerPrivate()
5060 :
5061 : @since GDAL 3.4
5062 :
5063 : @param hDS the dataset handle.
5064 : @param iLayer a layer number between 0 and GetLayerCount()-1.
5065 :
5066 : @return true if the layer is a private or system table.
5067 : */
5068 :
5069 91 : int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)
5070 :
5071 : {
5072 91 : VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);
5073 :
5074 91 : const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);
5075 :
5076 91 : return res ? 1 : 0;
5077 : }
5078 :
5079 : /************************************************************************/
5080 : /* GetLayerIndex() */
5081 : /************************************************************************/
5082 :
5083 : /**
5084 : \brief Returns the index of the layer specified by name.
5085 :
5086 : @since GDAL 3.12
5087 :
5088 : @param pszName layer name (not NULL)
5089 :
5090 : @return an index >= 0, or -1 if not found.
5091 : */
5092 :
5093 3 : int GDALDataset::GetLayerIndex(const char *pszName)
5094 : {
5095 3 : const int nLayerCount = GetLayerCount();
5096 3 : int iMatch = -1;
5097 6 : for (int i = 0; i < nLayerCount; ++i)
5098 : {
5099 5 : if (const auto poLayer = GetLayer(i))
5100 : {
5101 5 : const char *pszLayerName = poLayer->GetDescription();
5102 5 : if (strcmp(pszName, pszLayerName) == 0)
5103 : {
5104 2 : iMatch = i;
5105 2 : break;
5106 : }
5107 3 : else if (EQUAL(pszName, pszLayerName))
5108 : {
5109 0 : iMatch = i;
5110 : }
5111 : }
5112 : }
5113 3 : return iMatch;
5114 : }
5115 :
5116 : /************************************************************************/
5117 : /* GDALDatasetDeleteLayer() */
5118 : /************************************************************************/
5119 :
5120 : /**
5121 : \brief Delete the indicated layer from the datasource.
5122 :
5123 : If this function is supported
5124 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
5125 :
5126 : This method is the same as the C++ method GDALDataset::DeleteLayer().
5127 :
5128 : @since GDAL 2.0
5129 :
5130 : @param hDS the dataset handle.
5131 : @param iLayer the index of the layer to delete.
5132 :
5133 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
5134 : layers is not supported for this datasource.
5135 :
5136 : */
5137 40 : OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)
5138 :
5139 : {
5140 40 : VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
5141 :
5142 : #ifdef OGRAPISPY_ENABLED
5143 40 : if (bOGRAPISpyEnabled)
5144 2 : OGRAPISpy_DS_DeleteLayer(hDS, iLayer);
5145 : #endif
5146 :
5147 40 : return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
5148 : }
5149 :
5150 : /************************************************************************/
5151 : /* CreateLayer() */
5152 : /************************************************************************/
5153 :
5154 : /**
5155 : \brief This method attempts to create a new layer on the dataset with the
5156 : indicated name, coordinate system, geometry type.
5157 :
5158 : The papszOptions argument
5159 : can be used to control driver specific creation options. These options are
5160 : normally documented in the format specific documentation.
5161 : That function will try to validate the creation option list passed to the
5162 : driver with the GDALValidateCreationOptions() method. This check can be
5163 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5164 : to NO.
5165 :
5166 : Drivers should extend the ICreateLayer() method and not
5167 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5168 : delegating the actual work to ICreateLayer().
5169 :
5170 : This method is the same as the C function GDALDatasetCreateLayer() and the
5171 : deprecated OGR_DS_CreateLayer().
5172 :
5173 : Example:
5174 :
5175 : \code{.cpp}
5176 : #include "gdal.h"
5177 : #include "cpl_string.h"
5178 :
5179 : ...
5180 :
5181 : OGRLayer *poLayer;
5182 : char **papszOptions;
5183 :
5184 : if( !poDS->TestCapability( ODsCCreateLayer ) )
5185 : {
5186 : ...
5187 : }
5188 :
5189 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5190 : poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
5191 : papszOptions );
5192 : CSLDestroy( papszOptions );
5193 :
5194 : if( poLayer == NULL )
5195 : {
5196 : ...
5197 : }
5198 : \endcode
5199 :
5200 : @param pszName the name for the new layer. This should ideally not
5201 : match any existing layer on the datasource.
5202 : @param poSpatialRef the coordinate system to use for the new layer, or NULL if
5203 : no coordinate system is available.
5204 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5205 : are no constraints on the types geometry to be written.
5206 : @param papszOptions a StringList of name=value options. Options are driver
5207 : specific.
5208 :
5209 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5210 :
5211 : */
5212 :
5213 7798 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5214 : const OGRSpatialReference *poSpatialRef,
5215 : OGRwkbGeometryType eGType,
5216 : CSLConstList papszOptions)
5217 :
5218 : {
5219 7798 : if (eGType == wkbNone)
5220 : {
5221 454 : return CreateLayer(pszName, nullptr, papszOptions);
5222 : }
5223 : else
5224 : {
5225 14688 : OGRGeomFieldDefn oGeomFieldDefn("", eGType);
5226 7344 : oGeomFieldDefn.SetSpatialRef(poSpatialRef);
5227 7344 : return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5228 : }
5229 : }
5230 :
5231 : /**
5232 : \brief This method attempts to create a new layer on the dataset with the
5233 : indicated name and geometry field definition.
5234 :
5235 : When poGeomFieldDefn is not null, most drivers should honor
5236 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5237 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5238 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5239 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5240 : very few currently.
5241 :
5242 : Note that even if a geometry coordinate precision is set and a driver honors the
5243 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5244 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5245 : with the coordinate precision. That is they are assumed to be valid once their
5246 : coordinates are rounded to it. If it might not be the case, the user may set
5247 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5248 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5249 : the passed geometries.
5250 :
5251 : The papszOptions argument
5252 : can be used to control driver specific creation options. These options are
5253 : normally documented in the format specific documentation.
5254 : This function will try to validate the creation option list passed to the
5255 : driver with the GDALValidateCreationOptions() method. This check can be
5256 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5257 : to NO.
5258 :
5259 : Drivers should extend the ICreateLayer() method and not
5260 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5261 : delegating the actual work to ICreateLayer().
5262 :
5263 : This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().
5264 :
5265 : @param pszName the name for the new layer. This should ideally not
5266 : match any existing layer on the datasource.
5267 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5268 : or NULL if there is no geometry field.
5269 : @param papszOptions a StringList of name=value options. Options are driver
5270 : specific.
5271 :
5272 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5273 : @since 3.9
5274 :
5275 : */
5276 :
5277 8857 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5278 : const OGRGeomFieldDefn *poGeomFieldDefn,
5279 : CSLConstList papszOptions)
5280 :
5281 : {
5282 8857 : if (CPLTestBool(
5283 : CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
5284 : {
5285 8857 : ValidateLayerCreationOptions(papszOptions);
5286 : }
5287 :
5288 : OGRLayer *poLayer;
5289 8857 : if (poGeomFieldDefn)
5290 : {
5291 8171 : OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);
5292 8264 : if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&
5293 93 : !TestCapability(ODsCCurveGeometries))
5294 : {
5295 23 : oGeomFieldDefn.SetType(
5296 : OGR_GT_GetLinear(poGeomFieldDefn->GetType()));
5297 : }
5298 :
5299 8171 : poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5300 : }
5301 : else
5302 : {
5303 686 : poLayer = ICreateLayer(pszName, nullptr, papszOptions);
5304 : }
5305 : #ifdef DEBUG
5306 8927 : if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
5307 70 : !poLayer->TestCapability(OLCCurveGeometries))
5308 : {
5309 0 : CPLError(CE_Warning, CPLE_AppDefined,
5310 : "Inconsistent driver: Layer geometry type is non-linear, but "
5311 : "TestCapability(OLCCurveGeometries) returns FALSE.");
5312 : }
5313 : #endif
5314 :
5315 8857 : return poLayer;
5316 : }
5317 :
5318 : //! @cond Doxygen_Suppress
5319 :
5320 : // Technical override to avoid ambiguous choice between the old and new
5321 : // new CreateLayer() signatures.
5322 11 : OGRLayer *GDALDataset::CreateLayer(const char *pszName)
5323 : {
5324 22 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5325 22 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5326 : }
5327 :
5328 : // Technical override to avoid ambiguous choice between the old and new
5329 : // new CreateLayer() signatures.
5330 1 : OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)
5331 : {
5332 2 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5333 2 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5334 : }
5335 :
5336 : //!@endcond
5337 :
5338 : /************************************************************************/
5339 : /* GDALDatasetCreateLayer() */
5340 : /************************************************************************/
5341 :
5342 : /**
5343 : \brief This function attempts to create a new layer on the dataset with the
5344 : indicated name, coordinate system, geometry type.
5345 :
5346 : The papszOptions argument can be used to control driver specific creation
5347 : options. These options are normally documented in the format specific
5348 : documentation.
5349 :
5350 : This method is the same as the C++ method GDALDataset::CreateLayer().
5351 :
5352 : Example:
5353 :
5354 : \code{.c}
5355 : #include "gdal.h"
5356 : #include "cpl_string.h"
5357 :
5358 : ...
5359 :
5360 : OGRLayerH hLayer;
5361 : char **papszOptions;
5362 :
5363 : if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
5364 : {
5365 : ...
5366 : }
5367 :
5368 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5369 : hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
5370 : papszOptions );
5371 : CSLDestroy( papszOptions );
5372 :
5373 : if( hLayer == NULL )
5374 : {
5375 : ...
5376 : }
5377 : \endcode
5378 :
5379 : @since GDAL 2.0
5380 :
5381 : @param hDS the dataset handle
5382 : @param pszName the name for the new layer. This should ideally not
5383 : match any existing layer on the datasource.
5384 : @param hSpatialRef the coordinate system to use for the new layer, or NULL if
5385 : no coordinate system is available.
5386 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5387 : are no constraints on the types geometry to be written.
5388 : @param papszOptions a StringList of name=value options. Options are driver
5389 : specific.
5390 :
5391 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5392 :
5393 : */
5394 :
5395 5961 : OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,
5396 : OGRSpatialReferenceH hSpatialRef,
5397 : OGRwkbGeometryType eGType,
5398 : CSLConstList papszOptions)
5399 :
5400 : {
5401 5961 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
5402 :
5403 5961 : if (pszName == nullptr)
5404 : {
5405 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5406 : "Name was NULL in GDALDatasetCreateLayer");
5407 0 : return nullptr;
5408 : }
5409 :
5410 : OGRLayerH hLayer =
5411 11922 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5412 5961 : pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,
5413 : const_cast<char **>(papszOptions)));
5414 :
5415 : #ifdef OGRAPISPY_ENABLED
5416 5961 : if (bOGRAPISpyEnabled)
5417 8 : OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,
5418 : const_cast<char **>(papszOptions), hLayer);
5419 : #endif
5420 :
5421 5961 : return hLayer;
5422 : }
5423 :
5424 : /************************************************************************/
5425 : /* GDALDatasetCreateLayerFromGeomFieldDefn() */
5426 : /************************************************************************/
5427 :
5428 : /**
5429 : \brief This function attempts to create a new layer on the dataset with the
5430 : indicated name and geometry field.
5431 :
5432 : When poGeomFieldDefn is not null, most drivers should honor
5433 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5434 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5435 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5436 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5437 : very few currently.
5438 :
5439 : Note that even if a geometry coordinate precision is set and a driver honors the
5440 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5441 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5442 : with the coordinate precision. That is they are assumed to be valid once their
5443 : coordinates are rounded to it. If it might not be the case, the user may set
5444 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5445 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5446 : the passed geometries.
5447 :
5448 : The papszOptions argument can be used to control driver specific creation
5449 : options. These options are normally documented in the format specific
5450 : documentation.
5451 :
5452 : This method is the same as the C++ method GDALDataset::CreateLayer().
5453 :
5454 : @param hDS the dataset handle
5455 : @param pszName the name for the new layer. This should ideally not
5456 : match any existing layer on the datasource.
5457 : @param hGeomFieldDefn the geometry field definition. May be NULL to indicate
5458 : a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()
5459 : for drivers supporting that interface).
5460 : @param papszOptions a StringList of name=value options. Options are driver
5461 : specific.
5462 :
5463 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5464 :
5465 : @since GDAL 3.9
5466 :
5467 : */
5468 :
5469 : OGRLayerH
5470 14 : GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,
5471 : OGRGeomFieldDefnH hGeomFieldDefn,
5472 : CSLConstList papszOptions)
5473 :
5474 : {
5475 14 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);
5476 :
5477 14 : if (!pszName)
5478 : {
5479 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5480 : "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");
5481 0 : return nullptr;
5482 : }
5483 :
5484 : OGRLayerH hLayer =
5485 28 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5486 14 : pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),
5487 : papszOptions));
5488 14 : return hLayer;
5489 : }
5490 :
5491 : /************************************************************************/
5492 : /* GDALDatasetCopyLayer() */
5493 : /************************************************************************/
5494 :
5495 : /**
5496 : \brief Duplicate an existing layer.
5497 :
5498 : This function creates a new layer, duplicate the field definitions of the
5499 : source layer and then duplicate each features of the source layer.
5500 : The papszOptions argument
5501 : can be used to control driver specific creation options. These options are
5502 : normally documented in the format specific documentation.
5503 : The source layer may come from another dataset.
5504 :
5505 : This method is the same as the C++ method GDALDataset::CopyLayer()
5506 :
5507 : @since GDAL 2.0
5508 :
5509 : @param hDS the dataset handle.
5510 : @param hSrcLayer source layer.
5511 : @param pszNewName the name of the layer to create.
5512 : @param papszOptions a StringList of name=value options. Options are driver
5513 : specific.
5514 :
5515 : @return a handle to the layer, or NULL if an error occurs.
5516 : */
5517 18 : OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,
5518 : const char *pszNewName,
5519 : CSLConstList papszOptions)
5520 :
5521 : {
5522 18 : VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
5523 18 : VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
5524 18 : VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
5525 :
5526 36 : return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(
5527 : OGRLayer::FromHandle(hSrcLayer), pszNewName,
5528 36 : const_cast<char **>(papszOptions)));
5529 : }
5530 :
5531 : /************************************************************************/
5532 : /* GDALDatasetExecuteSQL() */
5533 : /************************************************************************/
5534 :
5535 : /**
5536 : \brief Execute an SQL statement against the data store.
5537 :
5538 : The result of an SQL query is either NULL for statements that are in error,
5539 : or that have no results set, or an OGRLayer pointer representing a results
5540 : set from the query. Note that this OGRLayer is in addition to the layers
5541 : in the data store and must be destroyed with
5542 : ReleaseResultSet() before the dataset is closed
5543 : (destroyed).
5544 :
5545 : This method is the same as the C++ method GDALDataset::ExecuteSQL()
5546 :
5547 : For more information on the SQL dialect supported internally by OGR
5548 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
5549 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
5550 : to the underlying RDBMS.
5551 :
5552 : Starting with OGR 1.10, the <a
5553 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
5554 : also be used.
5555 :
5556 : @since GDAL 2.0
5557 :
5558 : @param hDS the dataset handle.
5559 : @param pszStatement the SQL statement to execute.
5560 : @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
5561 :
5562 : @param pszDialect allows control of the statement dialect. If set to NULL, the
5563 : OGR SQL engine will be used, except for RDBMS drivers that will use their
5564 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
5565 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
5566 :
5567 : @return an OGRLayer containing the results of the query. Deallocate with
5568 : GDALDatasetReleaseResultSet().
5569 :
5570 : */
5571 :
5572 10452 : OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,
5573 : OGRGeometryH hSpatialFilter,
5574 : const char *pszDialect)
5575 :
5576 : {
5577 10452 : VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
5578 :
5579 : OGRLayerH hLayer =
5580 20904 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(
5581 10452 : pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));
5582 :
5583 : #ifdef OGRAPISPY_ENABLED
5584 10452 : if (bOGRAPISpyEnabled)
5585 4 : OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,
5586 : hLayer);
5587 : #endif
5588 :
5589 10452 : return hLayer;
5590 : }
5591 :
5592 : /************************************************************************/
5593 : /* GDALDatasetAbortSQL() */
5594 : /************************************************************************/
5595 :
5596 : /**
5597 : \brief Abort any SQL statement running in the data store.
5598 :
5599 : This function can be safely called from any thread (pending that the dataset
5600 : object is still alive). Driver implementations will make sure that it can be
5601 : called in a thread-safe way.
5602 :
5603 : This might not be implemented by all drivers. At time of writing, only SQLite,
5604 : GPKG and PG drivers implement it
5605 :
5606 : This method is the same as the C++ method GDALDataset::AbortSQL()
5607 :
5608 : @since GDAL 3.2.0
5609 :
5610 : @param hDS the dataset handle.
5611 :
5612 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
5613 : is not supported for this datasource. .
5614 :
5615 : */
5616 :
5617 6 : OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)
5618 :
5619 : {
5620 6 : VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);
5621 6 : return GDALDataset::FromHandle(hDS)->AbortSQL();
5622 : }
5623 :
5624 : /************************************************************************/
5625 : /* GDALDatasetGetStyleTable() */
5626 : /************************************************************************/
5627 :
5628 : /**
5629 : \brief Returns dataset style table.
5630 :
5631 : This function is the same as the C++ method GDALDataset::GetStyleTable()
5632 :
5633 : @since GDAL 2.0
5634 :
5635 : @param hDS the dataset handle
5636 : @return handle to a style table which should not be modified or freed by the
5637 : caller.
5638 : */
5639 :
5640 6 : OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)
5641 :
5642 : {
5643 6 : VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
5644 :
5645 : return reinterpret_cast<OGRStyleTableH>(
5646 6 : GDALDataset::FromHandle(hDS)->GetStyleTable());
5647 : }
5648 :
5649 : /************************************************************************/
5650 : /* GDALDatasetSetStyleTableDirectly() */
5651 : /************************************************************************/
5652 :
5653 : /**
5654 : \brief Set dataset style table.
5655 :
5656 : This function operate exactly as GDALDatasetSetStyleTable() except that it
5657 : assumes ownership of the passed table.
5658 :
5659 : This function is the same as the C++ method
5660 : GDALDataset::SetStyleTableDirectly()
5661 :
5662 : @since GDAL 2.0
5663 :
5664 : @param hDS the dataset handle
5665 : @param hStyleTable style table handle to set
5666 :
5667 : */
5668 :
5669 0 : void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,
5670 : OGRStyleTableH hStyleTable)
5671 :
5672 : {
5673 0 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
5674 :
5675 0 : GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(
5676 0 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5677 : }
5678 :
5679 : /************************************************************************/
5680 : /* GDALDatasetSetStyleTable() */
5681 : /************************************************************************/
5682 :
5683 : /**
5684 : \brief Set dataset style table.
5685 :
5686 : This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
5687 : it assumes ownership of the passed table.
5688 :
5689 : This function is the same as the C++ method GDALDataset::SetStyleTable()
5690 :
5691 : @since GDAL 2.0
5692 :
5693 : @param hDS the dataset handle
5694 : @param hStyleTable style table handle to set
5695 :
5696 : */
5697 :
5698 5 : void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)
5699 :
5700 : {
5701 5 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
5702 5 : VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
5703 :
5704 5 : GDALDataset::FromHandle(hDS)->SetStyleTable(
5705 5 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5706 : }
5707 :
5708 : /************************************************************************/
5709 : /* ValidateLayerCreationOptions() */
5710 : /************************************************************************/
5711 :
5712 : //! @cond Doxygen_Suppress
5713 8857 : int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)
5714 : {
5715 : const char *pszOptionList =
5716 8857 : GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5717 8857 : if (pszOptionList == nullptr && poDriver != nullptr)
5718 : {
5719 : pszOptionList =
5720 8820 : poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5721 : }
5722 17714 : CPLString osDataset;
5723 8857 : osDataset.Printf("dataset %s", GetDescription());
5724 8857 : return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",
5725 17714 : osDataset);
5726 : }
5727 :
5728 : //! @endcond
5729 :
5730 : /************************************************************************/
5731 : /* Release() */
5732 : /************************************************************************/
5733 :
5734 : /**
5735 : \brief Drop a reference to this dataset, and if the reference count drops to one
5736 : close (destroy) the dataset.
5737 :
5738 : This method is the same as the C function OGRReleaseDataSource().
5739 :
5740 : @deprecated. In GDAL 2, use GDALClose() instead
5741 :
5742 : @return OGRERR_NONE on success or an error code.
5743 : */
5744 :
5745 4148 : OGRErr GDALDataset::Release()
5746 :
5747 : {
5748 4148 : ReleaseRef();
5749 4148 : return OGRERR_NONE;
5750 : }
5751 :
5752 : /************************************************************************/
5753 : /* GetRefCount() */
5754 : /************************************************************************/
5755 :
5756 : /**
5757 : \brief Fetch reference count.
5758 :
5759 : This method is the same as the C function OGR_DS_GetRefCount().
5760 :
5761 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5762 :
5763 : @return the current reference count for the datasource object itself.
5764 : */
5765 :
5766 919 : int GDALDataset::GetRefCount() const
5767 : {
5768 919 : return nRefCount;
5769 : }
5770 :
5771 : /************************************************************************/
5772 : /* GetSummaryRefCount() */
5773 : /************************************************************************/
5774 :
5775 : /**
5776 : \brief Fetch reference count of datasource and all owned layers.
5777 :
5778 : This method is the same as the C function OGR_DS_GetSummaryRefCount().
5779 :
5780 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5781 :
5782 : @deprecated
5783 :
5784 : @return the current summary reference count for the datasource and its layers.
5785 : */
5786 :
5787 0 : int GDALDataset::GetSummaryRefCount() const
5788 :
5789 : {
5790 0 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5791 0 : int nSummaryCount = nRefCount;
5792 0 : GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
5793 :
5794 0 : for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)
5795 0 : nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
5796 :
5797 0 : return nSummaryCount;
5798 : }
5799 :
5800 : /************************************************************************/
5801 : /* ICreateLayer() */
5802 : /************************************************************************/
5803 :
5804 : /**
5805 : \brief This method attempts to create a new layer on the dataset with the
5806 : indicated name, coordinate system, geometry type.
5807 :
5808 : This method is reserved to implementation by drivers.
5809 :
5810 : The papszOptions argument can be used to control driver specific creation
5811 : options. These options are normally documented in the format specific
5812 : documentation.
5813 :
5814 : @param pszName the name for the new layer. This should ideally not
5815 : match any existing layer on the datasource.
5816 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5817 : or NULL if there is no geometry field.
5818 : @param papszOptions a StringList of name=value options. Options are driver
5819 : specific.
5820 :
5821 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5822 :
5823 : @since GDAL 2.0 (prototype modified in 3.9)
5824 : */
5825 :
5826 : OGRLayer *
5827 16 : GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,
5828 : CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,
5829 : CPL_UNUSED CSLConstList papszOptions)
5830 :
5831 : {
5832 16 : CPLError(CE_Failure, CPLE_NotSupported,
5833 : "CreateLayer() not supported by this dataset.");
5834 :
5835 16 : return nullptr;
5836 : }
5837 :
5838 : /************************************************************************/
5839 : /* CopyLayer() */
5840 : /************************************************************************/
5841 :
5842 : /**
5843 : \brief Duplicate an existing layer.
5844 :
5845 : This method creates a new layer, duplicate the field definitions of the
5846 : source layer and then duplicate each features of the source layer.
5847 : The papszOptions argument
5848 : can be used to control driver specific creation options. These options are
5849 : normally documented in the format specific documentation.
5850 : The source layer may come from another dataset.
5851 :
5852 : This method is the same as the C function GDALDatasetCopyLayer() and the
5853 : deprecated OGR_DS_CopyLayer().
5854 :
5855 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5856 :
5857 : @param poSrcLayer source layer.
5858 : @param pszNewName the name of the layer to create.
5859 : @param papszOptions a StringList of name=value options. Options are driver
5860 : specific. There is a common option to set output layer
5861 : spatial reference: DST_SRSWKT. The option should be in
5862 : WKT format. Starting with GDAL 3.7, the common option
5863 : COPY_MD can be set to NO to prevent the default copying
5864 : of the metadata from the source layer to the target layer.
5865 :
5866 : @return a handle to the layer, or NULL if an error occurs.
5867 : */
5868 :
5869 134 : OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
5870 : char **papszOptions)
5871 :
5872 : {
5873 : /* -------------------------------------------------------------------- */
5874 : /* Create the layer. */
5875 : /* -------------------------------------------------------------------- */
5876 134 : if (!TestCapability(ODsCCreateLayer))
5877 : {
5878 0 : CPLError(CE_Failure, CPLE_NotSupported,
5879 : "This datasource does not support creation of layers.");
5880 0 : return nullptr;
5881 : }
5882 :
5883 134 : const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
5884 268 : OGRSpatialReference oDstSpaRef(pszSRSWKT);
5885 134 : oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5886 134 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
5887 134 : OGRLayer *poDstLayer = nullptr;
5888 :
5889 268 : CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));
5890 134 : aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr);
5891 134 : aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr);
5892 :
5893 134 : CPLErrorReset();
5894 134 : const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
5895 134 : if (nSrcGeomFieldCount == 1)
5896 : {
5897 82 : OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
5898 82 : if (pszSRSWKT)
5899 5 : oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);
5900 82 : poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,
5901 82 : aosCleanedUpOptions.List());
5902 : }
5903 : else
5904 : {
5905 : poDstLayer =
5906 52 : ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());
5907 : }
5908 :
5909 134 : if (poDstLayer == nullptr)
5910 0 : return nullptr;
5911 :
5912 134 : if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))
5913 : {
5914 133 : char **papszMD = poSrcLayer->GetMetadata();
5915 133 : if (papszMD)
5916 8 : poDstLayer->SetMetadata(papszMD);
5917 : }
5918 :
5919 : /* -------------------------------------------------------------------- */
5920 : /* Add fields. Default to copy all fields, and make sure to */
5921 : /* establish a mapping between indices, rather than names, in */
5922 : /* case the target datasource has altered it (e.g. Shapefile */
5923 : /* limited to 10 char field names). */
5924 : /* -------------------------------------------------------------------- */
5925 134 : const int nSrcFieldCount = poSrcDefn->GetFieldCount();
5926 :
5927 : // Initialize the index-to-index map to -1's.
5928 268 : std::vector<int> anMap(nSrcFieldCount, -1);
5929 :
5930 : // Caution: At the time of writing, the MapInfo driver
5931 : // returns NULL until a field has been added.
5932 134 : OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
5933 134 : int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
5934 288 : for (int iField = 0; iField < nSrcFieldCount; ++iField)
5935 : {
5936 154 : OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
5937 308 : OGRFieldDefn oFieldDefn(poSrcFieldDefn);
5938 :
5939 : // The field may have been already created at layer creation.
5940 154 : int iDstField = -1;
5941 154 : if (poDstFDefn)
5942 154 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
5943 154 : if (iDstField >= 0)
5944 : {
5945 0 : anMap[iField] = iDstField;
5946 : }
5947 154 : else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)
5948 : {
5949 : // Now that we've created a field, GetLayerDefn() won't return NULL.
5950 154 : if (poDstFDefn == nullptr)
5951 0 : poDstFDefn = poDstLayer->GetLayerDefn();
5952 :
5953 : // Sanity check: if it fails, the driver is buggy.
5954 308 : if (poDstFDefn != nullptr &&
5955 154 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
5956 : {
5957 0 : CPLError(CE_Warning, CPLE_AppDefined,
5958 : "The output driver has claimed to have added the %s "
5959 : "field, but it did not!",
5960 : oFieldDefn.GetNameRef());
5961 : }
5962 : else
5963 : {
5964 154 : anMap[iField] = nDstFieldCount;
5965 154 : ++nDstFieldCount;
5966 : }
5967 : }
5968 : }
5969 :
5970 : /* -------------------------------------------------------------------- */
5971 134 : std::unique_ptr<OGRCoordinateTransformation> poCT;
5972 134 : OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
5973 134 : if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&
5974 0 : sourceSRS->IsSame(&oDstSpaRef) == FALSE)
5975 : {
5976 0 : poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));
5977 0 : if (nullptr == poCT)
5978 : {
5979 0 : CPLError(CE_Failure, CPLE_NotSupported,
5980 : "This input/output spatial reference is not supported.");
5981 0 : return nullptr;
5982 : }
5983 : }
5984 : /* -------------------------------------------------------------------- */
5985 : /* Create geometry fields. */
5986 : /* -------------------------------------------------------------------- */
5987 135 : if (nSrcGeomFieldCount > 1 &&
5988 1 : TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
5989 : {
5990 :
5991 3 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5992 : {
5993 2 : if (nullptr == pszSRSWKT)
5994 : {
5995 2 : poDstLayer->CreateGeomField(
5996 2 : poSrcDefn->GetGeomFieldDefn(iField));
5997 : }
5998 : else
5999 : {
6000 : OGRGeomFieldDefn *pDstGeomFieldDefn =
6001 0 : poSrcDefn->GetGeomFieldDefn(iField);
6002 0 : pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
6003 0 : poDstLayer->CreateGeomField(pDstGeomFieldDefn);
6004 : }
6005 : }
6006 : }
6007 :
6008 : /* -------------------------------------------------------------------- */
6009 : /* Check if the destination layer supports transactions and set a */
6010 : /* default number of features in a single transaction. */
6011 : /* -------------------------------------------------------------------- */
6012 : const int nGroupTransactions =
6013 134 : poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
6014 :
6015 : /* -------------------------------------------------------------------- */
6016 : /* Transfer features. */
6017 : /* -------------------------------------------------------------------- */
6018 134 : poSrcLayer->ResetReading();
6019 :
6020 134 : if (nGroupTransactions <= 0)
6021 : {
6022 : while (true)
6023 : {
6024 : auto poFeature =
6025 453 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
6026 :
6027 453 : if (poFeature == nullptr)
6028 131 : break;
6029 :
6030 322 : CPLErrorReset();
6031 : auto poDstFeature =
6032 322 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
6033 :
6034 322 : if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=
6035 : OGRERR_NONE)
6036 : {
6037 0 : CPLError(CE_Failure, CPLE_AppDefined,
6038 : "Unable to translate feature " CPL_FRMT_GIB
6039 : " from layer %s.",
6040 0 : poFeature->GetFID(), poSrcDefn->GetName());
6041 0 : return poDstLayer;
6042 : }
6043 :
6044 322 : if (nullptr != poCT)
6045 : {
6046 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6047 : {
6048 0 : OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
6049 0 : if (nullptr == pGeom)
6050 0 : continue;
6051 :
6052 0 : const OGRErr eErr = pGeom->transform(poCT.get());
6053 0 : if (eErr == OGRERR_NONE)
6054 0 : continue;
6055 :
6056 0 : CPLError(CE_Failure, CPLE_AppDefined,
6057 : "Unable to transform geometry " CPL_FRMT_GIB
6058 : " from layer %s.",
6059 0 : poFeature->GetFID(), poSrcDefn->GetName());
6060 0 : return poDstLayer;
6061 : }
6062 : }
6063 :
6064 322 : poDstFeature->SetFID(poFeature->GetFID());
6065 :
6066 322 : CPLErrorReset();
6067 322 : if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)
6068 : {
6069 0 : return poDstLayer;
6070 : }
6071 322 : }
6072 : }
6073 : else
6074 : {
6075 3 : std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;
6076 : try
6077 : {
6078 3 : apoDstFeatures.resize(nGroupTransactions);
6079 : }
6080 0 : catch (const std::exception &e)
6081 : {
6082 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
6083 0 : return poDstLayer;
6084 : }
6085 3 : bool bStopTransfer = false;
6086 6 : while (!bStopTransfer)
6087 : {
6088 : /* --------------------------------------------------------------------
6089 : */
6090 : /* Fill the array with features. */
6091 : /* --------------------------------------------------------------------
6092 : */
6093 : // Number of features in the temporary array.
6094 3 : int nFeatCount = 0; // Used after for.
6095 33 : for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)
6096 : {
6097 : auto poFeature =
6098 33 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
6099 :
6100 33 : if (poFeature == nullptr)
6101 : {
6102 3 : bStopTransfer = true;
6103 3 : break;
6104 : }
6105 :
6106 30 : CPLErrorReset();
6107 30 : apoDstFeatures[nFeatCount] =
6108 60 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
6109 :
6110 60 : if (apoDstFeatures[nFeatCount]->SetFrom(
6111 60 : poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)
6112 : {
6113 0 : CPLError(CE_Failure, CPLE_AppDefined,
6114 : "Unable to translate feature " CPL_FRMT_GIB
6115 : " from layer %s.",
6116 0 : poFeature->GetFID(), poSrcDefn->GetName());
6117 0 : bStopTransfer = true;
6118 0 : poFeature.reset();
6119 0 : break;
6120 : }
6121 :
6122 30 : if (nullptr != poCT)
6123 : {
6124 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6125 : {
6126 : OGRGeometry *pGeom =
6127 0 : apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);
6128 0 : if (nullptr == pGeom)
6129 0 : continue;
6130 :
6131 0 : const OGRErr eErr = pGeom->transform(poCT.get());
6132 0 : if (eErr == OGRERR_NONE)
6133 0 : continue;
6134 :
6135 0 : CPLError(CE_Failure, CPLE_AppDefined,
6136 : "Unable to transform geometry " CPL_FRMT_GIB
6137 : " from layer %s.",
6138 0 : poFeature->GetFID(), poSrcDefn->GetName());
6139 0 : bStopTransfer = true;
6140 0 : poFeature.reset();
6141 0 : break;
6142 : }
6143 : }
6144 :
6145 30 : if (poFeature)
6146 : {
6147 30 : apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());
6148 : }
6149 : }
6150 :
6151 3 : CPLErrorReset();
6152 3 : bool bStopTransaction = false;
6153 6 : while (!bStopTransaction)
6154 : {
6155 3 : bStopTransaction = true;
6156 3 : if (poDstLayer->StartTransaction() != OGRERR_NONE)
6157 0 : break;
6158 33 : for (int i = 0; i < nFeatCount; ++i)
6159 : {
6160 30 : if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=
6161 : OGRERR_NONE)
6162 : {
6163 0 : bStopTransfer = true;
6164 0 : bStopTransaction = false;
6165 0 : break;
6166 : }
6167 30 : apoDstFeatures[i].reset();
6168 : }
6169 3 : if (bStopTransaction)
6170 : {
6171 3 : if (poDstLayer->CommitTransaction() != OGRERR_NONE)
6172 0 : break;
6173 : }
6174 : else
6175 : {
6176 0 : poDstLayer->RollbackTransaction();
6177 : }
6178 : }
6179 : }
6180 : }
6181 :
6182 134 : return poDstLayer;
6183 : }
6184 :
6185 : /************************************************************************/
6186 : /* DeleteLayer() */
6187 : /************************************************************************/
6188 :
6189 : /**
6190 : \fn GDALDataset::DeleteLayer(int)
6191 : \brief Delete the indicated layer from the datasource.
6192 :
6193 : If this method is supported
6194 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
6195 :
6196 : This method is the same as the C function GDALDatasetDeleteLayer() and the
6197 : deprecated OGR_DS_DeleteLayer().
6198 :
6199 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6200 :
6201 : @param iLayer the index of the layer to delete.
6202 :
6203 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
6204 : layers is not supported for this datasource.
6205 :
6206 : */
6207 :
6208 389 : OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)
6209 :
6210 : {
6211 389 : CPLError(CE_Failure, CPLE_NotSupported,
6212 : "DeleteLayer() not supported by this dataset.");
6213 :
6214 389 : return OGRERR_UNSUPPORTED_OPERATION;
6215 : }
6216 :
6217 : /************************************************************************/
6218 : /* GetLayerByName() */
6219 : /************************************************************************/
6220 :
6221 : /**
6222 : \brief Fetch a layer by name.
6223 :
6224 : The returned layer remains owned by the
6225 : GDALDataset and should not be deleted by the application.
6226 :
6227 : This method is the same as the C function GDALDatasetGetLayerByName() and the
6228 : deprecated OGR_DS_GetLayerByName().
6229 :
6230 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6231 :
6232 : @param pszName the layer name of the layer to fetch.
6233 :
6234 : @return the layer, or NULL if Layer is not found or an error occurs.
6235 : */
6236 :
6237 29518 : OGRLayer *GDALDataset::GetLayerByName(const char *pszName)
6238 :
6239 : {
6240 59036 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
6241 :
6242 29518 : if (!pszName)
6243 0 : return nullptr;
6244 :
6245 : // First a case sensitive check.
6246 932002 : for (int i = 0; i < GetLayerCount(); ++i)
6247 : {
6248 913983 : OGRLayer *poLayer = GetLayer(i);
6249 :
6250 913983 : if (strcmp(pszName, poLayer->GetName()) == 0)
6251 11499 : return poLayer;
6252 : }
6253 :
6254 : // Then case insensitive.
6255 893589 : for (int i = 0; i < GetLayerCount(); ++i)
6256 : {
6257 875792 : OGRLayer *poLayer = GetLayer(i);
6258 :
6259 875792 : if (EQUAL(pszName, poLayer->GetName()))
6260 222 : return poLayer;
6261 : }
6262 :
6263 17797 : return nullptr;
6264 : }
6265 :
6266 : //! @cond Doxygen_Suppress
6267 : /************************************************************************/
6268 : /* ProcessSQLCreateIndex() */
6269 : /* */
6270 : /* The correct syntax for creating an index in our dialect of */
6271 : /* SQL is: */
6272 : /* */
6273 : /* CREATE INDEX ON <layername> USING <columnname> */
6274 : /************************************************************************/
6275 :
6276 28 : OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)
6277 :
6278 : {
6279 28 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6280 :
6281 : /* -------------------------------------------------------------------- */
6282 : /* Do some general syntax checking. */
6283 : /* -------------------------------------------------------------------- */
6284 56 : if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||
6285 84 : !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||
6286 28 : !EQUAL(papszTokens[4], "USING"))
6287 : {
6288 0 : CSLDestroy(papszTokens);
6289 0 : CPLError(CE_Failure, CPLE_AppDefined,
6290 : "Syntax error in CREATE INDEX command.\n"
6291 : "Was '%s'\n"
6292 : "Should be of form 'CREATE INDEX ON <table> USING <field>'",
6293 : pszSQLCommand);
6294 0 : return OGRERR_FAILURE;
6295 : }
6296 :
6297 : /* -------------------------------------------------------------------- */
6298 : /* Find the named layer. */
6299 : /* -------------------------------------------------------------------- */
6300 28 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6301 28 : if (poLayer == nullptr)
6302 : {
6303 0 : CPLError(CE_Failure, CPLE_AppDefined,
6304 : "CREATE INDEX ON failed, no such layer as `%s'.",
6305 0 : papszTokens[3]);
6306 0 : CSLDestroy(papszTokens);
6307 0 : return OGRERR_FAILURE;
6308 : }
6309 :
6310 : /* -------------------------------------------------------------------- */
6311 : /* Does this layer even support attribute indexes? */
6312 : /* -------------------------------------------------------------------- */
6313 28 : if (poLayer->GetIndex() == nullptr)
6314 : {
6315 0 : CPLError(CE_Failure, CPLE_AppDefined,
6316 : "CREATE INDEX ON not supported by this driver.");
6317 0 : CSLDestroy(papszTokens);
6318 0 : return OGRERR_FAILURE;
6319 : }
6320 :
6321 : /* -------------------------------------------------------------------- */
6322 : /* Find the named field. */
6323 : /* -------------------------------------------------------------------- */
6324 28 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6325 :
6326 28 : CSLDestroy(papszTokens);
6327 :
6328 28 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6329 : {
6330 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6331 : pszSQLCommand);
6332 0 : return OGRERR_FAILURE;
6333 : }
6334 :
6335 : /* -------------------------------------------------------------------- */
6336 : /* Attempt to create the index. */
6337 : /* -------------------------------------------------------------------- */
6338 28 : OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
6339 28 : if (eErr == OGRERR_NONE)
6340 : {
6341 28 : eErr = poLayer->GetIndex()->IndexAllFeatures(i);
6342 : }
6343 : else
6344 : {
6345 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
6346 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
6347 : }
6348 :
6349 28 : return eErr;
6350 : }
6351 :
6352 : /************************************************************************/
6353 : /* ProcessSQLDropIndex() */
6354 : /* */
6355 : /* The correct syntax for dropping one or more indexes in */
6356 : /* the OGR SQL dialect is: */
6357 : /* */
6358 : /* DROP INDEX ON <layername> [USING <columnname>] */
6359 : /************************************************************************/
6360 :
6361 10 : OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)
6362 :
6363 : {
6364 10 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6365 :
6366 : /* -------------------------------------------------------------------- */
6367 : /* Do some general syntax checking. */
6368 : /* -------------------------------------------------------------------- */
6369 20 : if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||
6370 10 : !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||
6371 30 : !EQUAL(papszTokens[2], "ON") ||
6372 10 : (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))
6373 : {
6374 0 : CSLDestroy(papszTokens);
6375 0 : CPLError(CE_Failure, CPLE_AppDefined,
6376 : "Syntax error in DROP INDEX command.\n"
6377 : "Was '%s'\n"
6378 : "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
6379 : pszSQLCommand);
6380 0 : return OGRERR_FAILURE;
6381 : }
6382 :
6383 : /* -------------------------------------------------------------------- */
6384 : /* Find the named layer. */
6385 : /* -------------------------------------------------------------------- */
6386 10 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6387 10 : if (poLayer == nullptr)
6388 : {
6389 0 : CPLError(CE_Failure, CPLE_AppDefined,
6390 : "DROP INDEX ON failed, no such layer as `%s'.",
6391 0 : papszTokens[3]);
6392 0 : CSLDestroy(papszTokens);
6393 0 : return OGRERR_FAILURE;
6394 : }
6395 :
6396 : /* -------------------------------------------------------------------- */
6397 : /* Does this layer even support attribute indexes? */
6398 : /* -------------------------------------------------------------------- */
6399 10 : if (poLayer->GetIndex() == nullptr)
6400 : {
6401 0 : CPLError(CE_Failure, CPLE_AppDefined,
6402 : "Indexes not supported by this driver.");
6403 0 : CSLDestroy(papszTokens);
6404 0 : return OGRERR_FAILURE;
6405 : }
6406 :
6407 : /* -------------------------------------------------------------------- */
6408 : /* If we were not given a field name, drop all indexes. */
6409 : /* -------------------------------------------------------------------- */
6410 10 : if (CSLCount(papszTokens) == 4)
6411 : {
6412 0 : for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)
6413 : {
6414 : OGRAttrIndex *poAttrIndex;
6415 :
6416 0 : poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
6417 0 : if (poAttrIndex != nullptr)
6418 : {
6419 0 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6420 0 : if (eErr != OGRERR_NONE)
6421 : {
6422 0 : CSLDestroy(papszTokens);
6423 0 : return eErr;
6424 : }
6425 : }
6426 : }
6427 :
6428 0 : CSLDestroy(papszTokens);
6429 0 : return OGRERR_NONE;
6430 : }
6431 :
6432 : /* -------------------------------------------------------------------- */
6433 : /* Find the named field. */
6434 : /* -------------------------------------------------------------------- */
6435 10 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6436 10 : CSLDestroy(papszTokens);
6437 :
6438 10 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6439 : {
6440 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6441 : pszSQLCommand);
6442 0 : return OGRERR_FAILURE;
6443 : }
6444 :
6445 : /* -------------------------------------------------------------------- */
6446 : /* Attempt to drop the index. */
6447 : /* -------------------------------------------------------------------- */
6448 10 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6449 :
6450 10 : return eErr;
6451 : }
6452 :
6453 : /************************************************************************/
6454 : /* ProcessSQLDropTable() */
6455 : /* */
6456 : /* The correct syntax for dropping a table (layer) in the OGR SQL */
6457 : /* dialect is: */
6458 : /* */
6459 : /* DROP TABLE <layername> */
6460 : /************************************************************************/
6461 :
6462 500 : OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)
6463 :
6464 : {
6465 500 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6466 :
6467 : /* -------------------------------------------------------------------- */
6468 : /* Do some general syntax checking. */
6469 : /* -------------------------------------------------------------------- */
6470 1000 : if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||
6471 500 : !EQUAL(papszTokens[1], "TABLE"))
6472 : {
6473 0 : CSLDestroy(papszTokens);
6474 0 : CPLError(CE_Failure, CPLE_AppDefined,
6475 : "Syntax error in DROP TABLE command.\n"
6476 : "Was '%s'\n"
6477 : "Should be of form 'DROP TABLE <table>'",
6478 : pszSQLCommand);
6479 0 : return OGRERR_FAILURE;
6480 : }
6481 :
6482 : /* -------------------------------------------------------------------- */
6483 : /* Find the named layer. */
6484 : /* -------------------------------------------------------------------- */
6485 500 : OGRLayer *poLayer = nullptr;
6486 :
6487 500 : int i = 0; // Used after for.
6488 40199 : for (; i < GetLayerCount(); ++i)
6489 : {
6490 40199 : poLayer = GetLayer(i);
6491 :
6492 40199 : if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))
6493 500 : break;
6494 39699 : poLayer = nullptr;
6495 : }
6496 :
6497 500 : if (poLayer == nullptr)
6498 : {
6499 0 : CPLError(CE_Failure, CPLE_AppDefined,
6500 0 : "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
6501 0 : CSLDestroy(papszTokens);
6502 0 : return OGRERR_FAILURE;
6503 : }
6504 :
6505 500 : CSLDestroy(papszTokens);
6506 :
6507 : /* -------------------------------------------------------------------- */
6508 : /* Delete it. */
6509 : /* -------------------------------------------------------------------- */
6510 :
6511 500 : return DeleteLayer(i);
6512 : }
6513 :
6514 : //! @endcond
6515 :
6516 : /************************************************************************/
6517 : /* GDALDatasetParseSQLType() */
6518 : /************************************************************************/
6519 :
6520 : /* All arguments will be altered */
6521 6 : static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
6522 : int &nPrecision)
6523 : {
6524 6 : char *pszParenthesis = strchr(pszType, '(');
6525 6 : if (pszParenthesis)
6526 : {
6527 4 : nWidth = atoi(pszParenthesis + 1);
6528 4 : *pszParenthesis = '\0';
6529 4 : char *pszComma = strchr(pszParenthesis + 1, ',');
6530 4 : if (pszComma)
6531 2 : nPrecision = atoi(pszComma + 1);
6532 : }
6533 :
6534 6 : OGRFieldType eType = OFTString;
6535 6 : if (EQUAL(pszType, "INTEGER"))
6536 0 : eType = OFTInteger;
6537 6 : else if (EQUAL(pszType, "INTEGER[]"))
6538 0 : eType = OFTIntegerList;
6539 6 : else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||
6540 4 : EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
6541 4 : EQUAL(pszType, "REAL") /* unofficial alias */)
6542 2 : eType = OFTReal;
6543 4 : else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||
6544 4 : EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
6545 4 : EQUAL(pszType, "REAL[]") /* unofficial alias */)
6546 0 : eType = OFTRealList;
6547 4 : else if (EQUAL(pszType, "CHARACTER") ||
6548 0 : EQUAL(pszType, "TEXT") /* unofficial alias */ ||
6549 0 : EQUAL(pszType, "STRING") /* unofficial alias */ ||
6550 0 : EQUAL(pszType, "VARCHAR") /* unofficial alias */)
6551 4 : eType = OFTString;
6552 0 : else if (EQUAL(pszType, "TEXT[]") ||
6553 0 : EQUAL(pszType, "STRING[]") /* unofficial alias */ ||
6554 0 : EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
6555 0 : eType = OFTStringList;
6556 0 : else if (EQUAL(pszType, "DATE"))
6557 0 : eType = OFTDate;
6558 0 : else if (EQUAL(pszType, "TIME"))
6559 0 : eType = OFTTime;
6560 0 : else if (EQUAL(pszType, "TIMESTAMP") ||
6561 0 : EQUAL(pszType, "DATETIME") /* unofficial alias */)
6562 0 : eType = OFTDateTime;
6563 : else
6564 0 : CPLError(CE_Warning, CPLE_NotSupported,
6565 : "Unsupported column type '%s'. Defaulting to VARCHAR",
6566 : pszType);
6567 :
6568 6 : return eType;
6569 : }
6570 :
6571 : /************************************************************************/
6572 : /* ProcessSQLAlterTableAddColumn() */
6573 : /* */
6574 : /* The correct syntax for adding a column in the OGR SQL */
6575 : /* dialect is: */
6576 : /* */
6577 : /* ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
6578 : /************************************************************************/
6579 :
6580 : //! @cond Doxygen_Suppress
6581 2 : OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)
6582 :
6583 : {
6584 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6585 :
6586 : /* -------------------------------------------------------------------- */
6587 : /* Do some general syntax checking. */
6588 : /* -------------------------------------------------------------------- */
6589 2 : const char *pszLayerName = nullptr;
6590 2 : const char *pszColumnName = nullptr;
6591 2 : int iTypeIndex = 0;
6592 2 : const int nTokens = CSLCount(papszTokens);
6593 :
6594 2 : if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6595 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&
6596 2 : EQUAL(papszTokens[4], "COLUMN"))
6597 : {
6598 1 : pszLayerName = papszTokens[2];
6599 1 : pszColumnName = papszTokens[5];
6600 1 : iTypeIndex = 6;
6601 : }
6602 1 : else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&
6603 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))
6604 : {
6605 1 : pszLayerName = papszTokens[2];
6606 1 : pszColumnName = papszTokens[4];
6607 1 : iTypeIndex = 5;
6608 : }
6609 : else
6610 : {
6611 0 : CSLDestroy(papszTokens);
6612 0 : CPLError(CE_Failure, CPLE_AppDefined,
6613 : "Syntax error in ALTER TABLE ADD COLUMN command.\n"
6614 : "Was '%s'\n"
6615 : "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
6616 : "<columnname> <columntype>'",
6617 : pszSQLCommand);
6618 0 : return OGRERR_FAILURE;
6619 : }
6620 :
6621 : /* -------------------------------------------------------------------- */
6622 : /* Merge type components into a single string if there were split */
6623 : /* with spaces */
6624 : /* -------------------------------------------------------------------- */
6625 4 : CPLString osType;
6626 6 : for (int i = iTypeIndex; i < nTokens; ++i)
6627 : {
6628 4 : osType += papszTokens[i];
6629 4 : CPLFree(papszTokens[i]);
6630 : }
6631 2 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6632 2 : papszTokens[iTypeIndex + 1] = nullptr;
6633 :
6634 : /* -------------------------------------------------------------------- */
6635 : /* Find the named layer. */
6636 : /* -------------------------------------------------------------------- */
6637 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6638 2 : if (poLayer == nullptr)
6639 : {
6640 0 : CPLError(CE_Failure, CPLE_AppDefined,
6641 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6642 : pszLayerName);
6643 0 : CSLDestroy(papszTokens);
6644 0 : return OGRERR_FAILURE;
6645 : }
6646 :
6647 : /* -------------------------------------------------------------------- */
6648 : /* Add column. */
6649 : /* -------------------------------------------------------------------- */
6650 :
6651 2 : int nWidth = 0;
6652 2 : int nPrecision = 0;
6653 2 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6654 4 : OGRFieldDefn oFieldDefn(pszColumnName, eType);
6655 2 : oFieldDefn.SetWidth(nWidth);
6656 2 : oFieldDefn.SetPrecision(nPrecision);
6657 :
6658 2 : CSLDestroy(papszTokens);
6659 :
6660 2 : return poLayer->CreateField(&oFieldDefn);
6661 : }
6662 :
6663 : /************************************************************************/
6664 : /* ProcessSQLAlterTableDropColumn() */
6665 : /* */
6666 : /* The correct syntax for dropping a column in the OGR SQL */
6667 : /* dialect is: */
6668 : /* */
6669 : /* ALTER TABLE <layername> DROP [COLUMN] <columnname> */
6670 : /************************************************************************/
6671 :
6672 2 : OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)
6673 :
6674 : {
6675 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6676 :
6677 : /* -------------------------------------------------------------------- */
6678 : /* Do some general syntax checking. */
6679 : /* -------------------------------------------------------------------- */
6680 2 : const char *pszLayerName = nullptr;
6681 2 : const char *pszColumnName = nullptr;
6682 3 : if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&
6683 4 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&
6684 1 : EQUAL(papszTokens[4], "COLUMN"))
6685 : {
6686 1 : pszLayerName = papszTokens[2];
6687 1 : pszColumnName = papszTokens[5];
6688 : }
6689 2 : else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&
6690 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))
6691 : {
6692 1 : pszLayerName = papszTokens[2];
6693 1 : pszColumnName = papszTokens[4];
6694 : }
6695 : else
6696 : {
6697 0 : CSLDestroy(papszTokens);
6698 0 : CPLError(CE_Failure, CPLE_AppDefined,
6699 : "Syntax error in ALTER TABLE DROP COLUMN command.\n"
6700 : "Was '%s'\n"
6701 : "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
6702 : "<columnname>'",
6703 : pszSQLCommand);
6704 0 : return OGRERR_FAILURE;
6705 : }
6706 :
6707 : /* -------------------------------------------------------------------- */
6708 : /* Find the named layer. */
6709 : /* -------------------------------------------------------------------- */
6710 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6711 2 : if (poLayer == nullptr)
6712 : {
6713 0 : CPLError(CE_Failure, CPLE_AppDefined,
6714 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6715 : pszLayerName);
6716 0 : CSLDestroy(papszTokens);
6717 0 : return OGRERR_FAILURE;
6718 : }
6719 :
6720 : /* -------------------------------------------------------------------- */
6721 : /* Find the field. */
6722 : /* -------------------------------------------------------------------- */
6723 :
6724 2 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6725 2 : if (nFieldIndex < 0)
6726 : {
6727 0 : CPLError(CE_Failure, CPLE_AppDefined,
6728 : "%s failed, no such field as `%s'.", pszSQLCommand,
6729 : pszColumnName);
6730 0 : CSLDestroy(papszTokens);
6731 0 : return OGRERR_FAILURE;
6732 : }
6733 :
6734 : /* -------------------------------------------------------------------- */
6735 : /* Remove it. */
6736 : /* -------------------------------------------------------------------- */
6737 :
6738 2 : CSLDestroy(papszTokens);
6739 :
6740 2 : return poLayer->DeleteField(nFieldIndex);
6741 : }
6742 :
6743 : /************************************************************************/
6744 : /* ProcessSQLAlterTableRenameColumn() */
6745 : /* */
6746 : /* The correct syntax for renaming a column in the OGR SQL */
6747 : /* dialect is: */
6748 : /* */
6749 : /* ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
6750 : /************************************************************************/
6751 :
6752 2 : OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)
6753 :
6754 : {
6755 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6756 :
6757 : /* -------------------------------------------------------------------- */
6758 : /* Do some general syntax checking. */
6759 : /* -------------------------------------------------------------------- */
6760 2 : const char *pszLayerName = nullptr;
6761 2 : const char *pszOldColName = nullptr;
6762 2 : const char *pszNewColName = nullptr;
6763 3 : if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&
6764 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&
6765 3 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))
6766 : {
6767 1 : pszLayerName = papszTokens[2];
6768 1 : pszOldColName = papszTokens[5];
6769 1 : pszNewColName = papszTokens[7];
6770 : }
6771 2 : else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&
6772 1 : EQUAL(papszTokens[1], "TABLE") &&
6773 2 : EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))
6774 : {
6775 1 : pszLayerName = papszTokens[2];
6776 1 : pszOldColName = papszTokens[4];
6777 1 : pszNewColName = papszTokens[6];
6778 : }
6779 : else
6780 : {
6781 0 : CSLDestroy(papszTokens);
6782 0 : CPLError(CE_Failure, CPLE_AppDefined,
6783 : "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
6784 : "Was '%s'\n"
6785 : "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
6786 : "<columnname> TO <newname>'",
6787 : pszSQLCommand);
6788 0 : return OGRERR_FAILURE;
6789 : }
6790 :
6791 : /* -------------------------------------------------------------------- */
6792 : /* Find the named layer. */
6793 : /* -------------------------------------------------------------------- */
6794 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6795 2 : if (poLayer == nullptr)
6796 : {
6797 0 : CPLError(CE_Failure, CPLE_AppDefined,
6798 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6799 : pszLayerName);
6800 0 : CSLDestroy(papszTokens);
6801 0 : return OGRERR_FAILURE;
6802 : }
6803 :
6804 : /* -------------------------------------------------------------------- */
6805 : /* Find the field. */
6806 : /* -------------------------------------------------------------------- */
6807 :
6808 : const int nFieldIndex =
6809 2 : poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
6810 2 : if (nFieldIndex < 0)
6811 : {
6812 0 : CPLError(CE_Failure, CPLE_AppDefined,
6813 : "%s failed, no such field as `%s'.", pszSQLCommand,
6814 : pszOldColName);
6815 0 : CSLDestroy(papszTokens);
6816 0 : return OGRERR_FAILURE;
6817 : }
6818 :
6819 : /* -------------------------------------------------------------------- */
6820 : /* Rename column. */
6821 : /* -------------------------------------------------------------------- */
6822 : OGRFieldDefn *poOldFieldDefn =
6823 2 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6824 4 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6825 2 : oNewFieldDefn.SetName(pszNewColName);
6826 :
6827 2 : CSLDestroy(papszTokens);
6828 :
6829 2 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6830 2 : ALTER_NAME_FLAG);
6831 : }
6832 :
6833 : /************************************************************************/
6834 : /* ProcessSQLAlterTableAlterColumn() */
6835 : /* */
6836 : /* The correct syntax for altering the type of a column in the */
6837 : /* OGR SQL dialect is: */
6838 : /* */
6839 : /* ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
6840 : /************************************************************************/
6841 :
6842 4 : OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)
6843 :
6844 : {
6845 4 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6846 :
6847 : /* -------------------------------------------------------------------- */
6848 : /* Do some general syntax checking. */
6849 : /* -------------------------------------------------------------------- */
6850 4 : const char *pszLayerName = nullptr;
6851 4 : const char *pszColumnName = nullptr;
6852 4 : int iTypeIndex = 0;
6853 4 : const int nTokens = CSLCount(papszTokens);
6854 :
6855 4 : if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&
6856 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6857 2 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))
6858 : {
6859 2 : pszLayerName = papszTokens[2];
6860 2 : pszColumnName = papszTokens[5];
6861 2 : iTypeIndex = 7;
6862 : }
6863 2 : else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6864 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6865 2 : EQUAL(papszTokens[5], "TYPE"))
6866 : {
6867 2 : pszLayerName = papszTokens[2];
6868 2 : pszColumnName = papszTokens[4];
6869 2 : iTypeIndex = 6;
6870 : }
6871 : else
6872 : {
6873 0 : CSLDestroy(papszTokens);
6874 0 : CPLError(CE_Failure, CPLE_AppDefined,
6875 : "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
6876 : "Was '%s'\n"
6877 : "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
6878 : "<columnname> TYPE <columntype>'",
6879 : pszSQLCommand);
6880 0 : return OGRERR_FAILURE;
6881 : }
6882 :
6883 : /* -------------------------------------------------------------------- */
6884 : /* Merge type components into a single string if there were split */
6885 : /* with spaces */
6886 : /* -------------------------------------------------------------------- */
6887 8 : CPLString osType;
6888 8 : for (int i = iTypeIndex; i < nTokens; ++i)
6889 : {
6890 4 : osType += papszTokens[i];
6891 4 : CPLFree(papszTokens[i]);
6892 : }
6893 4 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6894 4 : papszTokens[iTypeIndex + 1] = nullptr;
6895 :
6896 : /* -------------------------------------------------------------------- */
6897 : /* Find the named layer. */
6898 : /* -------------------------------------------------------------------- */
6899 4 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6900 4 : if (poLayer == nullptr)
6901 : {
6902 0 : CPLError(CE_Failure, CPLE_AppDefined,
6903 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6904 : pszLayerName);
6905 0 : CSLDestroy(papszTokens);
6906 0 : return OGRERR_FAILURE;
6907 : }
6908 :
6909 : /* -------------------------------------------------------------------- */
6910 : /* Find the field. */
6911 : /* -------------------------------------------------------------------- */
6912 :
6913 : const int nFieldIndex =
6914 4 : poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6915 4 : if (nFieldIndex < 0)
6916 : {
6917 0 : CPLError(CE_Failure, CPLE_AppDefined,
6918 : "%s failed, no such field as `%s'.", pszSQLCommand,
6919 : pszColumnName);
6920 0 : CSLDestroy(papszTokens);
6921 0 : return OGRERR_FAILURE;
6922 : }
6923 :
6924 : /* -------------------------------------------------------------------- */
6925 : /* Alter column. */
6926 : /* -------------------------------------------------------------------- */
6927 :
6928 : OGRFieldDefn *poOldFieldDefn =
6929 4 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6930 8 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6931 :
6932 4 : int nWidth = 0;
6933 4 : int nPrecision = 0;
6934 4 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6935 4 : oNewFieldDefn.SetType(eType);
6936 4 : oNewFieldDefn.SetWidth(nWidth);
6937 4 : oNewFieldDefn.SetPrecision(nPrecision);
6938 :
6939 4 : int l_nFlags = 0;
6940 4 : if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
6941 2 : l_nFlags |= ALTER_TYPE_FLAG;
6942 4 : if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
6943 0 : poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
6944 4 : l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
6945 :
6946 4 : CSLDestroy(papszTokens);
6947 :
6948 4 : if (l_nFlags == 0)
6949 0 : return OGRERR_NONE;
6950 :
6951 4 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
6952 : }
6953 :
6954 : //! @endcond
6955 :
6956 : /************************************************************************/
6957 : /* ExecuteSQL() */
6958 : /************************************************************************/
6959 :
6960 : /**
6961 : \brief Execute an SQL statement against the data store.
6962 :
6963 : The result of an SQL query is either NULL for statements that are in error,
6964 : or that have no results set, or an OGRLayer pointer representing a results
6965 : set from the query. Note that this OGRLayer is in addition to the layers
6966 : in the data store and must be destroyed with
6967 : ReleaseResultSet() before the dataset is closed
6968 : (destroyed).
6969 :
6970 : This method is the same as the C function GDALDatasetExecuteSQL() and the
6971 : deprecated OGR_DS_ExecuteSQL().
6972 :
6973 : For more information on the SQL dialect supported internally by OGR
6974 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
6975 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
6976 : to the underlying RDBMS.
6977 :
6978 : Starting with OGR 1.10, the <a
6979 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
6980 : also be used.
6981 :
6982 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6983 :
6984 : @param pszStatement the SQL statement to execute.
6985 : @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
6986 : @param pszDialect allows control of the statement dialect. If set to NULL, the
6987 : OGR SQL engine will be used, except for RDBMS drivers that will use their
6988 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
6989 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
6990 :
6991 : @return an OGRLayer containing the results of the query. Deallocate with
6992 : ReleaseResultSet().
6993 :
6994 : */
6995 :
6996 3563 : OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,
6997 : OGRGeometry *poSpatialFilter,
6998 : const char *pszDialect)
6999 :
7000 : {
7001 3563 : return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
7002 : }
7003 :
7004 : //! @cond Doxygen_Suppress
7005 : OGRLayer *
7006 3571 : GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
7007 : const char *pszDialect,
7008 : swq_select_parse_options *poSelectParseOptions)
7009 :
7010 : {
7011 3571 : if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))
7012 : {
7013 : #ifdef SQLITE_ENABLED
7014 650 : return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
7015 650 : pszDialect);
7016 : #else
7017 : CPLError(CE_Failure, CPLE_NotSupported,
7018 : "The SQLite driver needs to be compiled to support the "
7019 : "SQLite SQL dialect");
7020 : return nullptr;
7021 : #endif
7022 : }
7023 :
7024 2921 : if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
7025 14 : !EQUAL(pszDialect, "OGRSQL"))
7026 : {
7027 6 : std::string osDialectList = "'OGRSQL'";
7028 : #ifdef SQLITE_ENABLED
7029 3 : osDialectList += ", 'SQLITE'";
7030 : #endif
7031 : const char *pszDialects =
7032 3 : GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);
7033 3 : if (pszDialects)
7034 : {
7035 : const CPLStringList aosTokens(
7036 0 : CSLTokenizeString2(pszDialects, " ", 0));
7037 0 : for (int i = 0; i < aosTokens.size(); ++i)
7038 : {
7039 0 : if (!EQUAL(aosTokens[i], "OGRSQL") &&
7040 0 : !EQUAL(aosTokens[i], "SQLITE"))
7041 : {
7042 0 : osDialectList += ", '";
7043 0 : osDialectList += aosTokens[i];
7044 0 : osDialectList += "'";
7045 : }
7046 : }
7047 : }
7048 3 : CPLError(CE_Warning, CPLE_NotSupported,
7049 : "Dialect '%s' is unsupported. Only supported dialects are %s. "
7050 : "Defaulting to OGRSQL",
7051 : pszDialect, osDialectList.c_str());
7052 : }
7053 :
7054 : /* -------------------------------------------------------------------- */
7055 : /* Handle CREATE INDEX statements specially. */
7056 : /* -------------------------------------------------------------------- */
7057 2921 : if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))
7058 : {
7059 28 : ProcessSQLCreateIndex(pszStatement);
7060 28 : return nullptr;
7061 : }
7062 :
7063 : /* -------------------------------------------------------------------- */
7064 : /* Handle DROP INDEX statements specially. */
7065 : /* -------------------------------------------------------------------- */
7066 2893 : if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))
7067 : {
7068 10 : ProcessSQLDropIndex(pszStatement);
7069 10 : return nullptr;
7070 : }
7071 :
7072 : /* -------------------------------------------------------------------- */
7073 : /* Handle DROP TABLE statements specially. */
7074 : /* -------------------------------------------------------------------- */
7075 2883 : if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))
7076 : {
7077 500 : ProcessSQLDropTable(pszStatement);
7078 500 : return nullptr;
7079 : }
7080 :
7081 : /* -------------------------------------------------------------------- */
7082 : /* Handle ALTER TABLE statements specially. */
7083 : /* -------------------------------------------------------------------- */
7084 2383 : if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))
7085 : {
7086 11 : char **papszTokens = CSLTokenizeString(pszStatement);
7087 11 : const int nTokens = CSLCount(papszTokens);
7088 11 : if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))
7089 : {
7090 2 : ProcessSQLAlterTableAddColumn(pszStatement);
7091 2 : CSLDestroy(papszTokens);
7092 2 : return nullptr;
7093 : }
7094 9 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))
7095 : {
7096 2 : ProcessSQLAlterTableDropColumn(pszStatement);
7097 2 : CSLDestroy(papszTokens);
7098 2 : return nullptr;
7099 : }
7100 7 : else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&
7101 1 : EQUAL(papszTokens[4], "TO"))
7102 : {
7103 1 : const char *pszSrcTableName = papszTokens[2];
7104 1 : const char *pszDstTableName = papszTokens[5];
7105 1 : auto poSrcLayer = GetLayerByName(pszSrcTableName);
7106 1 : if (poSrcLayer)
7107 : {
7108 1 : CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));
7109 : }
7110 : else
7111 : {
7112 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");
7113 : }
7114 1 : CSLDestroy(papszTokens);
7115 1 : return nullptr;
7116 : }
7117 6 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))
7118 : {
7119 2 : ProcessSQLAlterTableRenameColumn(pszStatement);
7120 2 : CSLDestroy(papszTokens);
7121 2 : return nullptr;
7122 : }
7123 4 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))
7124 : {
7125 4 : ProcessSQLAlterTableAlterColumn(pszStatement);
7126 4 : CSLDestroy(papszTokens);
7127 4 : return nullptr;
7128 : }
7129 : else
7130 : {
7131 0 : CPLError(CE_Failure, CPLE_AppDefined,
7132 : "Unsupported ALTER TABLE command : %s", pszStatement);
7133 0 : CSLDestroy(papszTokens);
7134 0 : return nullptr;
7135 : }
7136 : }
7137 :
7138 : /* -------------------------------------------------------------------- */
7139 : /* Preparse the SQL statement. */
7140 : /* -------------------------------------------------------------------- */
7141 2372 : swq_select *psSelectInfo = new swq_select();
7142 2372 : swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
7143 2372 : if (poSelectParseOptions != nullptr)
7144 8 : poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
7145 2372 : if (psSelectInfo->preparse(pszStatement,
7146 2372 : poCustomFuncRegistrar != nullptr) != CE_None)
7147 : {
7148 142 : delete psSelectInfo;
7149 142 : return nullptr;
7150 : }
7151 :
7152 : /* -------------------------------------------------------------------- */
7153 : /* If there is no UNION ALL, build result layer. */
7154 : /* -------------------------------------------------------------------- */
7155 2230 : if (psSelectInfo->poOtherSelect == nullptr)
7156 : {
7157 2224 : return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
7158 2224 : pszDialect, poSelectParseOptions);
7159 : }
7160 :
7161 : /* -------------------------------------------------------------------- */
7162 : /* Build result union layer. */
7163 : /* -------------------------------------------------------------------- */
7164 6 : int nSrcLayers = 0;
7165 6 : OGRLayer **papoSrcLayers = nullptr;
7166 :
7167 6 : do
7168 : {
7169 12 : swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
7170 12 : psSelectInfo->poOtherSelect = nullptr;
7171 :
7172 12 : OGRLayer *poLayer = BuildLayerFromSelectInfo(
7173 : psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
7174 12 : if (poLayer == nullptr)
7175 : {
7176 : // Each source layer owns an independent select info.
7177 0 : for (int i = 0; i < nSrcLayers; ++i)
7178 0 : delete papoSrcLayers[i];
7179 0 : CPLFree(papoSrcLayers);
7180 :
7181 : // So we just have to destroy the remaining select info.
7182 0 : delete psNextSelectInfo;
7183 :
7184 0 : return nullptr;
7185 : }
7186 : else
7187 : {
7188 24 : papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
7189 12 : papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
7190 12 : papoSrcLayers[nSrcLayers] = poLayer;
7191 12 : ++nSrcLayers;
7192 :
7193 12 : psSelectInfo = psNextSelectInfo;
7194 : }
7195 12 : } while (psSelectInfo != nullptr);
7196 :
7197 6 : return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
7198 : }
7199 :
7200 : //! @endcond
7201 :
7202 : /************************************************************************/
7203 : /* AbortSQL() */
7204 : /************************************************************************/
7205 :
7206 : /**
7207 : \brief Abort any SQL statement running in the data store.
7208 :
7209 : This function can be safely called from any thread (pending that the dataset
7210 : object is still alive). Driver implementations will make sure that it can be
7211 : called in a thread-safe way.
7212 :
7213 : This might not be implemented by all drivers. At time of writing, only SQLite,
7214 : GPKG and PG drivers implement it
7215 :
7216 : This method is the same as the C method GDALDatasetAbortSQL()
7217 :
7218 : @since GDAL 3.2.0
7219 :
7220 :
7221 : */
7222 :
7223 0 : OGRErr GDALDataset::AbortSQL()
7224 : {
7225 0 : CPLError(CE_Failure, CPLE_NotSupported,
7226 : "AbortSQL is not supported for this driver.");
7227 0 : return OGRERR_UNSUPPORTED_OPERATION;
7228 : }
7229 :
7230 : /************************************************************************/
7231 : /* BuildLayerFromSelectInfo() */
7232 : /************************************************************************/
7233 :
7234 : struct GDALSQLParseInfo
7235 : {
7236 : swq_field_list sFieldList;
7237 : int nExtraDSCount;
7238 : GDALDataset **papoExtraDS;
7239 : char *pszWHERE;
7240 : };
7241 :
7242 2236 : OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
7243 : swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
7244 : const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
7245 : {
7246 4472 : std::unique_ptr<swq_select> psSelectInfoUnique(psSelectInfo);
7247 :
7248 2236 : std::unique_ptr<OGRGenSQLResultsLayer> poResults;
7249 : GDALSQLParseInfo *psParseInfo =
7250 2236 : BuildParseInfo(psSelectInfoUnique.get(), poSelectParseOptions);
7251 :
7252 2236 : if (psParseInfo)
7253 : {
7254 2201 : const auto nErrorCounter = CPLGetErrorCounter();
7255 4402 : poResults = std::make_unique<OGRGenSQLResultsLayer>(
7256 2201 : this, std::move(psSelectInfoUnique), poSpatialFilter,
7257 4402 : psParseInfo->pszWHERE, pszDialect);
7258 2278 : if (CPLGetErrorCounter() > nErrorCounter &&
7259 77 : CPLGetLastErrorType() != CE_None)
7260 77 : poResults.reset();
7261 : }
7262 :
7263 2236 : DestroyParseInfo(psParseInfo);
7264 :
7265 4472 : return poResults.release();
7266 : }
7267 :
7268 : /************************************************************************/
7269 : /* DestroyParseInfo() */
7270 : /************************************************************************/
7271 :
7272 : //! @cond Doxygen_Suppress
7273 2305 : void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
7274 : {
7275 2305 : if (psParseInfo == nullptr)
7276 35 : return;
7277 :
7278 2270 : CPLFree(psParseInfo->sFieldList.names);
7279 2270 : CPLFree(psParseInfo->sFieldList.types);
7280 2270 : CPLFree(psParseInfo->sFieldList.table_ids);
7281 2270 : CPLFree(psParseInfo->sFieldList.ids);
7282 :
7283 : // Release the datasets we have opened with OGROpenShared()
7284 : // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
7285 : // has taken a reference on them, which it will release in its
7286 : // destructor.
7287 2277 : for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)
7288 7 : GDALClose(psParseInfo->papoExtraDS[iEDS]);
7289 :
7290 2270 : CPLFree(psParseInfo->papoExtraDS);
7291 2270 : CPLFree(psParseInfo->pszWHERE);
7292 2270 : CPLFree(psParseInfo);
7293 : }
7294 :
7295 : /************************************************************************/
7296 : /* BuildParseInfo() */
7297 : /************************************************************************/
7298 :
7299 : GDALSQLParseInfo *
7300 2270 : GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
7301 : swq_select_parse_options *poSelectParseOptions)
7302 : {
7303 2270 : int nFirstLayerFirstSpecialFieldIndex = 0;
7304 :
7305 : GDALSQLParseInfo *psParseInfo =
7306 2270 : static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
7307 :
7308 : /* -------------------------------------------------------------------- */
7309 : /* Validate that all the source tables are recognized, count */
7310 : /* fields. */
7311 : /* -------------------------------------------------------------------- */
7312 2270 : int nFieldCount = 0;
7313 :
7314 4608 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7315 : {
7316 2341 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7317 2341 : GDALDataset *poTableDS = this;
7318 :
7319 2341 : if (psTableDef->data_source != nullptr)
7320 : {
7321 7 : poTableDS = GDALDataset::FromHandle(
7322 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7323 7 : if (poTableDS == nullptr)
7324 : {
7325 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
7326 0 : CPLError(CE_Failure, CPLE_AppDefined,
7327 : "Unable to open secondary datasource "
7328 : "`%s' required by JOIN.",
7329 : psTableDef->data_source);
7330 :
7331 0 : DestroyParseInfo(psParseInfo);
7332 0 : return nullptr;
7333 : }
7334 :
7335 : // Keep in an array to release at the end of this function.
7336 14 : psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
7337 7 : psParseInfo->papoExtraDS,
7338 7 : sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
7339 7 : psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
7340 : }
7341 :
7342 : OGRLayer *poSrcLayer =
7343 2341 : poTableDS->GetLayerByName(psTableDef->table_name);
7344 :
7345 2341 : if (poSrcLayer == nullptr)
7346 : {
7347 3 : CPLError(CE_Failure, CPLE_AppDefined,
7348 : "SELECT from table %s failed, no such table/featureclass.",
7349 : psTableDef->table_name);
7350 :
7351 3 : DestroyParseInfo(psParseInfo);
7352 3 : return nullptr;
7353 : }
7354 :
7355 2338 : nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
7356 2338 : if (iTable == 0 ||
7357 34 : (poSelectParseOptions &&
7358 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7359 2301 : nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7360 :
7361 2338 : const char *pszFID = poSrcLayer->GetFIDColumn();
7362 2948 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7363 610 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7364 560 : nFieldCount++;
7365 : }
7366 :
7367 : /* -------------------------------------------------------------------- */
7368 : /* Build the field list for all indicated tables. */
7369 : /* -------------------------------------------------------------------- */
7370 :
7371 2267 : psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
7372 2267 : psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
7373 :
7374 2267 : psParseInfo->sFieldList.count = 0;
7375 2267 : psParseInfo->sFieldList.names = static_cast<char **>(
7376 2267 : CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7377 4534 : psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
7378 2267 : sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7379 2267 : psParseInfo->sFieldList.table_ids = static_cast<int *>(
7380 2267 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7381 2267 : psParseInfo->sFieldList.ids = static_cast<int *>(
7382 2267 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7383 :
7384 2267 : bool bIsFID64 = false;
7385 4605 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7386 : {
7387 2338 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7388 2338 : GDALDataset *poTableDS = this;
7389 :
7390 2338 : if (psTableDef->data_source != nullptr)
7391 : {
7392 7 : poTableDS = GDALDataset::FromHandle(
7393 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7394 7 : CPLAssert(poTableDS != nullptr);
7395 7 : poTableDS->Dereference();
7396 : }
7397 :
7398 : OGRLayer *poSrcLayer =
7399 2338 : poTableDS->GetLayerByName(psTableDef->table_name);
7400 :
7401 2338 : for (int iField = 0;
7402 18521 : iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)
7403 : {
7404 : OGRFieldDefn *poFDefn =
7405 16183 : poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
7406 16183 : const int iOutField = psParseInfo->sFieldList.count++;
7407 32366 : psParseInfo->sFieldList.names[iOutField] =
7408 16183 : const_cast<char *>(poFDefn->GetNameRef());
7409 16183 : if (poFDefn->GetType() == OFTInteger)
7410 : {
7411 4082 : if (poFDefn->GetSubType() == OFSTBoolean)
7412 160 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7413 : else
7414 3922 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7415 : }
7416 12101 : else if (poFDefn->GetType() == OFTInteger64)
7417 : {
7418 756 : if (poFDefn->GetSubType() == OFSTBoolean)
7419 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7420 : else
7421 756 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7422 : }
7423 11345 : else if (poFDefn->GetType() == OFTReal)
7424 2713 : psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
7425 8632 : else if (poFDefn->GetType() == OFTString)
7426 5578 : psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
7427 3054 : else if (poFDefn->GetType() == OFTTime)
7428 83 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
7429 2971 : else if (poFDefn->GetType() == OFTDate)
7430 143 : psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
7431 2828 : else if (poFDefn->GetType() == OFTDateTime)
7432 939 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
7433 : else
7434 1889 : psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
7435 :
7436 16183 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7437 16183 : psParseInfo->sFieldList.ids[iOutField] = iField;
7438 : }
7439 :
7440 2338 : if (iTable == 0)
7441 : {
7442 2267 : nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
7443 : }
7444 :
7445 2338 : if (iTable == 0 ||
7446 34 : (poSelectParseOptions &&
7447 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7448 : {
7449 :
7450 2301 : for (int iField = 0;
7451 4252 : iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7452 : iField++)
7453 : {
7454 : OGRGeomFieldDefn *poFDefn =
7455 1951 : poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
7456 1951 : const int iOutField = psParseInfo->sFieldList.count++;
7457 3902 : psParseInfo->sFieldList.names[iOutField] =
7458 1951 : const_cast<char *>(poFDefn->GetNameRef());
7459 1951 : if (*psParseInfo->sFieldList.names[iOutField] == '\0')
7460 1136 : psParseInfo->sFieldList.names[iOutField] =
7461 : const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
7462 1951 : psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
7463 :
7464 1951 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7465 1951 : psParseInfo->sFieldList.ids[iOutField] =
7466 1951 : GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
7467 : poSrcLayer->GetLayerDefn(), iField);
7468 : }
7469 : }
7470 :
7471 2339 : if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7472 1 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7473 : {
7474 1 : bIsFID64 = true;
7475 : }
7476 : }
7477 :
7478 : /* -------------------------------------------------------------------- */
7479 : /* Expand '*' in 'SELECT *' now before we add the pseudo fields */
7480 : /* -------------------------------------------------------------------- */
7481 2267 : const bool bAlwaysPrefixWithTableName =
7482 2309 : poSelectParseOptions &&
7483 42 : poSelectParseOptions->bAlwaysPrefixWithTableName;
7484 2267 : if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
7485 2267 : bAlwaysPrefixWithTableName) != CE_None)
7486 : {
7487 2 : DestroyParseInfo(psParseInfo);
7488 2 : return nullptr;
7489 : }
7490 :
7491 13590 : for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
7492 : {
7493 11325 : psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
7494 11325 : const_cast<char *>(SpecialFieldNames[iField]);
7495 11325 : psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
7496 11325 : (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
7497 : : SpecialFieldTypes[iField];
7498 11325 : psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
7499 11325 : psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
7500 11325 : nFirstLayerFirstSpecialFieldIndex + iField;
7501 11325 : psParseInfo->sFieldList.count++;
7502 : }
7503 :
7504 : /* In the case a layer has an explicit FID column name, then add it */
7505 : /* so it can be selected */
7506 4601 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7507 : {
7508 2336 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7509 2336 : GDALDataset *poTableDS = this;
7510 :
7511 2336 : if (psTableDef->data_source != nullptr)
7512 : {
7513 7 : poTableDS = GDALDataset::FromHandle(
7514 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7515 7 : CPLAssert(poTableDS != nullptr);
7516 7 : poTableDS->Dereference();
7517 : }
7518 :
7519 : OGRLayer *poSrcLayer =
7520 2336 : poTableDS->GetLayerByName(psTableDef->table_name);
7521 :
7522 2336 : const char *pszFID = poSrcLayer->GetFIDColumn();
7523 2946 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7524 610 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7525 : {
7526 560 : const int iOutField = psParseInfo->sFieldList.count++;
7527 560 : psParseInfo->sFieldList.names[iOutField] =
7528 : const_cast<char *>(pszFID);
7529 560 : if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7530 0 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7531 : {
7532 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7533 : }
7534 : else
7535 : {
7536 560 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7537 : }
7538 560 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7539 1120 : psParseInfo->sFieldList.ids[iOutField] =
7540 560 : poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
7541 : }
7542 : }
7543 :
7544 : /* -------------------------------------------------------------------- */
7545 : /* Finish the parse operation. */
7546 : /* -------------------------------------------------------------------- */
7547 2265 : if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
7548 : CE_None)
7549 : {
7550 30 : DestroyParseInfo(psParseInfo);
7551 30 : return nullptr;
7552 : }
7553 :
7554 : /* -------------------------------------------------------------------- */
7555 : /* Extract the WHERE expression to use separately. */
7556 : /* -------------------------------------------------------------------- */
7557 2235 : if (psSelectInfo->where_expr != nullptr)
7558 : {
7559 958 : psParseInfo->pszWHERE =
7560 958 : psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
7561 : // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
7562 : }
7563 :
7564 2235 : return psParseInfo;
7565 : }
7566 :
7567 : //! @endcond
7568 :
7569 : /************************************************************************/
7570 : /* ReleaseResultSet() */
7571 : /************************************************************************/
7572 :
7573 : /**
7574 : \brief Release results of ExecuteSQL().
7575 :
7576 : This method should only be used to deallocate OGRLayers resulting from
7577 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
7578 : results set before destroying the GDALDataset may cause errors.
7579 :
7580 : This method is the same as the C function GDALDatasetReleaseResultSet() and the
7581 : deprecated OGR_DS_ReleaseResultSet().
7582 :
7583 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7584 :
7585 : @param poResultsSet the result of a previous ExecuteSQL() call.
7586 : */
7587 :
7588 2154 : void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)
7589 :
7590 : {
7591 2154 : delete poResultsSet;
7592 2154 : }
7593 :
7594 : /************************************************************************/
7595 : /* GetStyleTable() */
7596 : /************************************************************************/
7597 :
7598 : /**
7599 : \brief Returns dataset style table.
7600 :
7601 : This method is the same as the C function GDALDatasetGetStyleTable() and the
7602 : deprecated OGR_DS_GetStyleTable().
7603 :
7604 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7605 :
7606 : @return pointer to a style table which should not be modified or freed by the
7607 : caller.
7608 : */
7609 :
7610 834 : OGRStyleTable *GDALDataset::GetStyleTable()
7611 : {
7612 834 : return m_poStyleTable;
7613 : }
7614 :
7615 : /************************************************************************/
7616 : /* SetStyleTableDirectly() */
7617 : /************************************************************************/
7618 :
7619 : /**
7620 : \brief Set dataset style table.
7621 :
7622 : This method operate exactly as SetStyleTable() except that it
7623 : assumes ownership of the passed table.
7624 :
7625 : This method is the same as the C function GDALDatasetSetStyleTableDirectly()
7626 : and the deprecated OGR_DS_SetStyleTableDirectly().
7627 :
7628 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7629 :
7630 : @param poStyleTable pointer to style table to set
7631 :
7632 : */
7633 0 : void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
7634 : {
7635 0 : if (m_poStyleTable)
7636 0 : delete m_poStyleTable;
7637 0 : m_poStyleTable = poStyleTable;
7638 0 : }
7639 :
7640 : /************************************************************************/
7641 : /* SetStyleTable() */
7642 : /************************************************************************/
7643 :
7644 : /**
7645 : \brief Set dataset style table.
7646 :
7647 : This method operate exactly as SetStyleTableDirectly() except
7648 : that it does not assume ownership of the passed table.
7649 :
7650 : This method is the same as the C function GDALDatasetSetStyleTable() and the
7651 : deprecated OGR_DS_SetStyleTable().
7652 :
7653 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7654 :
7655 : @param poStyleTable pointer to style table to set
7656 :
7657 : */
7658 :
7659 830 : void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
7660 : {
7661 830 : if (m_poStyleTable)
7662 0 : delete m_poStyleTable;
7663 830 : if (poStyleTable)
7664 1 : m_poStyleTable = poStyleTable->Clone();
7665 830 : }
7666 :
7667 : /************************************************************************/
7668 : /* IsGenericSQLDialect() */
7669 : /************************************************************************/
7670 :
7671 : //! @cond Doxygen_Suppress
7672 1748 : int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
7673 : {
7674 3188 : return pszDialect != nullptr &&
7675 3188 : (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
7676 : }
7677 :
7678 : //! @endcond
7679 :
7680 : /************************************************************************/
7681 : /* GetLayerCount() */
7682 : /************************************************************************/
7683 :
7684 : /**
7685 : \brief Get the number of layers in this dataset.
7686 :
7687 : This method is the same as the C function GDALDatasetGetLayerCount(),
7688 : and the deprecated OGR_DS_GetLayerCount().
7689 :
7690 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7691 :
7692 : @return layer count.
7693 : */
7694 :
7695 81358 : int GDALDataset::GetLayerCount()
7696 : {
7697 81358 : return 0;
7698 : }
7699 :
7700 : /************************************************************************/
7701 : /* GetLayer() */
7702 : /************************************************************************/
7703 :
7704 : /**
7705 : \fn GDALDataset::GetLayer(int)
7706 : \brief Fetch a layer by index.
7707 :
7708 : The returned layer remains owned by the
7709 : GDALDataset and should not be deleted by the application.
7710 :
7711 : See GetLayers() for a C++ iterator version of this method.
7712 :
7713 : This method is the same as the C function GDALDatasetGetLayer() and the
7714 : deprecated OGR_DS_GetLayer().
7715 :
7716 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7717 :
7718 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7719 :
7720 : @return the layer, or NULL if iLayer is out of range or an error occurs.
7721 :
7722 : @see GetLayers()
7723 : */
7724 :
7725 0 : OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer)
7726 : {
7727 0 : return nullptr;
7728 : }
7729 :
7730 : /************************************************************************/
7731 : /* IsLayerPrivate() */
7732 : /************************************************************************/
7733 :
7734 : /**
7735 : \fn GDALDataset::IsLayerPrivate(int)
7736 : \brief Returns true if the layer at the specified index is deemed a private or
7737 : system table, or an internal detail only.
7738 :
7739 : This method is the same as the C function GDALDatasetIsLayerPrivate().
7740 :
7741 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7742 :
7743 : @return true if the layer is a private or system table.
7744 :
7745 : @since GDAL 3.4
7746 : */
7747 :
7748 849 : bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const
7749 : {
7750 849 : return false;
7751 : }
7752 :
7753 : /************************************************************************/
7754 : /* ResetReading() */
7755 : /************************************************************************/
7756 :
7757 : /**
7758 : \brief Reset feature reading to start on the first feature.
7759 :
7760 : This affects GetNextFeature().
7761 :
7762 : Depending on drivers, this may also have the side effect of calling
7763 : OGRLayer::ResetReading() on the layers of this dataset.
7764 :
7765 : This method is the same as the C function GDALDatasetResetReading().
7766 :
7767 : @since GDAL 2.2
7768 : */
7769 7 : void GDALDataset::ResetReading()
7770 : {
7771 7 : if (!m_poPrivate)
7772 0 : return;
7773 7 : m_poPrivate->nCurrentLayerIdx = 0;
7774 7 : m_poPrivate->nLayerCount = -1;
7775 7 : m_poPrivate->poCurrentLayer = nullptr;
7776 7 : m_poPrivate->nFeatureReadInLayer = 0;
7777 7 : m_poPrivate->nFeatureReadInDataset = 0;
7778 7 : m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
7779 7 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
7780 : }
7781 :
7782 : /************************************************************************/
7783 : /* GDALDatasetResetReading() */
7784 : /************************************************************************/
7785 :
7786 : /**
7787 : \brief Reset feature reading to start on the first feature.
7788 :
7789 : This affects GDALDatasetGetNextFeature().
7790 :
7791 : Depending on drivers, this may also have the side effect of calling
7792 : OGR_L_ResetReading() on the layers of this dataset.
7793 :
7794 : This method is the same as the C++ method GDALDataset::ResetReading()
7795 :
7796 : @param hDS dataset handle
7797 : @since GDAL 2.2
7798 : */
7799 14 : void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)
7800 : {
7801 14 : VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
7802 :
7803 14 : return GDALDataset::FromHandle(hDS)->ResetReading();
7804 : }
7805 :
7806 : /************************************************************************/
7807 : /* GetNextFeature() */
7808 : /************************************************************************/
7809 :
7810 : /**
7811 : \brief Fetch the next available feature from this dataset.
7812 :
7813 : This method is intended for the few drivers where OGRLayer::GetNextFeature()
7814 : is not efficient, but in general OGRLayer::GetNextFeature() is a more
7815 : natural API.
7816 :
7817 : See GetFeatures() for a C++ iterator version of this method.
7818 :
7819 : The returned feature becomes the responsibility of the caller to
7820 : delete with OGRFeature::DestroyFeature().
7821 :
7822 : Depending on the driver, this method may return features from layers in a
7823 : non sequential way. This is what may happen when the
7824 : ODsCRandomLayerRead capability is declared (for example for the
7825 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7826 : advised to use GDALDataset::GetNextFeature() instead of
7827 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7828 : implementation.
7829 :
7830 : The default implementation, used by most drivers, will
7831 : however iterate over each layer, and then over each feature within this
7832 : layer.
7833 :
7834 : This method takes into account spatial and attribute filters set on layers that
7835 : will be iterated upon.
7836 :
7837 : The ResetReading() method can be used to start at the beginning again.
7838 :
7839 : Depending on drivers, this may also have the side effect of calling
7840 : OGRLayer::GetNextFeature() on the layers of this dataset.
7841 :
7842 : This method is the same as the C function GDALDatasetGetNextFeature().
7843 :
7844 : @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
7845 : layer to which the object belongs to, or NULL.
7846 : It is possible that the output of *ppoBelongingLayer
7847 : to be NULL despite the feature not being NULL.
7848 : @param pdfProgressPct a pointer to a double variable to receive the
7849 : percentage progress (in [0,1] range), or NULL.
7850 : On return, the pointed value might be negative if
7851 : determining the progress is not possible.
7852 : @param pfnProgress a progress callback to report progress (for
7853 : GetNextFeature() calls that might have a long
7854 : duration) and offer cancellation possibility, or NULL.
7855 : @param pProgressData user data provided to pfnProgress, or NULL
7856 : @return a feature, or NULL if no more features are available.
7857 : @since GDAL 2.2
7858 : @see GetFeatures()
7859 : */
7860 :
7861 60 : OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,
7862 : double *pdfProgressPct,
7863 : GDALProgressFunc pfnProgress,
7864 : void *pProgressData)
7865 : {
7866 60 : if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)
7867 : {
7868 2 : if (ppoBelongingLayer != nullptr)
7869 2 : *ppoBelongingLayer = nullptr;
7870 2 : if (pdfProgressPct != nullptr)
7871 1 : *pdfProgressPct = 1.0;
7872 2 : if (pfnProgress != nullptr)
7873 0 : pfnProgress(1.0, "", pProgressData);
7874 2 : return nullptr;
7875 : }
7876 :
7877 58 : if (m_poPrivate->poCurrentLayer == nullptr &&
7878 8 : (pdfProgressPct != nullptr || pfnProgress != nullptr))
7879 : {
7880 1 : if (m_poPrivate->nLayerCount < 0)
7881 : {
7882 1 : m_poPrivate->nLayerCount = GetLayerCount();
7883 : }
7884 :
7885 1 : if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)
7886 : {
7887 1 : m_poPrivate->nTotalFeatures = 0;
7888 5 : for (int i = 0; i < m_poPrivate->nLayerCount; i++)
7889 : {
7890 4 : OGRLayer *poLayer = GetLayer(i);
7891 8 : if (poLayer == nullptr ||
7892 4 : !poLayer->TestCapability(OLCFastFeatureCount))
7893 : {
7894 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7895 0 : break;
7896 : }
7897 4 : GIntBig nCount = poLayer->GetFeatureCount(FALSE);
7898 4 : if (nCount < 0)
7899 : {
7900 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7901 0 : break;
7902 : }
7903 4 : m_poPrivate->nTotalFeatures += nCount;
7904 : }
7905 : }
7906 : }
7907 :
7908 : while (true)
7909 : {
7910 71 : if (m_poPrivate->poCurrentLayer == nullptr)
7911 : {
7912 44 : m_poPrivate->poCurrentLayer =
7913 22 : GetLayer(m_poPrivate->nCurrentLayerIdx);
7914 22 : if (m_poPrivate->poCurrentLayer == nullptr)
7915 : {
7916 7 : m_poPrivate->nCurrentLayerIdx = -1;
7917 7 : if (ppoBelongingLayer != nullptr)
7918 7 : *ppoBelongingLayer = nullptr;
7919 7 : if (pdfProgressPct != nullptr)
7920 1 : *pdfProgressPct = 1.0;
7921 7 : return nullptr;
7922 : }
7923 15 : m_poPrivate->poCurrentLayer->ResetReading();
7924 15 : m_poPrivate->nFeatureReadInLayer = 0;
7925 15 : if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)
7926 : {
7927 0 : if (m_poPrivate->poCurrentLayer->TestCapability(
7928 0 : OLCFastFeatureCount))
7929 0 : m_poPrivate->nTotalFeaturesInLayer =
7930 0 : m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
7931 : else
7932 0 : m_poPrivate->nTotalFeaturesInLayer = 0;
7933 : }
7934 : }
7935 64 : OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
7936 64 : if (poFeature == nullptr)
7937 : {
7938 13 : m_poPrivate->nCurrentLayerIdx++;
7939 13 : m_poPrivate->poCurrentLayer = nullptr;
7940 13 : continue;
7941 : }
7942 :
7943 51 : m_poPrivate->nFeatureReadInLayer++;
7944 51 : m_poPrivate->nFeatureReadInDataset++;
7945 51 : if (pdfProgressPct != nullptr || pfnProgress != nullptr)
7946 : {
7947 4 : double dfPct = 0.0;
7948 4 : if (m_poPrivate->nTotalFeatures > 0)
7949 : {
7950 4 : dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
7951 4 : m_poPrivate->nTotalFeatures;
7952 : }
7953 : else
7954 : {
7955 0 : dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /
7956 0 : m_poPrivate->nLayerCount;
7957 0 : if (m_poPrivate->nTotalFeaturesInLayer > 0)
7958 : {
7959 0 : dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
7960 0 : m_poPrivate->nTotalFeaturesInLayer /
7961 0 : m_poPrivate->nLayerCount;
7962 : }
7963 : }
7964 4 : if (pdfProgressPct)
7965 4 : *pdfProgressPct = dfPct;
7966 4 : if (pfnProgress)
7967 0 : pfnProgress(dfPct, "", nullptr);
7968 : }
7969 :
7970 51 : if (ppoBelongingLayer != nullptr)
7971 51 : *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
7972 51 : return poFeature;
7973 13 : }
7974 : }
7975 :
7976 : /************************************************************************/
7977 : /* GDALDatasetGetNextFeature() */
7978 : /************************************************************************/
7979 : /**
7980 : \brief Fetch the next available feature from this dataset.
7981 :
7982 : This method is intended for the few drivers where OGR_L_GetNextFeature()
7983 : is not efficient, but in general OGR_L_GetNextFeature() is a more
7984 : natural API.
7985 :
7986 : The returned feature becomes the responsibility of the caller to
7987 : delete with OGRFeature::DestroyFeature().
7988 :
7989 : Depending on the driver, this method may return features from layers in a
7990 : non sequential way. This is what may happen when the
7991 : ODsCRandomLayerRead capability is declared (for example for the
7992 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7993 : advised to use GDALDataset::GetNextFeature() instead of
7994 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7995 : implementation.
7996 :
7997 : The default implementation, used by most drivers, will
7998 : however iterate over each layer, and then over each feature within this
7999 : layer.
8000 :
8001 : This method takes into account spatial and attribute filters set on layers that
8002 : will be iterated upon.
8003 :
8004 : The ResetReading() method can be used to start at the beginning again.
8005 :
8006 : Depending on drivers, this may also have the side effect of calling
8007 : OGRLayer::GetNextFeature() on the layers of this dataset.
8008 :
8009 : This method is the same as the C++ method GDALDataset::GetNextFeature()
8010 :
8011 : @param hDS dataset handle.
8012 : @param phBelongingLayer a pointer to a OGRLayer* variable to receive the
8013 : layer to which the object belongs to, or NULL.
8014 : It is possible that the output of *ppoBelongingLayer
8015 : to be NULL despite the feature not being NULL.
8016 : @param pdfProgressPct a pointer to a double variable to receive the
8017 : percentage progress (in [0,1] range), or NULL.
8018 : On return, the pointed value might be negative if
8019 : determining the progress is not possible.
8020 : @param pfnProgress a progress callback to report progress (for
8021 : GetNextFeature() calls that might have a long
8022 : duration) and offer cancellation possibility, or NULL
8023 : @param pProgressData user data provided to pfnProgress, or NULL
8024 : @return a feature, or NULL if no more features are available.
8025 : @since GDAL 2.2
8026 : */
8027 1917 : OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,
8028 : OGRLayerH *phBelongingLayer,
8029 : double *pdfProgressPct,
8030 : GDALProgressFunc pfnProgress,
8031 : void *pProgressData)
8032 : {
8033 1917 : VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
8034 :
8035 3834 : return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(
8036 : reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
8037 3834 : pfnProgress, pProgressData));
8038 : }
8039 :
8040 : /************************************************************************/
8041 : /* TestCapability() */
8042 : /************************************************************************/
8043 :
8044 : /**
8045 : \fn GDALDataset::TestCapability( const char * pszCap )
8046 : \brief Test if capability is available.
8047 :
8048 : One of the following dataset capability names can be passed into this
8049 : method, and a TRUE or FALSE value will be returned indicating whether or not
8050 : the capability is available for this object.
8051 :
8052 : <ul>
8053 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
8054 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
8055 : layers.<p>
8056 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
8057 : datasource support CreateGeomField() just after layer creation.<p>
8058 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
8059 : geometries.<p>
8060 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
8061 : transactions.<p>
8062 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
8063 : transactions through emulation.<p>
8064 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
8065 : GetNextFeature() implementation, potentially returning features from
8066 : layers in a non sequential way.<p>
8067 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
8068 : CreateFeature() on layers in a non sequential way.<p>
8069 : <li> <b>GDsCAddRelationship</b>: True if AddRelationship() is supported</li>
8070 : <li> <b>GDsCDeleteRelationship</b>: True if DeleteRelationship() is supported</li>
8071 : <li> <b>GDsCUpdateRelationship</b>: True if UpdateRelationship() is supported</li>
8072 : <li> <b>GDsCFastGetExtent</b>: True if GetExtent() is fast</li>
8073 : <li> <b>GDsCFastGetExtentWGS84LongLat</b>: True if GetExtentWGS84LongLat() is fast</li>
8074 : </ul>
8075 :
8076 : The \#define macro forms of the capability names should be used in preference
8077 : to the strings themselves to avoid misspelling.
8078 :
8079 : This method is the same as the C function GDALDatasetTestCapability() and the
8080 : deprecated OGR_DS_TestCapability().
8081 :
8082 : In GDAL 1.X, this method used to be in the OGRDataSource class.
8083 :
8084 : @param pszCap the capability to test.
8085 :
8086 : @return TRUE if capability available otherwise FALSE.
8087 : */
8088 :
8089 575 : int GDALDataset::TestCapability(const char *pszCap)
8090 : {
8091 575 : if (EQUAL(pszCap, GDsCFastGetExtent) ||
8092 573 : EQUAL(pszCap, GDsCFastGetExtentWGS84LongLat))
8093 : {
8094 4 : for (auto &&poLayer : GetLayers())
8095 : {
8096 2 : if (!poLayer->TestCapability(OLCFastGetExtent))
8097 2 : return FALSE;
8098 : }
8099 2 : return TRUE;
8100 : }
8101 571 : return FALSE;
8102 : }
8103 :
8104 : /************************************************************************/
8105 : /* GDALDatasetTestCapability() */
8106 : /************************************************************************/
8107 :
8108 : /**
8109 : \brief Test if capability is available.
8110 :
8111 : One of the following dataset capability names can be passed into this
8112 : function, and a TRUE or FALSE value will be returned indicating whether or not
8113 : the capability is available for this object.
8114 :
8115 : <ul>
8116 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
8117 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
8118 : layers.<p>
8119 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
8120 : datasource support CreateGeomField() just after layer creation.<p>
8121 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
8122 : geometries.<p>
8123 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
8124 : transactions.<p>
8125 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
8126 : transactions through emulation.<p>
8127 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
8128 : GetNextFeature() implementation, potentially returning features from
8129 : layers in a non sequential way.<p>
8130 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
8131 : CreateFeature() on layers in a non sequential way.<p>
8132 : <li> <b>GDsCAddRelationship</b>: True if AddRelationship() is supported</li>
8133 : <li> <b>GDsCDeleteRelationship</b>: True if DeleteRelationship() is supported</li>
8134 : <li> <b>GDsCUpdateRelationship</b>: True if UpdateRelationship() is supported</li>
8135 : <li> <b>GDsCFastGetExtent</b>: True if GetExtent() is fast</li>
8136 : <li> <b>GDsCFastGetExtentWGS84LongLat</b>: True if GetExtentWGS84LongLat() is fast</li>
8137 : </ul>
8138 :
8139 : The \#define macro forms of the capability names should be used in preference
8140 : to the strings themselves to avoid misspelling.
8141 :
8142 : This function is the same as the C++ method GDALDataset::TestCapability()
8143 :
8144 : @since GDAL 2.0
8145 :
8146 : @param hDS the dataset handle.
8147 : @param pszCap the capability to test.
8148 :
8149 : @return TRUE if capability available otherwise FALSE.
8150 : */
8151 122 : int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)
8152 :
8153 : {
8154 122 : VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
8155 122 : VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
8156 :
8157 122 : return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
8158 : }
8159 :
8160 : /************************************************************************/
8161 : /* StartTransaction() */
8162 : /************************************************************************/
8163 :
8164 : /**
8165 : \fn GDALDataset::StartTransaction(int)
8166 : \brief For datasources which support transactions, StartTransaction creates a
8167 : `transaction.
8168 :
8169 : If starting the transaction fails, will return
8170 : OGRERR_FAILURE. Datasources which do not support transactions will
8171 : always return OGRERR_UNSUPPORTED_OPERATION.
8172 :
8173 : Nested transactions are not supported.
8174 :
8175 : All changes done after the start of the transaction are definitely applied in
8176 : the datasource if CommitTransaction() is called. They may be canceled by
8177 : calling RollbackTransaction() instead.
8178 :
8179 : At the time of writing, transactions only apply on vector layers.
8180 :
8181 : Datasets that support transactions will advertise the ODsCTransactions
8182 : capability. Use of transactions at dataset level is generally preferred to
8183 : transactions at layer level, whose scope is rarely limited to the layer from
8184 : which it was started.
8185 :
8186 : In case StartTransaction() fails, neither CommitTransaction() or
8187 : RollbackTransaction() should be called.
8188 :
8189 : If an error occurs after a successful StartTransaction(), the whole transaction
8190 : may or may not be implicitly canceled, depending on drivers. (e.g. the PG
8191 : driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
8192 : an explicit call to RollbackTransaction() should be done to keep things
8193 : balanced.
8194 :
8195 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8196 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8197 : with significant overhead, in which case the user must explicitly allow for
8198 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8199 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8200 : ODsCTransactions).
8201 :
8202 : This function is the same as the C function GDALDatasetStartTransaction().
8203 :
8204 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8205 : transaction
8206 : mechanism is acceptable.
8207 :
8208 : @return OGRERR_NONE on success.
8209 : @since GDAL 2.0
8210 : */
8211 :
8212 37 : OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
8213 : {
8214 37 : return OGRERR_UNSUPPORTED_OPERATION;
8215 : }
8216 :
8217 : /************************************************************************/
8218 : /* GDALDatasetStartTransaction() */
8219 : /************************************************************************/
8220 :
8221 : /**
8222 : \brief For datasources which support transactions, StartTransaction creates a
8223 : transaction.
8224 :
8225 : If starting the transaction fails, will return
8226 : OGRERR_FAILURE. Datasources which do not support transactions will
8227 : always return OGRERR_UNSUPPORTED_OPERATION.
8228 :
8229 : Nested transactions are not supported.
8230 :
8231 : All changes done after the start of the transaction are definitely applied in
8232 : the datasource if CommitTransaction() is called. They may be canceled by
8233 : calling RollbackTransaction() instead.
8234 :
8235 : At the time of writing, transactions only apply on vector layers.
8236 :
8237 : Datasets that support transactions will advertise the ODsCTransactions
8238 : capability.
8239 : Use of transactions at dataset level is generally preferred to transactions at
8240 : layer level, whose scope is rarely limited to the layer from which it was
8241 : started.
8242 :
8243 : In case StartTransaction() fails, neither CommitTransaction() or
8244 : RollbackTransaction() should be called.
8245 :
8246 : If an error occurs after a successful StartTransaction(), the whole
8247 : transaction may or may not be implicitly canceled, depending on drivers. (e.g.
8248 : the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
8249 : error, an explicit call to RollbackTransaction() should be done to keep things
8250 : balanced.
8251 :
8252 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8253 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8254 : with significant overhead, in which case the user must explicitly allow for
8255 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8256 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8257 : ODsCTransactions).
8258 :
8259 : This function is the same as the C++ method GDALDataset::StartTransaction()
8260 :
8261 : @param hDS the dataset handle.
8262 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8263 : transaction
8264 : mechanism is acceptable.
8265 :
8266 : @return OGRERR_NONE on success.
8267 : @since GDAL 2.0
8268 : */
8269 105 : OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
8270 : {
8271 105 : VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
8272 : OGRERR_INVALID_HANDLE);
8273 :
8274 : #ifdef OGRAPISPY_ENABLED
8275 105 : if (bOGRAPISpyEnabled)
8276 2 : OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
8277 : #endif
8278 :
8279 105 : return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
8280 : }
8281 :
8282 : /************************************************************************/
8283 : /* CommitTransaction() */
8284 : /************************************************************************/
8285 :
8286 : /**
8287 : \brief For datasources which support transactions, CommitTransaction commits a
8288 : transaction.
8289 :
8290 : If no transaction is active, or the commit fails, will return
8291 : OGRERR_FAILURE. Datasources which do not support transactions will
8292 : always return OGRERR_UNSUPPORTED_OPERATION.
8293 :
8294 : Depending on drivers, this may or may not abort layer sequential readings that
8295 : are active.
8296 :
8297 : This function is the same as the C function GDALDatasetCommitTransaction().
8298 :
8299 : @return OGRERR_NONE on success.
8300 : @since GDAL 2.0
8301 : */
8302 37 : OGRErr GDALDataset::CommitTransaction()
8303 : {
8304 37 : return OGRERR_UNSUPPORTED_OPERATION;
8305 : }
8306 :
8307 : /************************************************************************/
8308 : /* GDALDatasetCommitTransaction() */
8309 : /************************************************************************/
8310 :
8311 : /**
8312 : \brief For datasources which support transactions, CommitTransaction commits a
8313 : transaction.
8314 :
8315 : If no transaction is active, or the commit fails, will return
8316 : OGRERR_FAILURE. Datasources which do not support transactions will
8317 : always return OGRERR_UNSUPPORTED_OPERATION.
8318 :
8319 : Depending on drivers, this may or may not abort layer sequential readings that
8320 : are active.
8321 :
8322 : This function is the same as the C++ method GDALDataset::CommitTransaction()
8323 :
8324 : @return OGRERR_NONE on success.
8325 : @since GDAL 2.0
8326 : */
8327 76 : OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
8328 : {
8329 76 : VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
8330 : OGRERR_INVALID_HANDLE);
8331 :
8332 : #ifdef OGRAPISPY_ENABLED
8333 76 : if (bOGRAPISpyEnabled)
8334 2 : OGRAPISpy_Dataset_CommitTransaction(hDS);
8335 : #endif
8336 :
8337 76 : return GDALDataset::FromHandle(hDS)->CommitTransaction();
8338 : }
8339 :
8340 : /************************************************************************/
8341 : /* RollbackTransaction() */
8342 : /************************************************************************/
8343 :
8344 : /**
8345 : \brief For datasources which support transactions, RollbackTransaction will
8346 : roll back a datasource to its state before the start of the current
8347 : transaction.
8348 : If no transaction is active, or the rollback fails, will return
8349 : OGRERR_FAILURE. Datasources which do not support transactions will
8350 : always return OGRERR_UNSUPPORTED_OPERATION.
8351 :
8352 : This function is the same as the C function GDALDatasetRollbackTransaction().
8353 :
8354 : @return OGRERR_NONE on success.
8355 : @since GDAL 2.0
8356 : */
8357 2 : OGRErr GDALDataset::RollbackTransaction()
8358 : {
8359 2 : return OGRERR_UNSUPPORTED_OPERATION;
8360 : }
8361 :
8362 : /************************************************************************/
8363 : /* GDALDatasetRollbackTransaction() */
8364 : /************************************************************************/
8365 :
8366 : /**
8367 : \brief For datasources which support transactions, RollbackTransaction will
8368 : roll back a datasource to its state before the start of the current
8369 : transaction.
8370 : If no transaction is active, or the rollback fails, will return
8371 : OGRERR_FAILURE. Datasources which do not support transactions will
8372 : always return OGRERR_UNSUPPORTED_OPERATION.
8373 :
8374 : This function is the same as the C++ method GDALDataset::RollbackTransaction().
8375 :
8376 : @return OGRERR_NONE on success.
8377 : @since GDAL 2.0
8378 : */
8379 44 : OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
8380 : {
8381 44 : VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
8382 : OGRERR_INVALID_HANDLE);
8383 :
8384 : #ifdef OGRAPISPY_ENABLED
8385 44 : if (bOGRAPISpyEnabled)
8386 2 : OGRAPISpy_Dataset_RollbackTransaction(hDS);
8387 : #endif
8388 :
8389 44 : return GDALDataset::FromHandle(hDS)->RollbackTransaction();
8390 : }
8391 :
8392 : //! @cond Doxygen_Suppress
8393 :
8394 : /************************************************************************/
8395 : /* ShareLockWithParentDataset() */
8396 : /************************************************************************/
8397 :
8398 : /* To be used typically by the GTiff driver to link overview datasets */
8399 : /* with their main dataset, so that they share the same lock */
8400 : /* Cf https://github.com/OSGeo/gdal/issues/1488 */
8401 : /* The parent dataset should remain alive while the this dataset is alive */
8402 :
8403 2355 : void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)
8404 : {
8405 2355 : if (m_poPrivate != nullptr)
8406 : {
8407 2355 : m_poPrivate->poParentDataset = poParentDataset;
8408 : }
8409 2355 : }
8410 :
8411 : /************************************************************************/
8412 : /* SetQueryLoggerFunc() */
8413 : /************************************************************************/
8414 :
8415 0 : bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,
8416 : CPL_UNUSED void *context)
8417 : {
8418 0 : return false;
8419 : }
8420 :
8421 : /************************************************************************/
8422 : /* EnterReadWrite() */
8423 : /************************************************************************/
8424 :
8425 8071230 : int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
8426 : {
8427 16142000 : if (m_poPrivate == nullptr ||
8428 8071050 : IsThreadSafe(GDAL_OF_RASTER | (nOpenFlags & GDAL_OF_UPDATE)))
8429 11977 : return FALSE;
8430 :
8431 8058960 : if (m_poPrivate->poParentDataset)
8432 242561 : return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
8433 :
8434 7816400 : if (eAccess == GA_Update)
8435 : {
8436 2232700 : if (m_poPrivate->eStateReadWriteMutex ==
8437 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8438 : {
8439 : // In case dead-lock would occur, which is not impossible,
8440 : // this can be used to prevent it, but at the risk of other
8441 : // issues.
8442 10312 : if (CPLTestBool(
8443 : CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
8444 : {
8445 10312 : m_poPrivate->eStateReadWriteMutex =
8446 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
8447 : }
8448 : else
8449 : {
8450 0 : m_poPrivate->eStateReadWriteMutex =
8451 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8452 : }
8453 : }
8454 2232700 : if (m_poPrivate->eStateReadWriteMutex ==
8455 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)
8456 : {
8457 : // There should be no race related to creating this mutex since
8458 : // it should be first created through IWriteBlock() / IRasterIO()
8459 : // and then GDALRasterBlock might call it from another thread.
8460 : #ifdef DEBUG_VERBOSE
8461 : CPLDebug("GDAL",
8462 : "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
8463 : CPLGetPID(), GetDescription());
8464 : #endif
8465 1531930 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8466 :
8467 : const int nCountMutex =
8468 1535410 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
8469 1535070 : if (nCountMutex == 0 && eRWFlag == GF_Read)
8470 : {
8471 520617 : CPLReleaseMutex(m_poPrivate->hMutex);
8472 1652880 : for (int i = 0; i < nBands; i++)
8473 : {
8474 1132270 : auto blockCache = papoBands[i]->poBandBlockCache;
8475 1132270 : if (blockCache)
8476 816878 : blockCache->WaitCompletionPendingTasks();
8477 : }
8478 520617 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8479 : }
8480 :
8481 1535060 : return TRUE;
8482 : }
8483 : }
8484 6284480 : return FALSE;
8485 : }
8486 :
8487 : /************************************************************************/
8488 : /* LeaveReadWrite() */
8489 : /************************************************************************/
8490 :
8491 1763660 : void GDALDataset::LeaveReadWrite()
8492 : {
8493 1763660 : if (m_poPrivate)
8494 : {
8495 1763520 : if (m_poPrivate->poParentDataset)
8496 : {
8497 228949 : m_poPrivate->poParentDataset->LeaveReadWrite();
8498 228949 : return;
8499 : }
8500 :
8501 1534570 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
8502 1533770 : CPLReleaseMutex(m_poPrivate->hMutex);
8503 : #ifdef DEBUG_VERBOSE
8504 : CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
8505 : CPLGetPID(), GetDescription());
8506 : #endif
8507 : }
8508 : }
8509 :
8510 : /************************************************************************/
8511 : /* InitRWLock() */
8512 : /************************************************************************/
8513 :
8514 3988320 : void GDALDataset::InitRWLock()
8515 : {
8516 3988320 : if (m_poPrivate)
8517 : {
8518 3988320 : if (m_poPrivate->poParentDataset)
8519 : {
8520 8592 : m_poPrivate->poParentDataset->InitRWLock();
8521 8592 : return;
8522 : }
8523 :
8524 3979730 : if (m_poPrivate->eStateReadWriteMutex ==
8525 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8526 : {
8527 1 : if (EnterReadWrite(GF_Write))
8528 1 : LeaveReadWrite();
8529 : }
8530 : }
8531 : }
8532 :
8533 : /************************************************************************/
8534 : /* DisableReadWriteMutex() */
8535 : /************************************************************************/
8536 :
8537 : // The mutex logic is broken in multi-threaded situations, for example
8538 : // with 2 WarpedVRT datasets being read at the same time. In that
8539 : // particular case, the mutex is not needed, so allow the VRTWarpedDataset code
8540 : // to disable it.
8541 19369 : void GDALDataset::DisableReadWriteMutex()
8542 : {
8543 19369 : if (m_poPrivate)
8544 : {
8545 19369 : if (m_poPrivate->poParentDataset)
8546 : {
8547 0 : m_poPrivate->poParentDataset->DisableReadWriteMutex();
8548 0 : return;
8549 : }
8550 :
8551 19369 : m_poPrivate->eStateReadWriteMutex =
8552 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8553 : }
8554 : }
8555 :
8556 : /************************************************************************/
8557 : /* TemporarilyDropReadWriteLock() */
8558 : /************************************************************************/
8559 :
8560 3417230 : void GDALDataset::TemporarilyDropReadWriteLock()
8561 : {
8562 3417230 : if (m_poPrivate == nullptr)
8563 0 : return;
8564 :
8565 3417230 : if (m_poPrivate->poParentDataset)
8566 : {
8567 26294 : m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
8568 26294 : return;
8569 : }
8570 :
8571 : #ifndef __COVERITY__
8572 3390940 : if (m_poPrivate->hMutex)
8573 : {
8574 : #ifdef DEBUG_VERBOSE
8575 : CPLDebug("GDAL",
8576 : "[Thread " CPL_FRMT_GIB "] "
8577 : "Temporarily drop RW mutex for %s",
8578 : CPLGetPID(), GetDescription());
8579 : #endif
8580 410670 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8581 : const int nCount =
8582 410668 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8583 : #ifdef DEBUG_EXTRA
8584 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
8585 : #endif
8586 1246320 : for (int i = 0; i < nCount + 1; i++)
8587 : {
8588 : // The mutex is recursive
8589 835661 : CPLReleaseMutex(m_poPrivate->hMutex);
8590 : }
8591 : }
8592 : #endif
8593 : }
8594 :
8595 : /************************************************************************/
8596 : /* ReacquireReadWriteLock() */
8597 : /************************************************************************/
8598 :
8599 3417240 : void GDALDataset::ReacquireReadWriteLock()
8600 : {
8601 3417240 : if (m_poPrivate == nullptr)
8602 0 : return;
8603 :
8604 3417240 : if (m_poPrivate->poParentDataset)
8605 : {
8606 26294 : m_poPrivate->poParentDataset->ReacquireReadWriteLock();
8607 26294 : return;
8608 : }
8609 :
8610 : #ifndef __COVERITY__
8611 3390950 : if (m_poPrivate->hMutex)
8612 : {
8613 : #ifdef DEBUG_VERBOSE
8614 : CPLDebug("GDAL",
8615 : "[Thread " CPL_FRMT_GIB "] "
8616 : "Reacquire temporarily dropped RW mutex for %s",
8617 : CPLGetPID(), GetDescription());
8618 : #endif
8619 410673 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8620 : const int nCount =
8621 410671 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8622 : #ifdef DEBUG_EXTRA
8623 : CPLAssert(nCount ==
8624 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
8625 : #endif
8626 410671 : if (nCount == 0)
8627 11350 : CPLReleaseMutex(m_poPrivate->hMutex);
8628 436356 : for (int i = 0; i < nCount - 1; i++)
8629 : {
8630 : // The mutex is recursive
8631 25685 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8632 : }
8633 : }
8634 : #endif
8635 : }
8636 :
8637 : /************************************************************************/
8638 : /* AcquireMutex() */
8639 : /************************************************************************/
8640 :
8641 196 : int GDALDataset::AcquireMutex()
8642 : {
8643 196 : if (m_poPrivate == nullptr)
8644 0 : return 0;
8645 196 : if (m_poPrivate->poParentDataset)
8646 : {
8647 0 : return m_poPrivate->poParentDataset->AcquireMutex();
8648 : }
8649 :
8650 196 : return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8651 : }
8652 :
8653 : /************************************************************************/
8654 : /* ReleaseMutex() */
8655 : /************************************************************************/
8656 :
8657 196 : void GDALDataset::ReleaseMutex()
8658 : {
8659 196 : if (m_poPrivate)
8660 : {
8661 196 : if (m_poPrivate->poParentDataset)
8662 : {
8663 0 : m_poPrivate->poParentDataset->ReleaseMutex();
8664 0 : return;
8665 : }
8666 :
8667 196 : CPLReleaseMutex(m_poPrivate->hMutex);
8668 : }
8669 : }
8670 :
8671 : //! @endcond
8672 :
8673 : /************************************************************************/
8674 : /* GDALDataset::Features::Iterator::Private */
8675 : /************************************************************************/
8676 :
8677 : struct GDALDataset::Features::Iterator::Private
8678 : {
8679 : GDALDataset::FeatureLayerPair m_oPair{};
8680 : GDALDataset *m_poDS = nullptr;
8681 : bool m_bEOF = true;
8682 : };
8683 :
8684 4 : GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8685 4 : : m_poPrivate(new GDALDataset::Features::Iterator::Private())
8686 : {
8687 4 : m_poPrivate->m_poDS = poDS;
8688 4 : if (bStart)
8689 : {
8690 2 : poDS->ResetReading();
8691 4 : m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(
8692 2 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8693 2 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8694 : }
8695 4 : }
8696 :
8697 : GDALDataset::Features::Iterator::~Iterator() = default;
8698 :
8699 : const GDALDataset::FeatureLayerPair &
8700 20 : GDALDataset::Features::Iterator::operator*() const
8701 : {
8702 20 : return m_poPrivate->m_oPair;
8703 : }
8704 :
8705 20 : GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()
8706 : {
8707 40 : m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(
8708 20 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8709 20 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8710 20 : return *this;
8711 : }
8712 :
8713 22 : bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const
8714 : {
8715 22 : return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
8716 : }
8717 :
8718 : /************************************************************************/
8719 : /* GetFeatures() */
8720 : /************************************************************************/
8721 :
8722 : /** Function that return an iterable object over features in the dataset
8723 : * layer.
8724 : *
8725 : * This is a C++ iterator friendly version of GetNextFeature().
8726 : *
8727 : * Using this iterator for standard range-based loops is safe, but
8728 : * due to implementation limitations, you shouldn't try to access
8729 : * (dereference) more than one iterator step at a time, since the
8730 : * FeatureLayerPair reference which is returned is reused.
8731 : *
8732 : * Typical use is:
8733 : * \code{.cpp}
8734 : * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
8735 : * {
8736 : * std::cout << "Feature of layer " <<
8737 : * oFeatureLayerPair.layer->GetName() << std::endl;
8738 : * oFeatureLayerPair.feature->DumpReadable();
8739 : * }
8740 : * \endcode
8741 : *
8742 : * @see GetNextFeature()
8743 : *
8744 : * @since GDAL 2.3
8745 : */
8746 2 : GDALDataset::Features GDALDataset::GetFeatures()
8747 : {
8748 2 : return Features(this);
8749 : }
8750 :
8751 : /************************************************************************/
8752 : /* begin() */
8753 : /************************************************************************/
8754 :
8755 : /**
8756 : \brief Return beginning of feature iterator.
8757 :
8758 : @since GDAL 2.3
8759 : */
8760 :
8761 2 : const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
8762 : {
8763 2 : return {m_poSelf, true};
8764 : }
8765 :
8766 : /************************************************************************/
8767 : /* end() */
8768 : /************************************************************************/
8769 :
8770 : /**
8771 : \brief Return end of feature iterator.
8772 :
8773 : @since GDAL 2.3
8774 : */
8775 :
8776 2 : const GDALDataset::Features::Iterator GDALDataset::Features::end() const
8777 : {
8778 2 : return {m_poSelf, false};
8779 : }
8780 :
8781 : /************************************************************************/
8782 : /* GDALDataset::Layers::Iterator::Private */
8783 : /************************************************************************/
8784 :
8785 : struct GDALDataset::Layers::Iterator::Private
8786 : {
8787 : OGRLayer *m_poLayer = nullptr;
8788 : int m_iCurLayer = 0;
8789 : int m_nLayerCount = 0;
8790 : GDALDataset *m_poDS = nullptr;
8791 : };
8792 :
8793 2 : GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())
8794 : {
8795 2 : }
8796 :
8797 : // False positive of cppcheck 1.72
8798 : // cppcheck-suppress uninitMemberVar
8799 9 : GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)
8800 9 : : m_poPrivate(new Private(*(oOther.m_poPrivate)))
8801 : {
8802 9 : }
8803 :
8804 5 : GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept
8805 5 : : m_poPrivate(std::move(oOther.m_poPrivate))
8806 : {
8807 5 : }
8808 :
8809 496 : GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8810 496 : : m_poPrivate(new Private())
8811 : {
8812 496 : m_poPrivate->m_poDS = poDS;
8813 496 : m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
8814 496 : if (bStart)
8815 : {
8816 250 : if (m_poPrivate->m_nLayerCount)
8817 247 : m_poPrivate->m_poLayer = poDS->GetLayer(0);
8818 : }
8819 : else
8820 : {
8821 246 : m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
8822 : }
8823 496 : }
8824 :
8825 : GDALDataset::Layers::Iterator::~Iterator() = default;
8826 :
8827 : // False positive of cppcheck 1.72
8828 : // cppcheck-suppress operatorEqVarError
8829 : GDALDataset::Layers::Iterator &
8830 1 : GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)
8831 : {
8832 1 : *m_poPrivate = *oOther.m_poPrivate;
8833 1 : return *this;
8834 : }
8835 :
8836 3 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(
8837 : GDALDataset::Layers::Iterator &&oOther) noexcept
8838 : {
8839 3 : m_poPrivate = std::move(oOther.m_poPrivate);
8840 3 : return *this;
8841 : }
8842 :
8843 286 : OGRLayer *GDALDataset::Layers::Iterator::operator*() const
8844 : {
8845 286 : return m_poPrivate->m_poLayer;
8846 : }
8847 :
8848 270 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()
8849 : {
8850 270 : m_poPrivate->m_iCurLayer++;
8851 270 : if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
8852 : {
8853 45 : m_poPrivate->m_poLayer =
8854 45 : m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
8855 : }
8856 : else
8857 : {
8858 225 : m_poPrivate->m_poLayer = nullptr;
8859 : }
8860 270 : return *this;
8861 : }
8862 :
8863 2 : GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
8864 : {
8865 2 : GDALDataset::Layers::Iterator temp = *this;
8866 2 : ++(*this);
8867 2 : return temp;
8868 : }
8869 :
8870 510 : bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const
8871 : {
8872 510 : return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
8873 : }
8874 :
8875 : /************************************************************************/
8876 : /* GetLayers() */
8877 : /************************************************************************/
8878 :
8879 : /** Function that returns an iterable object over layers in the dataset.
8880 : *
8881 : * This is a C++ iterator friendly version of GetLayer().
8882 : *
8883 : * Typical use is:
8884 : * \code{.cpp}
8885 : * for( auto&& poLayer: poDS->GetLayers() )
8886 : * {
8887 : * std::cout << "Layer << poLayer->GetName() << std::endl;
8888 : * }
8889 : * \endcode
8890 : *
8891 : * @see GetLayer()
8892 : *
8893 : * @since GDAL 2.3
8894 : */
8895 251 : GDALDataset::Layers GDALDataset::GetLayers()
8896 : {
8897 251 : return Layers(this);
8898 : }
8899 :
8900 : /************************************************************************/
8901 : /* begin() */
8902 : /************************************************************************/
8903 :
8904 : /**
8905 : \brief Return beginning of layer iterator.
8906 :
8907 : @since GDAL 2.3
8908 : */
8909 :
8910 250 : GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
8911 : {
8912 250 : return {m_poSelf, true};
8913 : }
8914 :
8915 : /************************************************************************/
8916 : /* end() */
8917 : /************************************************************************/
8918 :
8919 : /**
8920 : \brief Return end of layer iterator.
8921 :
8922 : @since GDAL 2.3
8923 : */
8924 :
8925 246 : GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
8926 : {
8927 246 : return {m_poSelf, false};
8928 : }
8929 :
8930 : /************************************************************************/
8931 : /* size() */
8932 : /************************************************************************/
8933 :
8934 : /**
8935 : \brief Get the number of layers in this dataset.
8936 :
8937 : @return layer count.
8938 :
8939 : @since GDAL 2.3
8940 : */
8941 :
8942 1 : size_t GDALDataset::Layers::size() const
8943 : {
8944 1 : return static_cast<size_t>(m_poSelf->GetLayerCount());
8945 : }
8946 :
8947 : /************************************************************************/
8948 : /* operator[]() */
8949 : /************************************************************************/
8950 : /**
8951 : \brief Fetch a layer by index.
8952 :
8953 : The returned layer remains owned by the
8954 : GDALDataset and should not be deleted by the application.
8955 :
8956 : @param iLayer a layer number between 0 and size()-1.
8957 :
8958 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
8959 :
8960 : @since GDAL 2.3
8961 : */
8962 :
8963 9 : OGRLayer *GDALDataset::Layers::operator[](int iLayer)
8964 : {
8965 9 : return m_poSelf->GetLayer(iLayer);
8966 : }
8967 :
8968 : /************************************************************************/
8969 : /* operator[]() */
8970 : /************************************************************************/
8971 : /**
8972 : \brief Fetch a layer by index.
8973 :
8974 : The returned layer remains owned by the
8975 : GDALDataset and should not be deleted by the application.
8976 :
8977 : @param iLayer a layer number between 0 and size()-1.
8978 :
8979 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
8980 :
8981 : @since GDAL 2.3
8982 : */
8983 :
8984 1 : OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)
8985 : {
8986 1 : return m_poSelf->GetLayer(static_cast<int>(iLayer));
8987 : }
8988 :
8989 : /************************************************************************/
8990 : /* operator[]() */
8991 : /************************************************************************/
8992 : /**
8993 : \brief Fetch a layer by name.
8994 :
8995 : The returned layer remains owned by the
8996 : GDALDataset and should not be deleted by the application.
8997 :
8998 : @param pszLayerName layer name
8999 :
9000 : @return the layer, or nullptr if pszLayerName does not match with a layer
9001 :
9002 : @since GDAL 2.3
9003 : */
9004 :
9005 1 : OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)
9006 : {
9007 1 : return m_poSelf->GetLayerByName(pszLayerName);
9008 : }
9009 :
9010 : /************************************************************************/
9011 : /* GDALDataset::Bands::Iterator::Private */
9012 : /************************************************************************/
9013 :
9014 : struct GDALDataset::Bands::Iterator::Private
9015 : {
9016 : GDALRasterBand *m_poBand = nullptr;
9017 : int m_iCurBand = 0;
9018 : int m_nBandCount = 0;
9019 : GDALDataset *m_poDS = nullptr;
9020 : };
9021 :
9022 6 : GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)
9023 6 : : m_poPrivate(new GDALDataset::Bands::Iterator::Private())
9024 : {
9025 6 : m_poPrivate->m_poDS = poDS;
9026 6 : m_poPrivate->m_nBandCount = poDS->GetRasterCount();
9027 6 : if (bStart)
9028 : {
9029 3 : if (m_poPrivate->m_nBandCount)
9030 3 : m_poPrivate->m_poBand = poDS->GetRasterBand(1);
9031 : }
9032 : else
9033 : {
9034 3 : m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
9035 : }
9036 6 : }
9037 :
9038 : GDALDataset::Bands::Iterator::~Iterator() = default;
9039 :
9040 5 : GDALRasterBand *GDALDataset::Bands::Iterator::operator*()
9041 : {
9042 5 : return m_poPrivate->m_poBand;
9043 : }
9044 :
9045 3 : GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()
9046 : {
9047 3 : m_poPrivate->m_iCurBand++;
9048 3 : if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
9049 : {
9050 2 : m_poPrivate->m_poBand =
9051 2 : m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
9052 : }
9053 : else
9054 : {
9055 1 : m_poPrivate->m_poBand = nullptr;
9056 : }
9057 3 : return *this;
9058 : }
9059 :
9060 6 : bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const
9061 : {
9062 6 : return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
9063 : }
9064 :
9065 : /************************************************************************/
9066 : /* GetBands() */
9067 : /************************************************************************/
9068 :
9069 : /** Function that returns an iterable object over GDALRasterBand in the dataset.
9070 : *
9071 : * This is a C++ iterator friendly version of GetRasterBand().
9072 : *
9073 : * Typical use is:
9074 : * \code{.cpp}
9075 : * for( auto&& poBand: poDS->GetBands() )
9076 : * {
9077 : * std::cout << "Band << poBand->GetDescription() << std::endl;
9078 : * }
9079 : * \endcode
9080 : *
9081 : * @see GetRasterBand()
9082 : *
9083 : * @since GDAL 2.3
9084 : */
9085 7 : GDALDataset::Bands GDALDataset::GetBands()
9086 : {
9087 7 : return Bands(this);
9088 : }
9089 :
9090 : /************************************************************************/
9091 : /* begin() */
9092 : /************************************************************************/
9093 :
9094 : /**
9095 : \brief Return beginning of band iterator.
9096 :
9097 : @since GDAL 2.3
9098 : */
9099 :
9100 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
9101 : {
9102 3 : return {m_poSelf, true};
9103 : }
9104 :
9105 : /************************************************************************/
9106 : /* end() */
9107 : /************************************************************************/
9108 :
9109 : /**
9110 : \brief Return end of band iterator.
9111 :
9112 : @since GDAL 2.3
9113 : */
9114 :
9115 3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
9116 : {
9117 3 : return {m_poSelf, false};
9118 : }
9119 :
9120 : /************************************************************************/
9121 : /* size() */
9122 : /************************************************************************/
9123 :
9124 : /**
9125 : \brief Get the number of raster bands in this dataset.
9126 :
9127 : @return raster band count.
9128 :
9129 : @since GDAL 2.3
9130 : */
9131 :
9132 2 : size_t GDALDataset::Bands::size() const
9133 : {
9134 2 : return static_cast<size_t>(m_poSelf->GetRasterCount());
9135 : }
9136 :
9137 : /************************************************************************/
9138 : /* operator[]() */
9139 : /************************************************************************/
9140 : /**
9141 : \brief Fetch a raster band by index.
9142 :
9143 : The returned band remains owned by the
9144 : GDALDataset and should not be deleted by the application.
9145 :
9146 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9147 : consistent with the conventions of C/C++, i.e. starting at 0.
9148 :
9149 : @param iBand a band index between 0 and size()-1.
9150 :
9151 : @return the band, or nullptr if iBand is out of range or an error occurs.
9152 :
9153 : @since GDAL 2.3
9154 : */
9155 :
9156 1 : GDALRasterBand *GDALDataset::Bands::operator[](int iBand)
9157 : {
9158 1 : return m_poSelf->GetRasterBand(1 + iBand);
9159 : }
9160 :
9161 : /************************************************************************/
9162 : /* operator[]() */
9163 : /************************************************************************/
9164 :
9165 : /**
9166 : \brief Fetch a raster band by index.
9167 :
9168 : The returned band remains owned by the
9169 : GDALDataset and should not be deleted by the application.
9170 :
9171 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9172 : consistent with the conventions of C/C++, i.e. starting at 0.
9173 :
9174 : @param iBand a band index between 0 and size()-1.
9175 :
9176 : @return the band, or nullptr if iBand is out of range or an error occurs.
9177 :
9178 : @since GDAL 2.3
9179 : */
9180 :
9181 1 : GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)
9182 : {
9183 1 : return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
9184 : }
9185 :
9186 : /************************************************************************/
9187 : /* GetRootGroup() */
9188 : /************************************************************************/
9189 :
9190 : /**
9191 : \brief Return the root GDALGroup of this dataset.
9192 :
9193 : Only valid for multidimensional datasets.
9194 :
9195 : This is the same as the C function GDALDatasetGetRootGroup().
9196 :
9197 : @since GDAL 3.1
9198 : */
9199 :
9200 2728 : std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
9201 : {
9202 2728 : return nullptr;
9203 : }
9204 :
9205 : /************************************************************************/
9206 : /* GetRawBinaryLayout() */
9207 : /************************************************************************/
9208 :
9209 : //! @cond Doxygen_Suppress
9210 : /**
9211 : \brief Return the layout of a dataset that can be considered as a raw binary
9212 : format.
9213 :
9214 : @param sLayout Structure that will be set if the dataset is a raw binary one.
9215 : @return true if the dataset is a raw binary one.
9216 : @since GDAL 3.1
9217 : */
9218 :
9219 0 : bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)
9220 : {
9221 0 : CPL_IGNORE_RET_VAL(sLayout);
9222 0 : return false;
9223 : }
9224 :
9225 : //! @endcond
9226 :
9227 : /************************************************************************/
9228 : /* ClearStatistics() */
9229 : /************************************************************************/
9230 :
9231 : /**
9232 : \brief Clear statistics
9233 :
9234 : Only implemented for now in PAM supported datasets
9235 :
9236 : This is the same as the C function GDALDatasetClearStatistics().
9237 :
9238 : @since GDAL 3.2
9239 : */
9240 :
9241 11 : void GDALDataset::ClearStatistics()
9242 : {
9243 22 : auto poRootGroup = GetRootGroup();
9244 11 : if (poRootGroup)
9245 1 : poRootGroup->ClearStatistics();
9246 11 : }
9247 :
9248 : /************************************************************************/
9249 : /* GDALDatasetClearStatistics() */
9250 : /************************************************************************/
9251 :
9252 : /**
9253 : \brief Clear statistics
9254 :
9255 : This is the same as the C++ method GDALDataset::ClearStatistics().
9256 :
9257 : @since GDAL 3.2
9258 : */
9259 :
9260 2 : void GDALDatasetClearStatistics(GDALDatasetH hDS)
9261 : {
9262 2 : VALIDATE_POINTER0(hDS, __func__);
9263 2 : GDALDataset::FromHandle(hDS)->ClearStatistics();
9264 : }
9265 :
9266 : /************************************************************************/
9267 : /* GetFieldDomainNames() */
9268 : /************************************************************************/
9269 :
9270 : /** Returns a list of the names of all field domains stored in the dataset.
9271 : *
9272 : * @note The default implementation assumes that drivers fully populate
9273 : * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect
9274 : * then a specialized implementation of GetFieldDomainNames() must be
9275 : * implemented.
9276 : *
9277 : * @param papszOptions Driver specific options determining how attributes
9278 : * should be retrieved. Pass nullptr for default behavior.
9279 : *
9280 : * @return list of field domain names
9281 : * @since GDAL 3.5
9282 : */
9283 : std::vector<std::string>
9284 44 : GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const
9285 : {
9286 :
9287 44 : std::vector<std::string> names;
9288 44 : names.reserve(m_oMapFieldDomains.size());
9289 56 : for (const auto &it : m_oMapFieldDomains)
9290 : {
9291 12 : names.emplace_back(it.first);
9292 : }
9293 44 : return names;
9294 : }
9295 :
9296 : /************************************************************************/
9297 : /* GDALDatasetGetFieldDomainNames() */
9298 : /************************************************************************/
9299 :
9300 : /** Returns a list of the names of all field domains stored in the dataset.
9301 : *
9302 : * This is the same as the C++ method GDALDataset::GetFieldDomainNames().
9303 : *
9304 : * @param hDS Dataset handle.
9305 : * @param papszOptions Driver specific options determining how attributes
9306 : * should be retrieved. Pass nullptr for default behavior.
9307 : *
9308 : * @return list of field domain names, to be freed with CSLDestroy()
9309 : * @since GDAL 3.5
9310 : */
9311 32 : char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,
9312 : CSLConstList papszOptions)
9313 : {
9314 32 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9315 : auto names =
9316 64 : GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);
9317 64 : CPLStringList res;
9318 137 : for (const auto &name : names)
9319 : {
9320 105 : res.AddString(name.c_str());
9321 : }
9322 32 : return res.StealList();
9323 : }
9324 :
9325 : /************************************************************************/
9326 : /* GetFieldDomain() */
9327 : /************************************************************************/
9328 :
9329 : /** Get a field domain from its name.
9330 : *
9331 : * @return the field domain, or nullptr if not found.
9332 : * @since GDAL 3.3
9333 : */
9334 270 : const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const
9335 : {
9336 270 : const auto iter = m_oMapFieldDomains.find(name);
9337 270 : if (iter == m_oMapFieldDomains.end())
9338 116 : return nullptr;
9339 154 : return iter->second.get();
9340 : }
9341 :
9342 : /************************************************************************/
9343 : /* GDALDatasetGetFieldDomain() */
9344 : /************************************************************************/
9345 :
9346 : /** Get a field domain from its name.
9347 : *
9348 : * This is the same as the C++ method GDALDataset::GetFieldDomain().
9349 : *
9350 : * @param hDS Dataset handle.
9351 : * @param pszName Name of field domain.
9352 : * @return the field domain (ownership remains to the dataset), or nullptr if
9353 : * not found.
9354 : * @since GDAL 3.3
9355 : */
9356 114 : OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)
9357 : {
9358 114 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9359 114 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9360 114 : return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(
9361 114 : GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
9362 : }
9363 :
9364 : /************************************************************************/
9365 : /* AddFieldDomain() */
9366 : /************************************************************************/
9367 :
9368 : /** Add a field domain to the dataset.
9369 : *
9370 : * Only a few drivers will support this operation, and some of them might only
9371 : * support it only for some types of field domains.
9372 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9373 : * support this operation. A dataset having at least some support for this
9374 : * operation should report the ODsCAddFieldDomain dataset capability.
9375 : *
9376 : * Anticipated failures will not be emitted through the CPLError()
9377 : * infrastructure, but will be reported in the failureReason output parameter.
9378 : *
9379 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9380 : * default implementation of GetFieldDomainNames() to work correctly, or
9381 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9382 : * implemented.
9383 : *
9384 : * @param domain The domain definition.
9385 : * @param failureReason Output parameter. Will contain an error message if
9386 : * an error occurs.
9387 : * @return true in case of success.
9388 : * @since GDAL 3.3
9389 : */
9390 0 : bool GDALDataset::AddFieldDomain(
9391 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9392 : std::string &failureReason)
9393 : {
9394 0 : failureReason = "AddFieldDomain not supported by this driver";
9395 0 : return false;
9396 : }
9397 :
9398 : /************************************************************************/
9399 : /* GDALDatasetAddFieldDomain() */
9400 : /************************************************************************/
9401 :
9402 : /** Add a field domain to the dataset.
9403 : *
9404 : * Only a few drivers will support this operation, and some of them might only
9405 : * support it only for some types of field domains.
9406 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9407 : * support this operation. A dataset having at least some support for this
9408 : * operation should report the ODsCAddFieldDomain dataset capability.
9409 : *
9410 : * Anticipated failures will not be emitted through the CPLError()
9411 : * infrastructure, but will be reported in the ppszFailureReason output
9412 : * parameter.
9413 : *
9414 : * @param hDS Dataset handle.
9415 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9416 : * the passed object is copied.
9417 : * @param ppszFailureReason Output parameter. Will contain an error message if
9418 : * an error occurs (*ppszFailureReason to be freed
9419 : * with CPLFree). May be NULL.
9420 : * @return true in case of success.
9421 : * @since GDAL 3.3
9422 : */
9423 37 : bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,
9424 : char **ppszFailureReason)
9425 : {
9426 37 : VALIDATE_POINTER1(hDS, __func__, false);
9427 37 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9428 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9429 74 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9430 37 : if (poDomain == nullptr)
9431 0 : return false;
9432 37 : std::string failureReason;
9433 74 : const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(
9434 37 : std::move(poDomain), failureReason);
9435 37 : if (ppszFailureReason)
9436 : {
9437 37 : *ppszFailureReason =
9438 37 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9439 : }
9440 37 : return bRet;
9441 : }
9442 :
9443 : /************************************************************************/
9444 : /* DeleteFieldDomain() */
9445 : /************************************************************************/
9446 :
9447 : /** Removes a field domain from the dataset.
9448 : *
9449 : * Only a few drivers will support this operation.
9450 : *
9451 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9452 : * support this operation. A dataset having at least some support for this
9453 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9454 : *
9455 : * Anticipated failures will not be emitted through the CPLError()
9456 : * infrastructure, but will be reported in the failureReason output parameter.
9457 : *
9458 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9459 : * default implementation of GetFieldDomainNames() to work correctly, or
9460 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9461 : * implemented.
9462 : *
9463 : * @param name The domain name.
9464 : * @param failureReason Output parameter. Will contain an error message if
9465 : * an error occurs.
9466 : * @return true in case of success.
9467 : * @since GDAL 3.5
9468 : */
9469 0 : bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,
9470 : std::string &failureReason)
9471 : {
9472 0 : failureReason = "DeleteFieldDomain not supported by this driver";
9473 0 : return false;
9474 : }
9475 :
9476 : /************************************************************************/
9477 : /* GDALDatasetDeleteFieldDomain() */
9478 : /************************************************************************/
9479 :
9480 : /** Removes a field domain from the dataset.
9481 : *
9482 : * Only a few drivers will support this operation.
9483 : *
9484 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9485 : * support this operation. A dataset having at least some support for this
9486 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9487 : *
9488 : * Anticipated failures will not be emitted through the CPLError()
9489 : * infrastructure, but will be reported in the ppszFailureReason output
9490 : * parameter.
9491 : *
9492 : * @param hDS Dataset handle.
9493 : * @param pszName The domain name.
9494 : * @param ppszFailureReason Output parameter. Will contain an error message if
9495 : * an error occurs (*ppszFailureReason to be freed
9496 : * with CPLFree). May be NULL.
9497 : * @return true in case of success.
9498 : * @since GDAL 3.3
9499 : */
9500 8 : bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,
9501 : char **ppszFailureReason)
9502 : {
9503 8 : VALIDATE_POINTER1(hDS, __func__, false);
9504 8 : VALIDATE_POINTER1(pszName, __func__, false);
9505 8 : std::string failureReason;
9506 : const bool bRet =
9507 8 : GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);
9508 8 : if (ppszFailureReason)
9509 : {
9510 0 : *ppszFailureReason =
9511 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9512 : }
9513 8 : return bRet;
9514 : }
9515 :
9516 : /************************************************************************/
9517 : /* UpdateFieldDomain() */
9518 : /************************************************************************/
9519 :
9520 : /** Updates an existing field domain by replacing its definition.
9521 : *
9522 : * The existing field domain with matching name will be replaced.
9523 : *
9524 : * Only a few drivers will support this operation, and some of them might only
9525 : * support it only for some types of field domains.
9526 : * At the time of writing (GDAL 3.5), only the Memory driver
9527 : * supports this operation. A dataset having at least some support for this
9528 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9529 : *
9530 : * Anticipated failures will not be emitted through the CPLError()
9531 : * infrastructure, but will be reported in the failureReason output parameter.
9532 : *
9533 : * @param domain The domain definition.
9534 : * @param failureReason Output parameter. Will contain an error message if
9535 : * an error occurs.
9536 : * @return true in case of success.
9537 : * @since GDAL 3.5
9538 : */
9539 0 : bool GDALDataset::UpdateFieldDomain(
9540 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9541 : std::string &failureReason)
9542 : {
9543 0 : failureReason = "UpdateFieldDomain not supported by this driver";
9544 0 : return false;
9545 : }
9546 :
9547 : /************************************************************************/
9548 : /* GDALDatasetUpdateFieldDomain() */
9549 : /************************************************************************/
9550 :
9551 : /** Updates an existing field domain by replacing its definition.
9552 : *
9553 : * The existing field domain with matching name will be replaced.
9554 : *
9555 : * Only a few drivers will support this operation, and some of them might only
9556 : * support it only for some types of field domains.
9557 : * At the time of writing (GDAL 3.5), only the Memory driver
9558 : * supports this operation. A dataset having at least some support for this
9559 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9560 : *
9561 : * Anticipated failures will not be emitted through the CPLError()
9562 : * infrastructure, but will be reported in the failureReason output parameter.
9563 : *
9564 : * @param hDS Dataset handle.
9565 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9566 : * the passed object is copied.
9567 : * @param ppszFailureReason Output parameter. Will contain an error message if
9568 : * an error occurs (*ppszFailureReason to be freed
9569 : * with CPLFree). May be NULL.
9570 : * @return true in case of success.
9571 : * @since GDAL 3.5
9572 : */
9573 4 : bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,
9574 : OGRFieldDomainH hFieldDomain,
9575 : char **ppszFailureReason)
9576 : {
9577 4 : VALIDATE_POINTER1(hDS, __func__, false);
9578 4 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9579 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9580 8 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9581 4 : if (poDomain == nullptr)
9582 0 : return false;
9583 4 : std::string failureReason;
9584 8 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(
9585 4 : std::move(poDomain), failureReason);
9586 4 : if (ppszFailureReason)
9587 : {
9588 0 : *ppszFailureReason =
9589 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9590 : }
9591 4 : return bRet;
9592 : }
9593 :
9594 : /************************************************************************/
9595 : /* GetRelationshipNames() */
9596 : /************************************************************************/
9597 :
9598 : /** Returns a list of the names of all relationships stored in the dataset.
9599 : *
9600 : * @param papszOptions Driver specific options determining how relationships
9601 : * should be retrieved. Pass nullptr for default behavior.
9602 : *
9603 : * @return list of relationship names
9604 : * @since GDAL 3.6
9605 : */
9606 : std::vector<std::string>
9607 164 : GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const
9608 : {
9609 164 : return {};
9610 : }
9611 :
9612 : /************************************************************************/
9613 : /* GDALDatasetGetRelationshipNames() */
9614 : /************************************************************************/
9615 :
9616 : /** Returns a list of the names of all relationships stored in the dataset.
9617 : *
9618 : * This is the same as the C++ method GDALDataset::GetRelationshipNames().
9619 : *
9620 : * @param hDS Dataset handle.
9621 : * @param papszOptions Driver specific options determining how relationships
9622 : * should be retrieved. Pass nullptr for default behavior.
9623 : *
9624 : * @return list of relationship names, to be freed with CSLDestroy()
9625 : * @since GDAL 3.6
9626 : */
9627 46 : char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,
9628 : CSLConstList papszOptions)
9629 : {
9630 46 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9631 : auto names =
9632 92 : GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);
9633 92 : CPLStringList res;
9634 146 : for (const auto &name : names)
9635 : {
9636 100 : res.AddString(name.c_str());
9637 : }
9638 46 : return res.StealList();
9639 : }
9640 :
9641 : /************************************************************************/
9642 : /* GetRelationship() */
9643 : /************************************************************************/
9644 :
9645 : /** Get a relationship from its name.
9646 : *
9647 : * @return the relationship, or nullptr if not found.
9648 : * @since GDAL 3.6
9649 : */
9650 : const GDALRelationship *
9651 0 : GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const
9652 : {
9653 0 : return nullptr;
9654 : }
9655 :
9656 : /************************************************************************/
9657 : /* GDALDatasetGetRelationship() */
9658 : /************************************************************************/
9659 :
9660 : /** Get a relationship from its name.
9661 : *
9662 : * This is the same as the C++ method GDALDataset::GetRelationship().
9663 : *
9664 : * @param hDS Dataset handle.
9665 : * @param pszName Name of relationship.
9666 : * @return the relationship (ownership remains to the dataset), or nullptr if
9667 : * not found.
9668 : * @since GDAL 3.6
9669 : */
9670 52 : GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,
9671 : const char *pszName)
9672 : {
9673 52 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9674 52 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9675 52 : return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(
9676 52 : GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));
9677 : }
9678 :
9679 : /************************************************************************/
9680 : /* AddRelationship() */
9681 : /************************************************************************/
9682 :
9683 : /** Add a relationship to the dataset.
9684 : *
9685 : * Only a few drivers will support this operation, and some of them might only
9686 : * support it only for some types of relationships.
9687 : *
9688 : * A dataset having at least some support for this
9689 : * operation should report the GDsCAddRelationship dataset capability.
9690 : *
9691 : * Anticipated failures will not be emitted through the CPLError()
9692 : * infrastructure, but will be reported in the failureReason output parameter.
9693 : *
9694 : * When adding a many-to-many relationship
9695 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9696 : * mapping table name (see GDALRelationship::GetMappingTableName) to instruct
9697 : * the driver to create an appropriately named and structured mapping table.
9698 : * Some dataset formats require particular naming conventions and field
9699 : * structures for the mapping table, and delegating the construction of the
9700 : * mapping table to the driver will avoid these pitfalls.
9701 : *
9702 : * @param relationship The relationship definition.
9703 : * @param failureReason Output parameter. Will contain an error message if
9704 : * an error occurs.
9705 : * @return true in case of success.
9706 : * @since GDAL 3.6
9707 : */
9708 0 : bool GDALDataset::AddRelationship(
9709 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9710 : std::string &failureReason)
9711 : {
9712 0 : failureReason = "AddRelationship not supported by this driver";
9713 0 : return false;
9714 : }
9715 :
9716 : /************************************************************************/
9717 : /* GDALDatasetAddRelationship() */
9718 : /************************************************************************/
9719 :
9720 : /** Add a relationship to the dataset.
9721 : *
9722 : * Only a few drivers will support this operation, and some of them might only
9723 : * support it only for some types of relationships.
9724 : *
9725 : * A dataset having at least some support for this
9726 : * operation should report the GDsCAddRelationship dataset capability.
9727 : *
9728 : * Anticipated failures will not be emitted through the CPLError()
9729 : * infrastructure, but will be reported in the failureReason output parameter.
9730 : *
9731 : * When adding a many-to-many relationship
9732 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9733 : * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the
9734 : * driver to create an appropriately named and structured mapping table. Some
9735 : * dataset formats require particular naming conventions and field structures
9736 : * for the mapping table, and delegating the construction of the mapping table
9737 : * to the driver will avoid these pitfalls.
9738 : *
9739 : * @param hDS Dataset handle.
9740 : * @param hRelationship The relationship definition. Contrary to the C++
9741 : * version, the passed object is copied.
9742 : * @param ppszFailureReason Output parameter. Will contain an error message if
9743 : * an error occurs (*ppszFailureReason to be freed
9744 : * with CPLFree). May be NULL.
9745 : * @return true in case of success.
9746 : * @since GDAL 3.6
9747 : */
9748 42 : bool GDALDatasetAddRelationship(GDALDatasetH hDS,
9749 : GDALRelationshipH hRelationship,
9750 : char **ppszFailureReason)
9751 : {
9752 42 : VALIDATE_POINTER1(hDS, __func__, false);
9753 42 : VALIDATE_POINTER1(hRelationship, __func__, false);
9754 : std::unique_ptr<GDALRelationship> poRelationship(
9755 84 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9756 42 : std::string failureReason;
9757 84 : const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(
9758 42 : std::move(poRelationship), failureReason);
9759 42 : if (ppszFailureReason)
9760 : {
9761 0 : *ppszFailureReason =
9762 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9763 : }
9764 42 : return bRet;
9765 : }
9766 :
9767 : /************************************************************************/
9768 : /* DeleteRelationship() */
9769 : /************************************************************************/
9770 :
9771 : /** Removes a relationship from the dataset.
9772 : *
9773 : * Only a few drivers will support this operation.
9774 : *
9775 : * A dataset having at least some support for this
9776 : * operation should report the GDsCDeleteRelationship dataset capability.
9777 : *
9778 : * Anticipated failures will not be emitted through the CPLError()
9779 : * infrastructure, but will be reported in the failureReason output parameter.
9780 : *
9781 : * @param name The relationship name.
9782 : * @param failureReason Output parameter. Will contain an error message if
9783 : * an error occurs.
9784 : * @return true in case of success.
9785 : * @since GDAL 3.6
9786 : */
9787 0 : bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,
9788 : std::string &failureReason)
9789 : {
9790 0 : failureReason = "DeleteRelationship not supported by this driver";
9791 0 : return false;
9792 : }
9793 :
9794 : /************************************************************************/
9795 : /* GDALDatasetDeleteRelationship() */
9796 : /************************************************************************/
9797 :
9798 : /** Removes a relationship from the dataset.
9799 : *
9800 : * Only a few drivers will support this operation.
9801 : *
9802 : * A dataset having at least some support for this
9803 : * operation should report the GDsCDeleteRelationship dataset capability.
9804 : *
9805 : * Anticipated failures will not be emitted through the CPLError()
9806 : * infrastructure, but will be reported in the ppszFailureReason output
9807 : * parameter.
9808 : *
9809 : * @param hDS Dataset handle.
9810 : * @param pszName The relationship name.
9811 : * @param ppszFailureReason Output parameter. Will contain an error message if
9812 : * an error occurs (*ppszFailureReason to be freed
9813 : * with CPLFree). May be NULL.
9814 : * @return true in case of success.
9815 : * @since GDAL 3.6
9816 : */
9817 6 : bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,
9818 : char **ppszFailureReason)
9819 : {
9820 6 : VALIDATE_POINTER1(hDS, __func__, false);
9821 6 : VALIDATE_POINTER1(pszName, __func__, false);
9822 6 : std::string failureReason;
9823 12 : const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(
9824 6 : pszName, failureReason);
9825 6 : if (ppszFailureReason)
9826 : {
9827 0 : *ppszFailureReason =
9828 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9829 : }
9830 6 : return bRet;
9831 : }
9832 :
9833 : /************************************************************************/
9834 : /* UpdateRelationship() */
9835 : /************************************************************************/
9836 :
9837 : /** Updates an existing relationship by replacing its definition.
9838 : *
9839 : * The existing relationship with matching name will be replaced.
9840 : *
9841 : * Only a few drivers will support this operation, and some of them might only
9842 : * support it only for some types of relationships.
9843 : * A dataset having at least some support for this
9844 : * operation should report the GDsCUpdateRelationship dataset capability.
9845 : *
9846 : * Anticipated failures will not be emitted through the CPLError()
9847 : * infrastructure, but will be reported in the failureReason output parameter.
9848 : *
9849 : * @param relationship The relationship definition.
9850 : * @param failureReason Output parameter. Will contain an error message if
9851 : * an error occurs.
9852 : * @return true in case of success.
9853 : * @since GDAL 3.6
9854 : */
9855 0 : bool GDALDataset::UpdateRelationship(
9856 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9857 : std::string &failureReason)
9858 : {
9859 0 : failureReason = "UpdateRelationship not supported by this driver";
9860 0 : return false;
9861 : }
9862 :
9863 : /************************************************************************/
9864 : /* GDALDatasetUpdateRelationship() */
9865 : /************************************************************************/
9866 :
9867 : /** Updates an existing relationship by replacing its definition.
9868 : *
9869 : * The existing relationship with matching name will be replaced.
9870 : *
9871 : * Only a few drivers will support this operation, and some of them might only
9872 : * support it only for some types of relationships.
9873 : * A dataset having at least some support for this
9874 : * operation should report the GDsCUpdateRelationship dataset capability.
9875 : *
9876 : * Anticipated failures will not be emitted through the CPLError()
9877 : * infrastructure, but will be reported in the failureReason output parameter.
9878 : *
9879 : * @param hDS Dataset handle.
9880 : * @param hRelationship The relationship definition. Contrary to the C++
9881 : * version, the passed object is copied.
9882 : * @param ppszFailureReason Output parameter. Will contain an error message if
9883 : * an error occurs (*ppszFailureReason to be freed
9884 : * with CPLFree). May be NULL.
9885 : * @return true in case of success.
9886 : * @since GDAL 3.5
9887 : */
9888 9 : bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,
9889 : GDALRelationshipH hRelationship,
9890 : char **ppszFailureReason)
9891 : {
9892 9 : VALIDATE_POINTER1(hDS, __func__, false);
9893 9 : VALIDATE_POINTER1(hRelationship, __func__, false);
9894 : std::unique_ptr<GDALRelationship> poRelationship(
9895 18 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9896 9 : std::string failureReason;
9897 18 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(
9898 9 : std::move(poRelationship), failureReason);
9899 9 : if (ppszFailureReason)
9900 : {
9901 0 : *ppszFailureReason =
9902 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9903 : }
9904 9 : return bRet;
9905 : }
9906 :
9907 : /************************************************************************/
9908 : /* GDALDatasetSetQueryLoggerFunc() */
9909 : /************************************************************************/
9910 :
9911 : /**
9912 : * Sets the SQL query logger callback.
9913 : *
9914 : * When supported by the driver, the callback will be called with
9915 : * the executed SQL text, the error message, the execution time in milliseconds,
9916 : * the number of records fetched/affected and the client status data.
9917 : *
9918 : * A value of -1 in the execution time or in the number of records indicates
9919 : * that the values are unknown.
9920 : *
9921 : * @param hDS Dataset handle.
9922 : * @param pfnQueryLoggerFunc Callback function
9923 : * @param poQueryLoggerArg Opaque client status data
9924 : * @return true in case of success.
9925 : * @since GDAL 3.7
9926 : */
9927 1 : bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,
9928 : GDALQueryLoggerFunc pfnQueryLoggerFunc,
9929 : void *poQueryLoggerArg)
9930 : {
9931 1 : VALIDATE_POINTER1(hDS, __func__, false);
9932 2 : return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,
9933 1 : poQueryLoggerArg);
9934 : }
9935 :
9936 : //! @cond Doxygen_Suppress
9937 :
9938 : /************************************************************************/
9939 : /* SetEnableOverviews() */
9940 : /************************************************************************/
9941 :
9942 7491 : void GDALDataset::SetEnableOverviews(bool bEnable)
9943 : {
9944 7491 : if (m_poPrivate)
9945 : {
9946 7491 : m_poPrivate->m_bOverviewsEnabled = bEnable;
9947 : }
9948 7491 : }
9949 :
9950 : /************************************************************************/
9951 : /* AreOverviewsEnabled() */
9952 : /************************************************************************/
9953 :
9954 2005600 : bool GDALDataset::AreOverviewsEnabled() const
9955 : {
9956 2005600 : return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
9957 : }
9958 :
9959 : /************************************************************************/
9960 : /* IsAllBands() */
9961 : /************************************************************************/
9962 :
9963 3488 : bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const
9964 : {
9965 3488 : if (nBands != nBandCount)
9966 1 : return false;
9967 3487 : if (panBandList)
9968 : {
9969 12663 : for (int i = 0; i < nBandCount; ++i)
9970 : {
9971 9268 : if (panBandList[i] != i + 1)
9972 27 : return false;
9973 : }
9974 : }
9975 3460 : return true;
9976 : }
9977 :
9978 : //! @endcond
9979 :
9980 : /************************************************************************/
9981 : /* GetCompressionFormats() */
9982 : /************************************************************************/
9983 :
9984 : /** Return the compression formats that can be natively obtained for the
9985 : * window of interest and requested bands.
9986 : *
9987 : * For example, a tiled dataset may be able to return data in a compressed
9988 : * format if the window of interest matches exactly a tile. For some formats,
9989 : * drivers may also be able to merge several tiles together (not currently
9990 : * implemented though).
9991 : *
9992 : * Each format string is a pseudo MIME type, whose first part can be passed
9993 : * as the pszFormat argument of ReadCompressedData(), with additional
9994 : * parameters specified as key=value with a semi-colon separator.
9995 : *
9996 : * The amount and types of optional parameters passed after the MIME type is
9997 : * format dependent, and driver dependent (some drivers might not be able to
9998 : * return those extra information without doing a rather costly processing).
9999 : *
10000 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
10001 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
10002 : * consequently "JPEG" can be passed as the pszFormat argument of
10003 : * ReadCompressedData(). For JPEG, implementations can use the
10004 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
10005 : * above from a JPEG codestream.
10006 : *
10007 : * Several values might be returned. For example,
10008 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
10009 : * if the JPEGXL codestream includes a JPEG reconstruction box.
10010 : *
10011 : * In the general case this method will return an empty list.
10012 : *
10013 : * This is the same as C function GDALDatasetGetCompressionFormats().
10014 : *
10015 : * @param nXOff The pixel offset to the top left corner of the region
10016 : * of the band to be accessed. This would be zero to start from the left side.
10017 : *
10018 : * @param nYOff The line offset to the top left corner of the region
10019 : * of the band to be accessed. This would be zero to start from the top.
10020 : *
10021 : * @param nXSize The width of the region of the band to be accessed in pixels.
10022 : *
10023 : * @param nYSize The height of the region of the band to be accessed in lines.
10024 : *
10025 : * @param nBandCount the number of bands being requested.
10026 : *
10027 : * @param panBandList the list of nBandCount band numbers.
10028 : * Note band numbers are 1 based. This may be NULL to select the first
10029 : * nBandCount bands.
10030 : *
10031 : * @return a list of compatible formats (which may be empty)
10032 : *
10033 : * For example, to check if native compression format(s) are available on the
10034 : * whole image:
10035 : * \code{.cpp}
10036 : * const CPLStringList aosFormats =
10037 : * poDataset->GetCompressionFormats(0, 0,
10038 : * poDataset->GetRasterXSize(),
10039 : * poDataset->GetRasterYSize(),
10040 : * poDataset->GetRasterCount(),
10041 : * nullptr);
10042 : * for( const char* pszFormat: aosFormats )
10043 : * {
10044 : * // Remove optional parameters and just print out the MIME type.
10045 : * const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));
10046 : * printf("Found format %s\n, aosTokens[0]);
10047 : * }
10048 : * \endcode
10049 : *
10050 : * @since GDAL 3.7
10051 : */
10052 : CPLStringList
10053 0 : GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
10054 : CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10055 : CPL_UNUSED int nBandCount,
10056 : CPL_UNUSED const int *panBandList)
10057 : {
10058 0 : return CPLStringList();
10059 : }
10060 :
10061 : /************************************************************************/
10062 : /* GDALDatasetGetCompressionFormats() */
10063 : /************************************************************************/
10064 :
10065 : /** Return the compression formats that can be natively obtained for the
10066 : * window of interest and requested bands.
10067 : *
10068 : * For example, a tiled dataset may be able to return data in a compressed
10069 : * format if the window of interest matches exactly a tile. For some formats,
10070 : * drivers may also be able to merge several tiles together (not currently
10071 : * implemented though).
10072 : *
10073 : * Each format string is a pseudo MIME type, whose first part can be passed
10074 : * as the pszFormat argument of ReadCompressedData(), with additional
10075 : * parameters specified as key=value with a semi-colon separator.
10076 : *
10077 : * The amount and types of optional parameters passed after the MIME type is
10078 : * format dependent, and driver dependent (some drivers might not be able to
10079 : * return those extra information without doing a rather costly processing).
10080 : *
10081 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
10082 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
10083 : * consequently "JPEG" can be passed as the pszFormat argument of
10084 : * ReadCompressedData(). For JPEG, implementations can use the
10085 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
10086 : * above from a JPEG codestream.
10087 : *
10088 : * Several values might be returned. For example,
10089 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
10090 : * if the JPEGXL codestream includes a JPEG reconstruction box.
10091 : *
10092 : * In the general case this method will return an empty list.
10093 : *
10094 : * This is the same as C++ method GDALDataset::GetCompressionFormats().
10095 : *
10096 : * @param hDS Dataset handle.
10097 : *
10098 : * @param nXOff The pixel offset to the top left corner of the region
10099 : * of the band to be accessed. This would be zero to start from the left side.
10100 : *
10101 : * @param nYOff The line offset to the top left corner of the region
10102 : * of the band to be accessed. This would be zero to start from the top.
10103 : *
10104 : * @param nXSize The width of the region of the band to be accessed in pixels.
10105 : *
10106 : * @param nYSize The height of the region of the band to be accessed in lines.
10107 : *
10108 : * @param nBandCount the number of bands being requested.
10109 : *
10110 : * @param panBandList the list of nBandCount band numbers.
10111 : * Note band numbers are 1 based. This may be NULL to select the first
10112 : * nBandCount bands.
10113 : *
10114 : * @return a list of compatible formats (which may be empty) that should be
10115 : * freed with CSLDestroy(), or nullptr.
10116 : *
10117 : * @since GDAL 3.7
10118 : */
10119 9 : char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,
10120 : int nXSize, int nYSize, int nBandCount,
10121 : const int *panBandList)
10122 : {
10123 9 : VALIDATE_POINTER1(hDS, __func__, nullptr);
10124 9 : return GDALDataset::FromHandle(hDS)
10125 9 : ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,
10126 9 : panBandList)
10127 9 : .StealList();
10128 : }
10129 :
10130 : /************************************************************************/
10131 : /* ReadCompressedData() */
10132 : /************************************************************************/
10133 :
10134 : /** Return the compressed content that can be natively obtained for the
10135 : * window of interest and requested bands.
10136 : *
10137 : * For example, a tiled dataset may be able to return data in compressed format
10138 : * if the window of interest matches exactly a tile. For some formats, drivers
10139 : * may also be example to merge several tiles together (not currently
10140 : * implemented though).
10141 : *
10142 : * The implementation should make sure that the content returned forms a valid
10143 : * standalone file. For example, for the GeoTIFF implementation of this method,
10144 : * when extracting a JPEG tile, the method will automatically add the content
10145 : * of the JPEG Huffman and/or quantization tables that might be stored in the
10146 : * TIFF JpegTables tag, and not in tile data itself.
10147 : *
10148 : * In the general case this method will return CE_Failure.
10149 : *
10150 : * This is the same as C function GDALDatasetReadCompressedData().
10151 : *
10152 : * @param pszFormat Requested compression format (e.g. "JPEG",
10153 : * "WEBP", "JXL"). This is the MIME type of one of the values
10154 : * returned by GetCompressionFormats(). The format string is designed to
10155 : * potentially include at a later point key=value optional parameters separated
10156 : * by a semi-colon character. At time of writing, none are implemented.
10157 : * ReadCompressedData() implementations should verify optional parameters and
10158 : * return CE_Failure if they cannot support one of them.
10159 : *
10160 : * @param nXOff The pixel offset to the top left corner of the region
10161 : * of the band to be accessed. This would be zero to start from the left side.
10162 : *
10163 : * @param nYOff The line offset to the top left corner of the region
10164 : * of the band to be accessed. This would be zero to start from the top.
10165 : *
10166 : * @param nXSize The width of the region of the band to be accessed in pixels.
10167 : *
10168 : * @param nYSize The height of the region of the band to be accessed in lines.
10169 : *
10170 : * @param nBandCount the number of bands being requested.
10171 : *
10172 : * @param panBandList the list of nBandCount band numbers.
10173 : * Note band numbers are 1 based. This may be NULL to select the first
10174 : * nBandCount bands.
10175 : *
10176 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10177 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10178 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10179 : * buffer will be filled with the compressed data, provided that pnBufferSize
10180 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10181 : * of *ppBuffer, is sufficiently large to hold the data.
10182 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10183 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10184 : * free it with VSIFree().
10185 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10186 : * but *pnBufferSize will be updated with an upper bound of the size that would
10187 : * be necessary to hold it (if pnBufferSize != nullptr).
10188 : *
10189 : * @param pnBufferSize Output buffer size, or nullptr.
10190 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10191 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10192 : * method is successful, *pnBufferSize will be updated with the actual size
10193 : * used.
10194 : *
10195 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10196 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10197 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10198 : * *ppszDetailedFormat might contain strings like
10199 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10200 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10201 : * The string will contain at least as much information as what
10202 : * GetCompressionFormats() returns, and potentially more when
10203 : * ppBuffer != nullptr.
10204 : *
10205 : * @return CE_None in case of success, CE_Failure otherwise.
10206 : *
10207 : * For example, to request JPEG content on the whole image and let GDAL deal
10208 : * with the buffer allocation.
10209 : * \code{.cpp}
10210 : * void* pBuffer = nullptr;
10211 : * size_t nBufferSize = 0;
10212 : * CPLErr eErr =
10213 : * poDataset->ReadCompressedData("JPEG",
10214 : * 0, 0,
10215 : * poDataset->GetRasterXSize(),
10216 : * poDataset->GetRasterYSize(),
10217 : * poDataset->GetRasterCount(),
10218 : * nullptr, // panBandList
10219 : * &pBuffer,
10220 : * &nBufferSize,
10221 : * nullptr // ppszDetailedFormat
10222 : * );
10223 : * if (eErr == CE_None)
10224 : * {
10225 : * CPLAssert(pBuffer != nullptr);
10226 : * CPLAssert(nBufferSize > 0);
10227 : * VSILFILE* fp = VSIFOpenL("my.jpeg", "wb");
10228 : * if (fp)
10229 : * {
10230 : * VSIFWriteL(pBuffer, nBufferSize, 1, fp);
10231 : * VSIFCloseL(fp);
10232 : * }
10233 : * VSIFree(pBuffer);
10234 : * }
10235 : * \endcode
10236 : *
10237 : * Or to manage the buffer allocation on your side:
10238 : * \code{.cpp}
10239 : * size_t nUpperBoundBufferSize = 0;
10240 : * CPLErr eErr =
10241 : * poDataset->ReadCompressedData("JPEG",
10242 : * 0, 0,
10243 : * poDataset->GetRasterXSize(),
10244 : * poDataset->GetRasterYSize(),
10245 : * poDataset->GetRasterCount(),
10246 : * nullptr, // panBandList
10247 : * nullptr, // ppBuffer,
10248 : * &nUpperBoundBufferSize,
10249 : * nullptr // ppszDetailedFormat
10250 : * );
10251 : * if (eErr == CE_None)
10252 : * {
10253 : * std::vector<uint8_t> myBuffer;
10254 : * myBuffer.resize(nUpperBoundBufferSize);
10255 : * void* pBuffer = myBuffer.data();
10256 : * size_t nActualSize = nUpperBoundBufferSize;
10257 : * char* pszDetailedFormat = nullptr;
10258 : * // We also request detailed format, but we could have passed it to
10259 : * // nullptr as well.
10260 : * eErr =
10261 : * poDataset->ReadCompressedData("JPEG",
10262 : * 0, 0,
10263 : * poDataset->GetRasterXSize(),
10264 : * poDataset->GetRasterYSize(),
10265 : * poDataset->GetRasterCount(),
10266 : * nullptr, // panBandList
10267 : * &pBuffer,
10268 : * &nActualSize,
10269 : * &pszDetailedFormat);
10270 : * if (eErr == CE_None)
10271 : * {
10272 : * CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified
10273 : * CPLAssert(nActualSize <= nUpperBoundBufferSize);
10274 : * myBuffer.resize(nActualSize);
10275 : * // do something useful
10276 : * VSIFree(pszDetailedFormat);
10277 : * }
10278 : * }
10279 : * \endcode
10280 : *
10281 : * @since GDAL 3.7
10282 : */
10283 462 : CPLErr GDALDataset::ReadCompressedData(
10284 : CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,
10285 : CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10286 : CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,
10287 : CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,
10288 : CPL_UNUSED char **ppszDetailedFormat)
10289 : {
10290 462 : return CE_Failure;
10291 : }
10292 :
10293 : /************************************************************************/
10294 : /* GDALDatasetReadCompressedData() */
10295 : /************************************************************************/
10296 :
10297 : /** Return the compressed content that can be natively obtained for the
10298 : * window of interest and requested bands.
10299 : *
10300 : * For example, a tiled dataset may be able to return data in compressed format
10301 : * if the window of interest matches exactly a tile. For some formats, drivers
10302 : * may also be example to merge several tiles together (not currently
10303 : * implemented though).
10304 : *
10305 : * The implementation should make sure that the content returned forms a valid
10306 : * standalone file. For example, for the GeoTIFF implementation of this method,
10307 : * when extracting a JPEG tile, the method will automatically adds the content
10308 : * of the JPEG Huffman and/or quantization tables that might be stored in the
10309 : * TIFF JpegTables tag, and not in tile data itself.
10310 : *
10311 : * In the general case this method will return CE_Failure.
10312 : *
10313 : * This is the same as C++ method GDALDataset:ReadCompressedData().
10314 : *
10315 : * @param hDS Dataset handle.
10316 : *
10317 : * @param pszFormat Requested compression format (e.g. "JPEG",
10318 : * "WEBP", "JXL"). This is the MIME type of one of the values
10319 : * returned by GetCompressionFormats(). The format string is designed to
10320 : * potentially include at a later point key=value optional parameters separated
10321 : * by a semi-colon character. At time of writing, none are implemented.
10322 : * ReadCompressedData() implementations should verify optional parameters and
10323 : * return CE_Failure if they cannot support one of them.
10324 : *
10325 : * @param nXOff The pixel offset to the top left corner of the region
10326 : * of the band to be accessed. This would be zero to start from the left side.
10327 : *
10328 : * @param nYOff The line offset to the top left corner of the region
10329 : * of the band to be accessed. This would be zero to start from the top.
10330 : *
10331 : * @param nXSize The width of the region of the band to be accessed in pixels.
10332 : *
10333 : * @param nYSize The height of the region of the band to be accessed in lines.
10334 : *
10335 : * @param nBandCount the number of bands being requested.
10336 : *
10337 : * @param panBandList the list of nBandCount band numbers.
10338 : * Note band numbers are 1 based. This may be NULL to select the first
10339 : * nBandCount bands.
10340 : *
10341 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10342 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10343 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10344 : * buffer will be filled with the compressed data, provided that pnBufferSize
10345 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10346 : * of *ppBuffer, is sufficiently large to hold the data.
10347 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10348 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10349 : * free it with VSIFree().
10350 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10351 : * but *pnBufferSize will be updated with an upper bound of the size that would
10352 : * be necessary to hold it (if pnBufferSize != nullptr).
10353 : *
10354 : * @param pnBufferSize Output buffer size, or nullptr.
10355 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10356 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10357 : * method is successful, *pnBufferSize will be updated with the actual size
10358 : * used.
10359 : *
10360 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10361 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10362 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10363 : * *ppszDetailedFormat might contain strings like
10364 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10365 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10366 : * The string will contain at least as much information as what
10367 : * GetCompressionFormats() returns, and potentially more when
10368 : * ppBuffer != nullptr.
10369 : *
10370 : * @return CE_None in case of success, CE_Failure otherwise.
10371 : *
10372 : * @since GDAL 3.7
10373 : */
10374 28 : CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,
10375 : int nXOff, int nYOff, int nXSize,
10376 : int nYSize, int nBandCount,
10377 : const int *panBandList, void **ppBuffer,
10378 : size_t *pnBufferSize,
10379 : char **ppszDetailedFormat)
10380 : {
10381 28 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10382 56 : return GDALDataset::FromHandle(hDS)->ReadCompressedData(
10383 : pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,
10384 28 : ppBuffer, pnBufferSize, ppszDetailedFormat);
10385 : }
10386 :
10387 : /************************************************************************/
10388 : /* CanBeCloned() */
10389 : /************************************************************************/
10390 :
10391 : //! @cond Doxygen_Suppress
10392 :
10393 : /** This method is called by GDALThreadSafeDataset::Create() to determine if
10394 : * it is possible to create a thread-safe wrapper for a dataset, which involves
10395 : * the ability to Clone() it.
10396 : *
10397 : * Implementations of this method must be thread-safe.
10398 : *
10399 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10400 : * expressing the intended use for thread-safety.
10401 : * Currently, the only valid scope is in the base
10402 : * implementation is GDAL_OF_RASTER.
10403 : * @param bCanShareState Determines if cloned datasets are allowed to share
10404 : * state with the dataset they have been cloned from.
10405 : * If set to true, the dataset from which they have been
10406 : * cloned from must remain opened during the lifetime of
10407 : * its clones.
10408 : * @return true if the Clone() method is expected to succeed with the same values
10409 : * of nScopeFlags and bCanShareState.
10410 : */
10411 149 : bool GDALDataset::CanBeCloned(int nScopeFlags,
10412 : [[maybe_unused]] bool bCanShareState) const
10413 : {
10414 149 : return m_bCanBeReopened && nScopeFlags == GDAL_OF_RASTER;
10415 : }
10416 :
10417 : //! @endcond
10418 :
10419 : /************************************************************************/
10420 : /* Clone() */
10421 : /************************************************************************/
10422 :
10423 : //! @cond Doxygen_Suppress
10424 :
10425 : /** This method "clones" the current dataset, that is it returns a new instance
10426 : * that is opened on the same underlying "file".
10427 : *
10428 : * The base implementation uses GDALDataset::Open() to re-open the dataset.
10429 : * The MEM driver has a specialized implementation that returns a new instance,
10430 : * but which shares the same memory buffer as this.
10431 : *
10432 : * Implementations of this method must be thread-safe.
10433 : *
10434 : * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10435 : * expressing the intended use for thread-safety.
10436 : * Currently, the only valid scope is in the base
10437 : * implementation is GDAL_OF_RASTER.
10438 : * @param bCanShareState Determines if cloned datasets are allowed to share
10439 : * state with the dataset they have been cloned from.
10440 : * If set to true, the dataset from which they have been
10441 : * cloned from must remain opened during the lifetime of
10442 : * its clones.
10443 : * @return a new instance, or nullptr in case of error.
10444 : */
10445 : std::unique_ptr<GDALDataset>
10446 2051 : GDALDataset::Clone(int nScopeFlags, [[maybe_unused]] bool bCanShareState) const
10447 : {
10448 4102 : CPLStringList aosAllowedDrivers;
10449 2051 : if (poDriver)
10450 2051 : aosAllowedDrivers.AddString(poDriver->GetDescription());
10451 : return std::unique_ptr<GDALDataset>(GDALDataset::Open(
10452 2051 : GetDescription(),
10453 2051 : nScopeFlags | GDAL_OF_INTERNAL | GDAL_OF_VERBOSE_ERROR,
10454 4102 : aosAllowedDrivers.List(), papszOpenOptions));
10455 : }
10456 :
10457 : //! @endcond
10458 :
10459 : /************************************************************************/
10460 : /* GeolocationToPixelLine() */
10461 : /************************************************************************/
10462 :
10463 : /** Transform georeferenced coordinates to pixel/line coordinates.
10464 : *
10465 : * When poSRS is null, those georeferenced coordinates (dfGeolocX, dfGeolocY)
10466 : * must be in the "natural" SRS of the dataset, that is the one returned by
10467 : * GetSpatialRef() if there is a geotransform, GetGCPSpatialRef() if there are
10468 : * GCPs, WGS 84 if there are RPC coefficients, or the SRS of the geolocation
10469 : * array (generally WGS 84) if there is a geolocation array.
10470 : * If that natural SRS is a geographic one, dfGeolocX must be a longitude, and
10471 : * dfGeolocY a latitude. If that natural SRS is a projected one, dfGeolocX must
10472 : * be a easting, and dfGeolocY a northing.
10473 : *
10474 : * When poSRS is set to a non-null value, (dfGeolocX, dfGeolocY) must be
10475 : * expressed in that CRS, and that tuple must be conformant with the
10476 : * data-axis-to-crs-axis setting of poSRS, that is the one returned by
10477 : * the OGRSpatialReference::GetDataAxisToSRSAxisMapping(). If you want to be sure
10478 : * of the axis order, then make sure to call poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER)
10479 : * before calling this method, and in that case, dfGeolocX must be a longitude
10480 : * or an easting value, and dfGeolocX a latitude or a northing value.
10481 : *
10482 : * This method uses GDALCreateGenImgProjTransformer2() underneath.
10483 : *
10484 : * @param dfGeolocX X coordinate of the position (longitude or easting if poSRS
10485 : * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10486 : * where interpolation should be done.
10487 : * @param dfGeolocY Y coordinate of the position (latitude or northing if poSRS
10488 : * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10489 : * where interpolation should be done.
10490 : * @param poSRS If set, override the natural CRS in which dfGeolocX, dfGeolocY are expressed
10491 : * @param[out] pdfPixel Pointer to the variable where to the store the pixel/column coordinate.
10492 : * @param[out] pdfLine Pointer to the variable where to the store the line coordinate.
10493 : * @param papszTransformerOptions Options accepted by GDALCreateGenImgProjTransformer2(), or nullptr.
10494 : *
10495 : * @return CE_None on success, or an error code on failure.
10496 : * @since GDAL 3.11
10497 : */
10498 :
10499 : CPLErr
10500 15 : GDALDataset::GeolocationToPixelLine(double dfGeolocX, double dfGeolocY,
10501 : const OGRSpatialReference *poSRS,
10502 : double *pdfPixel, double *pdfLine,
10503 : CSLConstList papszTransformerOptions) const
10504 : {
10505 30 : CPLStringList aosTO(papszTransformerOptions);
10506 :
10507 15 : if (poSRS)
10508 : {
10509 4 : const char *const apszOptions[] = {"FORMAT=WKT2", nullptr};
10510 8 : const std::string osWKT = poSRS->exportToWkt(apszOptions);
10511 4 : aosTO.SetNameValue("DST_SRS", osWKT.c_str());
10512 4 : const auto eAxisMappingStrategy = poSRS->GetAxisMappingStrategy();
10513 4 : if (eAxisMappingStrategy == OAMS_TRADITIONAL_GIS_ORDER)
10514 : aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10515 1 : "TRADITIONAL_GIS_ORDER");
10516 3 : else if (eAxisMappingStrategy == OAMS_AUTHORITY_COMPLIANT)
10517 : aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10518 1 : "AUTHORITY_COMPLIANT");
10519 : else
10520 : {
10521 2 : const auto &anValues = poSRS->GetDataAxisToSRSAxisMapping();
10522 4 : std::string osVal;
10523 6 : for (int v : anValues)
10524 : {
10525 4 : if (!osVal.empty())
10526 2 : osVal += ',';
10527 4 : osVal += std::to_string(v);
10528 : }
10529 : aosTO.SetNameValue("DST_SRS_DATA_AXIS_TO_SRS_AXIS_MAPPING",
10530 2 : osVal.c_str());
10531 : }
10532 : }
10533 :
10534 15 : auto hTransformer = GDALCreateGenImgProjTransformer2(
10535 : GDALDataset::ToHandle(const_cast<GDALDataset *>(this)), nullptr,
10536 15 : aosTO.List());
10537 15 : if (hTransformer == nullptr)
10538 : {
10539 1 : return CE_Failure;
10540 : }
10541 :
10542 14 : double z = 0;
10543 14 : int bSuccess = 0;
10544 14 : GDALGenImgProjTransform(hTransformer, TRUE, 1, &dfGeolocX, &dfGeolocY, &z,
10545 : &bSuccess);
10546 14 : GDALDestroyTransformer(hTransformer);
10547 14 : if (bSuccess)
10548 : {
10549 14 : if (pdfPixel)
10550 14 : *pdfPixel = dfGeolocX;
10551 14 : if (pdfLine)
10552 14 : *pdfLine = dfGeolocY;
10553 14 : return CE_None;
10554 : }
10555 : else
10556 : {
10557 0 : return CE_Failure;
10558 : }
10559 : }
10560 :
10561 : /************************************************************************/
10562 : /* GDALDatasetGeolocationToPixelLine() */
10563 : /************************************************************************/
10564 :
10565 : /** Transform georeferenced coordinates to pixel/line coordinates.
10566 : *
10567 : * @see GDALDataset::GeolocationToPixelLine()
10568 : * @since GDAL 3.11
10569 : */
10570 :
10571 0 : CPLErr GDALDatasetGeolocationToPixelLine(GDALDatasetH hDS, double dfGeolocX,
10572 : double dfGeolocY,
10573 : OGRSpatialReferenceH hSRS,
10574 : double *pdfPixel, double *pdfLine,
10575 : CSLConstList papszTransformerOptions)
10576 : {
10577 0 : VALIDATE_POINTER1(hDS, "GDALDatasetGeolocationToPixelLine", CE_Failure);
10578 :
10579 0 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
10580 0 : return poDS->GeolocationToPixelLine(
10581 0 : dfGeolocX, dfGeolocY, OGRSpatialReference::FromHandle(hSRS), pdfPixel,
10582 0 : pdfLine, papszTransformerOptions);
10583 : }
10584 :
10585 : /************************************************************************/
10586 : /* GetExtent() */
10587 : /************************************************************************/
10588 :
10589 : /** Return extent of dataset in specified CRS.
10590 : *
10591 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10592 : *
10593 : * For rasters, the base implementation of this method only succeeds if
10594 : * GetGeoTransform() and GetSpatialRef() succeed.
10595 : * For vectors, the base implementation of this method iterates over layers
10596 : * and call their OGRLayer::GetExtent() method.
10597 : *
10598 : * TestCapability(GDsCFastGetExtent) can be used to test if the execution
10599 : * time of this method is fast.
10600 : *
10601 : * This is the same as C function GDALGetExtent()
10602 : *
10603 : * @param[out] psExtent Pointer to output extent. Must NOT be null.
10604 : * @param poCRS CRS in which to express the extent. If not specified, this will
10605 : * be the raster CRS or the CRS of the first layer for a vector dataset.
10606 : * @return CE_None in case of success, CE_Failure otherwise
10607 : * @since GDAL 3.12
10608 : */
10609 :
10610 23 : CPLErr GDALDataset::GetExtent(OGREnvelope *psExtent,
10611 : const OGRSpatialReference *poCRS) const
10612 : {
10613 23 : auto poThisDS = const_cast<GDALDataset *>(this);
10614 23 : const OGRSpatialReference *poThisCRS = poThisDS->GetSpatialRef();
10615 23 : int nLayerCount = 0;
10616 23 : if (!poThisCRS)
10617 : {
10618 11 : nLayerCount = poThisDS->GetLayerCount();
10619 11 : if (nLayerCount >= 1)
10620 : {
10621 3 : if (auto poLayer = poThisDS->GetLayer(0))
10622 3 : poThisCRS = poLayer->GetSpatialRef();
10623 : }
10624 11 : if (poCRS && !poThisCRS)
10625 3 : return CE_Failure;
10626 : }
10627 20 : if (!poCRS)
10628 15 : poCRS = poThisCRS;
10629 :
10630 20 : *psExtent = OGREnvelope();
10631 :
10632 20 : GDALGeoTransform gt;
10633 20 : const bool bHasGT = poThisDS->GetGeoTransform(gt) == CE_None;
10634 20 : if (bHasGT)
10635 : {
10636 0 : std::unique_ptr<OGRCoordinateTransformation> poCT;
10637 15 : if (poCRS)
10638 : {
10639 12 : poCT.reset(OGRCreateCoordinateTransformation(poThisCRS, poCRS));
10640 : }
10641 :
10642 15 : constexpr int DENSIFY_POINT_COUNT = 21;
10643 15 : double dfULX = gt[0];
10644 15 : double dfULY = gt[3];
10645 15 : double dfURX = 0, dfURY = 0;
10646 15 : gt.Apply(nRasterXSize, 0, &dfURX, &dfURY);
10647 15 : double dfLLX = 0, dfLLY = 0;
10648 15 : gt.Apply(0, nRasterYSize, &dfLLX, &dfLLY);
10649 15 : double dfLRX = 0, dfLRY = 0;
10650 15 : gt.Apply(nRasterXSize, nRasterYSize, &dfLRX, &dfLRY);
10651 15 : const double xmin = std::min({dfULX, dfURX, dfLLX, dfLRX});
10652 15 : const double ymin = std::min({dfULY, dfURY, dfLLY, dfLRY});
10653 15 : const double xmax = std::max({dfULX, dfURX, dfLLX, dfLRX});
10654 15 : const double ymax = std::max({dfULY, dfURY, dfLLY, dfLRY});
10655 15 : if (poCT)
10656 : {
10657 12 : OGREnvelope sEnvTmp;
10658 24 : if (!poCT->TransformBounds(xmin, ymin, xmax, ymax, &(sEnvTmp.MinX),
10659 : &(sEnvTmp.MinY), &(sEnvTmp.MaxX),
10660 12 : &(sEnvTmp.MaxY), DENSIFY_POINT_COUNT))
10661 : {
10662 0 : return CE_Failure;
10663 : }
10664 12 : *psExtent = sEnvTmp;
10665 : }
10666 : else
10667 : {
10668 3 : psExtent->MinX = xmin;
10669 3 : psExtent->MinY = ymin;
10670 3 : psExtent->MaxX = xmax;
10671 3 : psExtent->MaxY = ymax;
10672 : }
10673 : }
10674 :
10675 20 : if (nLayerCount > 0)
10676 : {
10677 6 : for (auto &&poLayer : poThisDS->GetLayers())
10678 : {
10679 3 : auto poLayerCRS = poLayer->GetSpatialRef();
10680 3 : if (poLayerCRS)
10681 : {
10682 3 : OGREnvelope sLayerExtent;
10683 3 : if (poLayer->GetExtent(&sLayerExtent) == OGRERR_NONE)
10684 : {
10685 : auto poCT = std::unique_ptr<OGRCoordinateTransformation>(
10686 6 : OGRCreateCoordinateTransformation(poLayerCRS, poCRS));
10687 3 : if (poCT)
10688 : {
10689 3 : constexpr int DENSIFY_POINT_COUNT = 21;
10690 3 : OGREnvelope sEnvTmp;
10691 3 : if (poCT->TransformBounds(
10692 : sLayerExtent.MinX, sLayerExtent.MinY,
10693 : sLayerExtent.MaxX, sLayerExtent.MaxY,
10694 : &(sEnvTmp.MinX), &(sEnvTmp.MinY),
10695 : &(sEnvTmp.MaxX), &(sEnvTmp.MaxY),
10696 3 : DENSIFY_POINT_COUNT))
10697 : {
10698 3 : psExtent->Merge(sEnvTmp);
10699 : }
10700 : }
10701 : }
10702 : }
10703 : }
10704 : }
10705 :
10706 20 : return psExtent->IsInit() ? CE_None : CE_Failure;
10707 : }
10708 :
10709 : /************************************************************************/
10710 : /* GDALGetExtent() */
10711 : /************************************************************************/
10712 :
10713 : /** Return extent of dataset in specified CRS.
10714 : *
10715 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10716 : *
10717 : * For rasters, the base implementation of this method only succeeds if
10718 : * GetGeoTransform() and GetSpatialRef() succeed.
10719 : * For vectors, the base implementation of this method iterates over layers
10720 : * and call their OGRLayer::GetExtent() method.
10721 : *
10722 : * TestCapability(GDsCFastGetExtent) can be used to test if the execution
10723 : * time of this method is fast.
10724 : *
10725 : * This is the same as C++ method GDALDataset::GetExtent()
10726 : *
10727 : * @param hDS Dataset handle. Must NOT be null.
10728 : * @param[out] psExtent Pointer to output extent. Must NOT be null.
10729 : * @param hCRS CRS in which to express the extent. If not specified, this will
10730 : * be the raster CRS or the CRS of the first layer for a vector dataset.
10731 : * @return extent in poCRS (valid only if IsInit() method returns true)
10732 : * @since GDAL 3.12
10733 : */
10734 :
10735 10 : CPLErr GDALGetExtent(GDALDatasetH hDS, OGREnvelope *psExtent,
10736 : OGRSpatialReferenceH hCRS)
10737 : {
10738 10 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10739 10 : VALIDATE_POINTER1(psExtent, __func__, CE_Failure);
10740 20 : return GDALDataset::FromHandle(hDS)->GetExtent(
10741 10 : psExtent, OGRSpatialReference::FromHandle(hCRS));
10742 : }
10743 :
10744 : /************************************************************************/
10745 : /* GetExtentWGS84LongLat() */
10746 : /************************************************************************/
10747 :
10748 : /** Return extent of dataset in WGS84 longitude/latitude
10749 : *
10750 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10751 : *
10752 : * TestCapability(GDsCFastGetExtentWGS84LongLat) can be used to test if the execution
10753 : * time of this method is fast.
10754 : *
10755 : * This is the same as C function GDALGetExtentWGS84LongLat()
10756 : *
10757 : * @return extent (valid only if IsInit() method returns true)
10758 : * @since GDAL 3.12
10759 : */
10760 :
10761 6 : CPLErr GDALDataset::GetExtentWGS84LongLat(OGREnvelope *psExtent) const
10762 : {
10763 12 : OGRSpatialReference oSRS_WGS84;
10764 6 : oSRS_WGS84.SetFromUserInput("WGS84");
10765 6 : oSRS_WGS84.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
10766 12 : return GetExtent(psExtent, &oSRS_WGS84);
10767 : }
10768 :
10769 : /************************************************************************/
10770 : /* GDALGetExtentWGS84LongLat() */
10771 : /************************************************************************/
10772 :
10773 : /** Return extent of dataset in WGS84 longitude/latitude
10774 : *
10775 : * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10776 : *
10777 : * TestCapability(GDsCFastGetExtentWGS84LongLat) can be used to test if the execution
10778 : * time of this method is fast.
10779 : *
10780 : * This is the same as C++ method GDALDataset::GetExtentWGS84LongLat()
10781 : *
10782 : * @param hDS Dataset handle. Must NOT be null.
10783 : * @param[out] psExtent Pointer to output extent. Must NOT be null.
10784 : * @return extent (valid only if IsInit() method returns true)
10785 : * @since GDAL 3.12
10786 : */
10787 :
10788 4 : CPLErr GDALGetExtentWGS84LongLat(GDALDatasetH hDS, OGREnvelope *psExtent)
10789 : {
10790 4 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10791 4 : VALIDATE_POINTER1(psExtent, __func__, CE_Failure);
10792 4 : return GDALDataset::FromHandle(hDS)->GetExtentWGS84LongLat(psExtent);
10793 : }
10794 :
10795 : /************************************************************************/
10796 : /* ReportUpdateNotSupportedByDriver() */
10797 : /************************************************************************/
10798 :
10799 : //! @cond Doxygen_Suppress
10800 :
10801 : /* static */
10802 1 : void GDALDataset::ReportUpdateNotSupportedByDriver(const char *pszDriverName)
10803 : {
10804 1 : CPLError(CE_Failure, CPLE_NotSupported,
10805 : "The %s driver does not support update access to existing "
10806 : "datasets.",
10807 : pszDriverName);
10808 1 : }
10809 :
10810 : //! @endcond
10811 :
10812 : /************************************************************************/
10813 : /* BuildFilename() */
10814 : /************************************************************************/
10815 :
10816 : /** Generates a filename, potentially relative to another one.
10817 : *
10818 : * Given the path to a reference directory, and a path to a file
10819 : * referenced from it, build a path to the file that the current application
10820 : * can use. If the file path is already absolute, rather than relative, or if
10821 : * bRelativeToReferencePath is false, then the filename of interest will be
10822 : * returned unaltered.
10823 : *
10824 : * This is enhanced version of CPLProjectRelativeFilenameSafe() that takes
10825 : * into account the subdataset syntax.
10826 : *
10827 : * Examples:
10828 : * \code{.cpp}
10829 : * BuildFilename("tmp/abc.gif", "abc/def", true) == "abc/def/tmp/abc.gif"
10830 : * BuildFilename("../abc.gif", "/abc/def") == "/abc/abc.gif"
10831 : * BuildFilename("abc.gif", "C:\WIN", true) == "C:\WIN\abc.gif"
10832 : * BuildFilename("abc.gif", "C:\WIN", false) == "abc.gif"
10833 : * BuildFilename("/home/even/foo.tif", "/home/even/workdir", true) == "/home/even/foo.tif"
10834 : * \endcode
10835 : *
10836 : * @param pszFilename Filename of interest.
10837 : * @param pszReferencePath Path to a reference directory.
10838 : * @param bRelativeToReferencePath Whether pszFilename, if a relative path, is
10839 : * relative to pszReferencePath
10840 : * @since 3.11
10841 : */
10842 :
10843 : /* static */
10844 104238 : std::string GDALDataset::BuildFilename(const char *pszFilename,
10845 : const char *pszReferencePath,
10846 : bool bRelativeToReferencePath)
10847 : {
10848 104238 : std::string osSrcDSName;
10849 104238 : if (pszReferencePath != nullptr && bRelativeToReferencePath)
10850 : {
10851 : // Try subdatasetinfo API first
10852 : // Note: this will become the only branch when subdatasetinfo will become
10853 : // available for NITF_IM, RASTERLITE and TILEDB
10854 2584 : const auto oSubDSInfo{GDALGetSubdatasetInfo(pszFilename)};
10855 2584 : if (oSubDSInfo && !oSubDSInfo->GetPathComponent().empty())
10856 : {
10857 8 : auto path{oSubDSInfo->GetPathComponent()};
10858 12 : osSrcDSName = oSubDSInfo->ModifyPathComponent(
10859 8 : CPLProjectRelativeFilenameSafe(pszReferencePath, path.c_str())
10860 4 : .c_str());
10861 4 : GDALDestroySubdatasetInfo(oSubDSInfo);
10862 : }
10863 : else
10864 : {
10865 2580 : bool bDone = false;
10866 15470 : for (const char *pszSyntax : apszSpecialSubDatasetSyntax)
10867 : {
10868 12892 : CPLString osPrefix(pszSyntax);
10869 12892 : osPrefix.resize(strchr(pszSyntax, ':') - pszSyntax + 1);
10870 12892 : if (pszSyntax[osPrefix.size()] == '"')
10871 2578 : osPrefix += '"';
10872 12892 : if (EQUALN(pszFilename, osPrefix, osPrefix.size()))
10873 : {
10874 2 : if (STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}"))
10875 : {
10876 2 : const char *pszLastPart = strrchr(pszFilename, ':') + 1;
10877 : // CSV:z:/foo.xyz
10878 2 : if ((pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
10879 0 : pszLastPart - pszFilename >= 3 &&
10880 0 : pszLastPart[-3] == ':')
10881 : {
10882 0 : pszLastPart -= 2;
10883 : }
10884 2 : CPLString osPrefixFilename = pszFilename;
10885 2 : osPrefixFilename.resize(pszLastPart - pszFilename);
10886 4 : osSrcDSName = osPrefixFilename +
10887 4 : CPLProjectRelativeFilenameSafe(
10888 2 : pszReferencePath, pszLastPart);
10889 2 : bDone = true;
10890 : }
10891 0 : else if (STARTS_WITH_CI(pszSyntax + osPrefix.size(),
10892 : "{FILENAME}"))
10893 : {
10894 0 : CPLString osFilename(pszFilename + osPrefix.size());
10895 0 : size_t nPos = 0;
10896 0 : if (osFilename.size() >= 3 && osFilename[1] == ':' &&
10897 0 : (osFilename[2] == '\\' || osFilename[2] == '/'))
10898 0 : nPos = 2;
10899 0 : nPos = osFilename.find(
10900 0 : pszSyntax[osPrefix.size() + strlen("{FILENAME}")],
10901 : nPos);
10902 0 : if (nPos != std::string::npos)
10903 : {
10904 0 : const CPLString osSuffix = osFilename.substr(nPos);
10905 0 : osFilename.resize(nPos);
10906 0 : osSrcDSName = osPrefix +
10907 0 : CPLProjectRelativeFilenameSafe(
10908 0 : pszReferencePath, osFilename) +
10909 0 : osSuffix;
10910 0 : bDone = true;
10911 : }
10912 : }
10913 2 : break;
10914 : }
10915 : }
10916 2580 : if (!bDone)
10917 : {
10918 2578 : std::string osReferencePath = pszReferencePath;
10919 2578 : if (!CPLIsFilenameRelative(pszReferencePath))
10920 : {
10921 : // Simplify path by replacing "foo/a/../b" with "foo/b"
10922 2287 : while (STARTS_WITH(pszFilename, "../"))
10923 : {
10924 : osReferencePath =
10925 5 : CPLGetPathSafe(osReferencePath.c_str());
10926 5 : pszFilename += strlen("../");
10927 : }
10928 : }
10929 :
10930 5156 : osSrcDSName = CPLProjectRelativeFilenameSafe(
10931 2578 : osReferencePath.c_str(), pszFilename);
10932 : }
10933 2584 : }
10934 : }
10935 : else
10936 : {
10937 101654 : osSrcDSName = pszFilename;
10938 : }
10939 104238 : return osSrcDSName;
10940 : }
|