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  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  ****************************************************************************/
29 
30 #include "cpl_port.h"
31 #include "gdal.h"
32 #include "gdal_priv.h"
33 
34 #include <climits>
35 #include <cstdarg>
36 #include <cstdio>
37 #include <cstdlib>
38 #include <cstring>
39 #include <algorithm>
40 #include <map>
41 #include <new>
42 #include <set>
43 #include <string>
44 #include <utility>
45 
46 #include "cpl_conv.h"
47 #include "cpl_error.h"
48 #include "cpl_hash_set.h"
49 #include "cpl_multiproc.h"
50 #include "cpl_progress.h"
51 #include "cpl_string.h"
52 #include "cpl_vsi.h"
53 #include "cpl_vsi_error.h"
54 #include "ogr_api.h"
55 #include "ogr_attrind.h"
56 #include "ogr_core.h"
57 #include "ogr_feature.h"
58 #include "ogr_featurestyle.h"
59 #include "ogr_gensql.h"
60 #include "ogr_geometry.h"
61 #include "ogr_p.h"
62 #include "ogr_spatialref.h"
63 #include "ogr_srs_api.h"
64 #include "ograpispy.h"
65 #include "ogrsf_frmts.h"
66 #include "ogrunionlayer.h"
67 #include "ogr_swq.h"
68 
69 #include "../frmts/derived/derivedlist.h"
70 
71 #ifdef SQLITE_ENABLED
72 #include "../sqlite/ogrsqliteexecutesql.h"
73 #endif
74 
75 CPL_CVSID("$Id: gdaldataset.cpp a89f31543fbe6c7d738a6405c099ba82fdb3c326 2021-08-22 19:38:03 +0200 Even Rouault $")
76 
77 CPL_C_START
78 GDALAsyncReader *
79 GDALGetDefaultAsyncReader( GDALDataset *poDS,
80                            int nXOff, int nYOff,
81                            int nXSize, int nYSize,
82                            void *pBuf,
83                            int nBufXSize, int nBufYSize,
84                            GDALDataType eBufType,
85                            int nBandCount, int* panBandMap,
86                            int nPixelSpace, int nLineSpace,
87                            int nBandSpace, char **papszOptions );
88 CPL_C_END
89 
90 enum class GDALAllowReadWriteMutexState
91 {
92     RW_MUTEX_STATE_UNKNOWN,
93     RW_MUTEX_STATE_ALLOWED,
94     RW_MUTEX_STATE_DISABLED
95 };
96 
97 const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
98 const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
99 
100 class GDALDataset::Private
101 {
102     CPL_DISALLOW_COPY_ASSIGN(Private)
103 
104   public:
105     CPLMutex *hMutex = nullptr;
106     std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
107 #ifdef DEBUG_EXTRA
108     std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
109 #endif
110     GDALAllowReadWriteMutexState eStateReadWriteMutex = GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
111     int nCurrentLayerIdx = 0;
112     int nLayerCount = -1;
113     GIntBig nFeatureReadInLayer = 0;
114     GIntBig nFeatureReadInDataset = 0;
115     GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
116     GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
117     OGRLayer *poCurrentLayer = nullptr;
118 
119     char               *m_pszWKTCached = nullptr;
120     OGRSpatialReference *m_poSRSCached = nullptr;
121     char               *m_pszWKTGCPCached = nullptr;
122     OGRSpatialReference *m_poSRSGCPCached = nullptr;
123 
124     GDALDataset* poParentDataset = nullptr;
125 
126     bool m_bOverviewsEnabled = true;
127 
128     Private() = default;
129 };
130 
131 struct SharedDatasetCtxt
132 {
133     // PID of the thread that mark the dataset as shared
134     // This may not be the actual PID, but the responsiblePID.
135     GIntBig nPID;
136     char *pszDescription;
137     GDALAccess eAccess;
138 
139     GDALDataset *poDS;
140 };
141 
142 // Set of datasets opened as shared datasets (with GDALOpenShared)
143 // The values in the set are of type SharedDatasetCtxt.
144 static CPLHashSet *phSharedDatasetSet = nullptr;
145 
146 // Set of all datasets created in the constructor of GDALDataset.
147 // In the case of a shared dataset, memorize the PID of the thread
148 // that marked the dataset as shared, so that we can remove it from
149 // the phSharedDatasetSet in the destructor of the dataset, even
150 // if GDALClose is called from a different thread.
151 static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
152 
153 static CPLMutex *hDLMutex = nullptr;
154 
155 // Static array of all datasets. Used by GDALGetOpenDatasets.
156 // Not thread-safe. See GDALGetOpenDatasets.
157 static GDALDataset **ppDatasets = nullptr;
158 
GDALSharedDatasetHashFunc(const void * elt)159 static unsigned long GDALSharedDatasetHashFunc( const void *elt )
160 {
161     const SharedDatasetCtxt *psStruct =
162         static_cast<const SharedDatasetCtxt *>(elt);
163     return static_cast<unsigned long>(
164         CPLHashSetHashStr(psStruct->pszDescription) ^ psStruct->eAccess ^
165         psStruct->nPID);
166 }
167 
GDALSharedDatasetEqualFunc(const void * elt1,const void * elt2)168 static int GDALSharedDatasetEqualFunc( const void* elt1, const void* elt2 )
169 {
170     const SharedDatasetCtxt *psStruct1 =
171         static_cast<const SharedDatasetCtxt *>(elt1);
172     const SharedDatasetCtxt *psStruct2 =
173         static_cast<const SharedDatasetCtxt *>(elt2);
174     return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
175            psStruct1->nPID == psStruct2->nPID &&
176            psStruct1->eAccess == psStruct2->eAccess;
177 }
178 
GDALSharedDatasetFreeFunc(void * elt)179 static void GDALSharedDatasetFreeFunc( void* elt )
180 {
181     SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
182     CPLFree(psStruct->pszDescription);
183     CPLFree(psStruct);
184 }
185 
186 /************************************************************************/
187 /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
188 /************************************************************************/
189 
190 // The open-shared mutex must be used by the ProxyPool too.
GDALGetphDLMutex()191 CPLMutex **GDALGetphDLMutex() { return &hDLMutex; }
192 
193 // The current thread will act in the behalf of the thread of PID
194 // responsiblePID.
GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)195 void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
196 {
197     GIntBig *pResponsiblePID =
198         static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
199     if(pResponsiblePID == nullptr)
200     {
201         pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
202         CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
203     }
204     *pResponsiblePID = responsiblePID;
205 }
206 
207 // Get the PID of the thread that the current thread will act in the behalf of
208 // By default : the current thread acts in the behalf of itself.
GDALGetResponsiblePIDForCurrentThread()209 GIntBig GDALGetResponsiblePIDForCurrentThread()
210 {
211     GIntBig *pResponsiblePID =
212         static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
213     if( pResponsiblePID == nullptr )
214         return CPLGetPID();
215     return *pResponsiblePID;
216 }
217 
218 /************************************************************************/
219 /* ==================================================================== */
220 /*                             GDALDataset                              */
221 /* ==================================================================== */
222 /************************************************************************/
223 
224 /**
225  * \class GDALDataset "gdal_priv.h"
226  *
227  * A dataset encapsulating one or more raster bands.  Details are
228  * further discussed in the <a href="gdal_datamodel.html#GDALDataset">GDAL
229  * Data Model</a>.
230  *
231  * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
232  * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
233  * dataset.
234  */
235 
236 /************************************************************************/
237 /*                            GDALDataset()                             */
238 /************************************************************************/
239 
240 //! @cond Doxygen_Suppress
GDALDataset()241 GDALDataset::GDALDataset():
242     GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
243 {
244 }
245 
GDALDataset(int bForceCachedIOIn)246 GDALDataset::GDALDataset(int bForceCachedIOIn):
247     bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
248     m_poPrivate(new(std::nothrow) GDALDataset::Private)
249 {
250 }
251 //! @endcond
252 
253 /************************************************************************/
254 /*                            ~GDALDataset()                            */
255 /************************************************************************/
256 
257 /**
258  * \brief Destroy an open GDALDataset.
259  *
260  * This is the accepted method of closing a GDAL dataset and deallocating
261  * all resources associated with it.
262  *
263  * Equivalent of the C callable GDALClose().  Except that GDALClose() first
264  * decrements the reference count, and then closes only if it has dropped to
265  * zero.
266  *
267  * For Windows users, it is not recommended to use the delete operator on the
268  * dataset object because of known issues when allocating and freeing memory
269  * across module boundaries. Calling GDALClose() is then a better option.
270  */
271 
~GDALDataset()272 GDALDataset::~GDALDataset()
273 
274 {
275     // we don't want to report destruction of datasets that
276     // were never really open or meant as internal
277     if( !bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")) )
278     {
279         if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() )
280             CPLDebug("GDAL",
281                      "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
282                      GetDescription(), this, static_cast<int>(CPLGetPID()),
283                      static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
284         else
285             CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
286     }
287 
288     if( bSuppressOnClose )
289         VSIUnlink(GetDescription());
290 
291 /* -------------------------------------------------------------------- */
292 /*      Remove dataset from the "open" dataset list.                    */
293 /* -------------------------------------------------------------------- */
294     if( !bIsInternal )
295     {
296         CPLMutexHolderD(&hDLMutex);
297         if( poAllDatasetMap )
298         {
299             std::map<GDALDataset *, GIntBig>::iterator oIter =
300                 poAllDatasetMap->find(this);
301             CPLAssert(oIter != poAllDatasetMap->end());
302             GIntBig nPIDCreatorForShared = oIter->second;
303             poAllDatasetMap->erase(oIter);
304 
305             if( bShared && phSharedDatasetSet != nullptr )
306             {
307                 SharedDatasetCtxt sStruct;
308                 sStruct.nPID = nPIDCreatorForShared;
309                 sStruct.eAccess = eAccess;
310                 sStruct.pszDescription = const_cast<char *>(GetDescription());
311                 SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
312                     CPLHashSetLookup(phSharedDatasetSet, &sStruct));
313                 if( psStruct && psStruct->poDS == this )
314                 {
315                     CPLHashSetRemove(phSharedDatasetSet, psStruct);
316                 }
317                 else
318                 {
319                     CPLDebug("GDAL", "Should not happen. Cannot find %s, "
320                                      "this=%p in phSharedDatasetSet",
321                              GetDescription(), this);
322                 }
323             }
324 
325             if (poAllDatasetMap->empty())
326             {
327                 delete poAllDatasetMap;
328                 poAllDatasetMap = nullptr;
329                 if (phSharedDatasetSet)
330                 {
331                     CPLHashSetDestroy(phSharedDatasetSet);
332                 }
333                 phSharedDatasetSet = nullptr;
334                 CPLFree(ppDatasets);
335                 ppDatasets = nullptr;
336             }
337         }
338     }
339 
340 /* -------------------------------------------------------------------- */
341 /*      Destroy the raster bands if they exist.                         */
342 /* -------------------------------------------------------------------- */
343     for( int i = 0; i < nBands && papoBands != nullptr; ++i )
344     {
345         if( papoBands[i] != nullptr )
346             delete papoBands[i];
347         papoBands[i] = nullptr;
348     }
349 
350     CPLFree(papoBands);
351 
352     if ( m_poStyleTable )
353     {
354         delete m_poStyleTable;
355         m_poStyleTable = nullptr;
356     }
357 
358     if( m_poPrivate != nullptr )
359     {
360         if( m_poPrivate->hMutex != nullptr )
361             CPLDestroyMutex(m_poPrivate->hMutex);
362 
363         CPLFree(m_poPrivate->m_pszWKTCached);
364         if( m_poPrivate->m_poSRSCached )
365         {
366             m_poPrivate->m_poSRSCached->Release();
367         }
368         CPLFree(m_poPrivate->m_pszWKTGCPCached);
369         if( m_poPrivate->m_poSRSGCPCached )
370         {
371             m_poPrivate->m_poSRSGCPCached->Release();
372         }
373     }
374 
375     delete m_poPrivate;
376 
377     CSLDestroy(papszOpenOptions);
378 }
379 
380 /************************************************************************/
381 /*                      AddToDatasetOpenList()                          */
382 /************************************************************************/
383 
AddToDatasetOpenList()384 void GDALDataset::AddToDatasetOpenList()
385 {
386 /* -------------------------------------------------------------------- */
387 /*      Add this dataset to the open dataset list.                      */
388 /* -------------------------------------------------------------------- */
389     bIsInternal = false;
390 
391     CPLMutexHolderD(&hDLMutex);
392 
393     if (poAllDatasetMap == nullptr)
394         poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
395     (*poAllDatasetMap)[this] = -1;
396 }
397 
398 /************************************************************************/
399 /*                             FlushCache()                             */
400 /************************************************************************/
401 
402 /**
403  * \brief Flush all write cached data to disk.
404  *
405  * Any raster (or other GDAL) data written via GDAL calls, but buffered
406  * internally will be written to disk.
407  *
408  * The default implementation of this method just calls the FlushCache() method
409  * on each of the raster bands and the SyncToDisk() method
410  * on each of the layers.  Conceptionally, calling FlushCache() on a dataset
411  * should include any work that might be accomplished by calling SyncToDisk()
412  * on layers in that dataset.
413  *
414  * Using this method does not prevent use from calling GDALClose()
415  * to properly close a dataset and ensure that important data not addressed
416  * by FlushCache() is written in the file.
417  *
418  * This method is the same as the C function GDALFlushCache().
419  */
420 
FlushCache()421 void GDALDataset::FlushCache()
422 
423 {
424     // This sometimes happens if a dataset is destroyed before completely
425     // built.
426 
427     if( papoBands != nullptr )
428     {
429         for( int i = 0; i < nBands; ++i )
430         {
431             if( papoBands[i] != nullptr )
432                 papoBands[i]->FlushCache();
433         }
434     }
435 
436     const int nLayers = GetLayerCount();
437     // cppcheck-suppress knownConditionTrueFalse
438     if( nLayers > 0 )
439     {
440         CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
441         for( int i = 0; i < nLayers; ++i )
442         {
443             OGRLayer *poLayer = GetLayer(i);
444 
445             if( poLayer )
446             {
447                 poLayer->SyncToDisk();
448             }
449         }
450     }
451 }
452 
453 /************************************************************************/
454 /*                           GDALFlushCache()                           */
455 /************************************************************************/
456 
457 /**
458  * \brief Flush all write cached data to disk.
459  *
460  * @see GDALDataset::FlushCache().
461  */
462 
GDALFlushCache(GDALDatasetH hDS)463 void CPL_STDCALL GDALFlushCache( GDALDatasetH hDS )
464 
465 {
466     VALIDATE_POINTER0(hDS, "GDALFlushCache");
467 
468     GDALDataset::FromHandle(hDS)->FlushCache();
469 }
470 
471 /************************************************************************/
472 /*                        BlockBasedFlushCache()                        */
473 /*                                                                      */
474 /*      This helper method can be called by the                         */
475 /*      GDALDataset::FlushCache() for particular drivers to ensure      */
476 /*      that buffers will be flushed in a manner suitable for pixel     */
477 /*      interleaved (by block) IO.  That is, if all the bands have      */
478 /*      the same size blocks then a given block will be flushed for     */
479 /*      all bands before proceeding to the next block.                  */
480 /************************************************************************/
481 
482 //! @cond Doxygen_Suppress
BlockBasedFlushCache()483 void GDALDataset::BlockBasedFlushCache()
484 
485 {
486     GDALRasterBand *poBand1 = GetRasterBand(1);
487     if( poBand1 == nullptr )
488     {
489         GDALDataset::FlushCache();
490         return;
491     }
492 
493     int nBlockXSize = 0;
494     int nBlockYSize = 0;
495     poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
496 
497 /* -------------------------------------------------------------------- */
498 /*      Verify that all bands match.                                    */
499 /* -------------------------------------------------------------------- */
500     for( int iBand = 1; iBand < nBands; ++iBand )
501     {
502         GDALRasterBand *poBand = GetRasterBand(iBand + 1);
503 
504         int nThisBlockXSize, nThisBlockYSize;
505         poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
506         if( nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize )
507         {
508             GDALDataset::FlushCache();
509             return;
510         }
511     }
512 
513 /* -------------------------------------------------------------------- */
514 /*      Now flush writable data.                                        */
515 /* -------------------------------------------------------------------- */
516     for( int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY )
517     {
518         for( int iX = 0; iX < poBand1->nBlocksPerRow; ++iX )
519         {
520             for( int iBand = 0; iBand < nBands; ++iBand )
521             {
522                 GDALRasterBand *poBand = GetRasterBand(iBand + 1);
523 
524                 const CPLErr eErr = poBand->FlushBlock(iX, iY);
525 
526                 if( eErr != CE_None )
527                     return;
528             }
529         }
530     }
531 }
532 
533 /************************************************************************/
534 /*                          RasterInitialize()                          */
535 /*                                                                      */
536 /*      Initialize raster size                                          */
537 /************************************************************************/
538 
RasterInitialize(int nXSize,int nYSize)539 void GDALDataset::RasterInitialize( int nXSize, int nYSize )
540 
541 {
542     CPLAssert(nXSize > 0 && nYSize > 0);
543 
544     nRasterXSize = nXSize;
545     nRasterYSize = nYSize;
546 }
547 //! @endcond
548 
549 /************************************************************************/
550 /*                              AddBand()                               */
551 /************************************************************************/
552 
553 /**
554  * \fn GDALDataset::AddBand(GDALDataType, char**)
555  * \brief Add a band to a dataset.
556  *
557  * This method will add a new band to the dataset if the underlying format
558  * supports this action.  Most formats do not.
559  *
560  * Note that the new GDALRasterBand is not returned.  It may be fetched
561  * after successful completion of the method by calling
562  * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
563  * band will always be the last band.
564  *
565  * @param eType the data type of the pixels in the new band.
566  *
567  * @param papszOptions a list of NAME=VALUE option strings.  The supported
568  * options are format specific.  NULL may be passed by default.
569  *
570  * @return CE_None on success or CE_Failure on failure.
571  */
572 
AddBand(CPL_UNUSED GDALDataType eType,CPL_UNUSED char ** papszOptions)573 CPLErr GDALDataset::AddBand( CPL_UNUSED GDALDataType eType,
574                              CPL_UNUSED char **papszOptions )
575 
576 {
577     ReportError(CE_Failure, CPLE_NotSupported,
578                 "Dataset does not support the AddBand() method.");
579 
580     return CE_Failure;
581 }
582 
583 /************************************************************************/
584 /*                            GDALAddBand()                             */
585 /************************************************************************/
586 
587 /**
588  * \brief Add a band to a dataset.
589  *
590  * @see GDALDataset::AddBand().
591  */
592 
GDALAddBand(GDALDatasetH hDataset,GDALDataType eType,CSLConstList papszOptions)593 CPLErr CPL_STDCALL GDALAddBand( GDALDatasetH hDataset,
594                                 GDALDataType eType, CSLConstList papszOptions )
595 
596 {
597     VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
598 
599     return GDALDataset::FromHandle(hDataset)->AddBand(eType,
600                                             const_cast<char**>(papszOptions));
601 }
602 
603 /************************************************************************/
604 /*                              SetBand()                               */
605 /************************************************************************/
606 
607 //! @cond Doxygen_Suppress
608 /**  Set a band in the band array, updating the band count, and array size
609  * appropriately.
610  *
611  * @param nNewBand new band number (indexing starts at 1)
612  * @param poBand band object.
613  */
614 
SetBand(int nNewBand,GDALRasterBand * poBand)615 void GDALDataset::SetBand( int nNewBand, GDALRasterBand * poBand )
616 
617 {
618 /* -------------------------------------------------------------------- */
619 /*      Do we need to grow the bands list?                              */
620 /* -------------------------------------------------------------------- */
621     if( nBands < nNewBand || papoBands == nullptr )
622     {
623         GDALRasterBand **papoNewBands = nullptr;
624 
625         if( papoBands == nullptr )
626             papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
627                 sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
628         else
629             papoNewBands = static_cast<GDALRasterBand **>(
630                 VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
631                                           std::max(nNewBand, nBands)));
632         if (papoNewBands == nullptr)
633         {
634             ReportError(CE_Failure, CPLE_OutOfMemory,
635                         "Cannot allocate band array");
636             return;
637         }
638 
639         papoBands = papoNewBands;
640 
641         for( int i = nBands; i < nNewBand; ++i )
642             papoBands[i] = nullptr;
643 
644         nBands = std::max(nBands, nNewBand);
645     }
646 
647 /* -------------------------------------------------------------------- */
648 /*      Set the band.  Resetting the band is currently not permitted.   */
649 /* -------------------------------------------------------------------- */
650     if( papoBands[nNewBand - 1] != nullptr )
651     {
652         ReportError(CE_Failure, CPLE_NotSupported,
653                     "Cannot set band %d as it is already set", nNewBand);
654         return;
655     }
656 
657     papoBands[nNewBand - 1] = poBand;
658 
659 /* -------------------------------------------------------------------- */
660 /*      Set back reference information on the raster band.  Note        */
661 /*      that the GDALDataset is a friend of the GDALRasterBand          */
662 /*      specifically to allow this.                                     */
663 /* -------------------------------------------------------------------- */
664     poBand->nBand = nNewBand;
665     poBand->poDS = this;
666     poBand->nRasterXSize = nRasterXSize;
667     poBand->nRasterYSize = nRasterYSize;
668     poBand->eAccess = eAccess;  // Default access to be same as dataset.
669 }
670 //! @endcond
671 
672 /************************************************************************/
673 /*                           GetRasterXSize()                           */
674 /************************************************************************/
675 
676 /**
677 
678  \brief Fetch raster width in pixels.
679 
680  Equivalent of the C function GDALGetRasterXSize().
681 
682  @return the width in pixels of raster bands in this GDALDataset.
683 
684 */
685 
GetRasterXSize()686 int GDALDataset::GetRasterXSize() { return nRasterXSize; }
687 
688 /************************************************************************/
689 /*                         GDALGetRasterXSize()                         */
690 /************************************************************************/
691 
692 /**
693  * \brief Fetch raster width in pixels.
694  *
695  * @see GDALDataset::GetRasterXSize().
696  */
697 
GDALGetRasterXSize(GDALDatasetH hDataset)698 int CPL_STDCALL GDALGetRasterXSize( GDALDatasetH hDataset )
699 
700 {
701     VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
702 
703     return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
704 }
705 
706 /************************************************************************/
707 /*                           GetRasterYSize()                           */
708 /************************************************************************/
709 
710 /**
711 
712  \brief Fetch raster height in pixels.
713 
714  Equivalent of the C function GDALGetRasterYSize().
715 
716  @return the height in pixels of raster bands in this GDALDataset.
717 
718 */
719 
GetRasterYSize()720 int GDALDataset::GetRasterYSize() { return nRasterYSize; }
721 
722 /************************************************************************/
723 /*                         GDALGetRasterYSize()                         */
724 /************************************************************************/
725 
726 /**
727  * \brief Fetch raster height in pixels.
728  *
729  * @see GDALDataset::GetRasterYSize().
730  */
731 
GDALGetRasterYSize(GDALDatasetH hDataset)732 int CPL_STDCALL GDALGetRasterYSize( GDALDatasetH hDataset )
733 
734 {
735     VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
736 
737     return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
738 }
739 
740 /************************************************************************/
741 /*                           GetRasterBand()                            */
742 /************************************************************************/
743 
744 /**
745 
746  \brief Fetch a band object for a dataset.
747 
748  See GetBands() for a C++ iterator version of this method.
749 
750  Equivalent of the C function GDALGetRasterBand().
751 
752  @param nBandId the index number of the band to fetch, from 1 to
753                 GetRasterCount().
754 
755  @return the nBandId th band object
756 
757 */
758 
GetRasterBand(int nBandId)759 GDALRasterBand * GDALDataset::GetRasterBand( int nBandId )
760 
761 {
762     if ( papoBands )
763     {
764         if( nBandId < 1 || nBandId > nBands )
765         {
766             ReportError(CE_Failure, CPLE_IllegalArg,
767                         "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
768                         nBandId);
769             return nullptr;
770         }
771 
772         return papoBands[nBandId - 1];
773     }
774     return nullptr;
775 }
776 
777 /************************************************************************/
778 /*                         GDALGetRasterBand()                          */
779 /************************************************************************/
780 
781 /**
782  * \brief Fetch a band object for a dataset.
783  * @see GDALDataset::GetRasterBand().
784  */
785 
GDALGetRasterBand(GDALDatasetH hDS,int nBandId)786 GDALRasterBandH CPL_STDCALL GDALGetRasterBand( GDALDatasetH hDS, int nBandId )
787 
788 {
789     VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
790 
791     return GDALRasterBand::ToHandle(
792         GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
793 }
794 
795 /************************************************************************/
796 /*                           GetRasterCount()                           */
797 /************************************************************************/
798 
799 /**
800  * \brief Fetch the number of raster bands on this dataset.
801  *
802  * Same as the C function GDALGetRasterCount().
803  *
804  * @return the number of raster bands.
805  */
806 
GetRasterCount()807 int GDALDataset::GetRasterCount() { return papoBands ? nBands : 0; }
808 
809 /************************************************************************/
810 /*                         GDALGetRasterCount()                         */
811 /************************************************************************/
812 
813 /**
814  * \brief Fetch the number of raster bands on this dataset.
815  *
816  * @see GDALDataset::GetRasterCount().
817  */
818 
GDALGetRasterCount(GDALDatasetH hDS)819 int CPL_STDCALL GDALGetRasterCount( GDALDatasetH hDS )
820 
821 {
822     VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
823 
824     return GDALDataset::FromHandle(hDS)->GetRasterCount();
825 }
826 
827 /************************************************************************/
828 /*                          GetProjectionRef()                          */
829 /************************************************************************/
830 
831 /**
832  * \brief Fetch the projection definition string for this dataset.
833  *
834  * Same as the C function GDALGetProjectionRef().
835  *
836  * The returned string defines the projection coordinate system of the
837  * image in OpenGIS WKT format.  It should be suitable for use with the
838  * OGRSpatialReference class.
839  *
840  * When a projection definition is not available an empty (but not NULL)
841  * string is returned.
842  *
843  * \note Startig with GDAL 3.0, this is a compatibility layer around
844  * GetSpatialRef()
845  *
846  * @return a pointer to an internal projection reference string.  It should
847  * not be altered, freed or expected to last for long.
848  *
849  * @see https://gdal.org/tutorials/osr_api_tut.html
850  */
851 
GetProjectionRef() const852 const char *GDALDataset::GetProjectionRef() const
853 {
854     return GetProjectionRefFromSpatialRef(GetSpatialRef());
855 
856 }
857 
858 //! @cond Doxygen_Suppress
GetProjectionRefFromSpatialRef(const OGRSpatialReference * poSRS) const859 const char *GDALDataset::GetProjectionRefFromSpatialRef(const OGRSpatialReference* poSRS) const
860 {
861     if( !poSRS || !m_poPrivate )
862     {
863         return "";
864     }
865     char* pszWKT = nullptr;
866     poSRS->exportToWkt(&pszWKT);
867     if( !pszWKT )
868     {
869         return "";
870     }
871     if( m_poPrivate->m_pszWKTCached &&
872         strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0 )
873     {
874         CPLFree(pszWKT);
875         return m_poPrivate->m_pszWKTCached;
876     }
877     CPLFree(m_poPrivate->m_pszWKTCached);
878     m_poPrivate->m_pszWKTCached = pszWKT;
879     return m_poPrivate->m_pszWKTCached;
880 }
881 //! @endcond
882 
883 /************************************************************************/
884 /*                         _GetProjectionRef()                          */
885 /************************************************************************/
886 
887 //! @cond Doxygen_Suppress
888 /** Pre GDAL-2.5 way */
_GetProjectionRef()889 const char *GDALDataset::_GetProjectionRef() { return (""); }
890 //! @endcond
891 
892 /************************************************************************/
893 /*                           GetSpatialRef()                            */
894 /************************************************************************/
895 
896 /**
897  * \brief Fetch the spatial reference for this dataset.
898  *
899  * Same as the C function GDALGetSpatialRef().
900  *
901  * When a projection definition is not available, null is returned. If used on
902  * a dataset where there are GCPs and not a geotransform, this method returns
903  * null. Use GetGCPSpatialRef() instead.
904  *
905  * @since GDAL 3.0
906  *
907  * @return a pointer to an internal object. It should not be altered or freed.
908  * Its lifetime will be the one of the dataset object, or until the next
909  * call to this method.
910  *
911  * @see https://gdal.org/tutorials/osr_api_tut.html
912  */
913 
GetSpatialRef() const914 const OGRSpatialReference* GDALDataset::GetSpatialRef() const
915 {
916     return nullptr;
917 }
918 
919 /************************************************************************/
920 /*                        GDALGetSpatialRef()                           */
921 /************************************************************************/
922 
923 /**
924  * \brief Fetch the spatial reference for this dataset.
925  *
926  * @since GDAL 3.0
927  *
928  * @see GDALDataset::GetSpatialRef()
929  */
930 
GDALGetSpatialRef(GDALDatasetH hDS)931 OGRSpatialReferenceH GDALGetSpatialRef( GDALDatasetH hDS )
932 
933 {
934     VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
935 
936     return OGRSpatialReference::ToHandle(
937             const_cast<OGRSpatialReference*>(
938                 GDALDataset::FromHandle(hDS)->GetSpatialRef()));
939 }
940 
941 /************************************************************************/
942 /*                 GetSpatialRefFromOldGetProjectionRef()               */
943 /************************************************************************/
944 
945 //! @cond Doxygen_Suppress
GetSpatialRefFromOldGetProjectionRef() const946 const OGRSpatialReference* GDALDataset::GetSpatialRefFromOldGetProjectionRef() const
947 {
948     const char* pszWKT = const_cast<GDALDataset*>(this)->_GetProjectionRef();
949     if( !pszWKT || pszWKT[0] == '\0' || !m_poPrivate )
950     {
951         return nullptr;
952     }
953     if( !m_poPrivate->m_poSRSCached )
954     {
955         m_poPrivate->m_poSRSCached = new OGRSpatialReference();
956         m_poPrivate->m_poSRSCached->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
957     }
958     if( m_poPrivate->m_poSRSCached->importFromWkt(pszWKT) != OGRERR_NONE )
959     {
960         return nullptr;
961     }
962     return m_poPrivate->m_poSRSCached;
963 }
964 //! @endcond
965 
966 /************************************************************************/
967 /*                        GDALGetProjectionRef()                        */
968 /************************************************************************/
969 
970 /**
971  * \brief Fetch the projection definition string for this dataset.
972  *
973  * @see GDALDataset::GetProjectionRef()
974  */
975 
GDALGetProjectionRef(GDALDatasetH hDS)976 const char * CPL_STDCALL GDALGetProjectionRef( GDALDatasetH hDS )
977 
978 {
979     VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
980 
981     return GDALDataset::FromHandle(hDS)->GetProjectionRef();
982 }
983 
984 /************************************************************************/
985 /*                           SetProjection()                            */
986 /************************************************************************/
987 
988 /**
989  * \brief Set the projection reference string for this dataset.
990  *
991  * The string should be in OGC WKT or PROJ.4 format.  An error may occur
992  * because of incorrectly specified projection strings, because the dataset
993  * is not writable, or because the dataset does not support the indicated
994  * projection.  Many formats do not support writing projections.
995  *
996  * This method is the same as the C GDALSetProjection() function.
997  *
998  * \note Startig with GDAL 3.0, this is a compatibility layer around
999  * SetSpatialRef()
1000 
1001  * @param pszProjection projection reference string.
1002  *
1003  * @return CE_Failure if an error occurs, otherwise CE_None.
1004  */
1005 
SetProjection(const char * pszProjection)1006 CPLErr GDALDataset::SetProjection( const char *pszProjection )
1007 {
1008     if( pszProjection && pszProjection[0] != '\0' )
1009     {
1010         OGRSpatialReference oSRS;
1011         oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1012         if( oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE )
1013         {
1014             return CE_Failure;
1015         }
1016         return SetSpatialRef(&oSRS);
1017     }
1018     else
1019     {
1020         return SetSpatialRef(nullptr);
1021     }
1022 }
1023 
1024 /************************************************************************/
1025 /*                           SetSpatialRef()                            */
1026 /************************************************************************/
1027 
1028 /**
1029  * \brief Set the spatial reference system for this dataset.
1030  *
1031  * An error may occur because the dataset
1032  * is not writable, or because the dataset does not support the indicated
1033  * projection. Many formats do not support writing projections.
1034  *
1035  * This method is the same as the C GDALSetSpatialRef() function.
1036  *
1037  * @since GDAL 3.0
1038 
1039  * @param poSRS spatial reference system object. nullptr can potentially be
1040  * passed for drivers that support unsetting the SRS.
1041  *
1042  * @return CE_Failure if an error occurs, otherwise CE_None.
1043  */
1044 
SetSpatialRef(CPL_UNUSED const OGRSpatialReference * poSRS)1045 CPLErr GDALDataset::SetSpatialRef( CPL_UNUSED const OGRSpatialReference* poSRS )
1046 {
1047     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1048         ReportError(CE_Failure, CPLE_NotSupported,
1049                     "Dataset does not support the SetSpatialRef() method.");
1050     return CE_Failure;
1051 }
1052 
1053 /************************************************************************/
1054 /*                         GDALSetSpatialRef()                          */
1055 /************************************************************************/
1056 
1057 /**
1058  * \brief Set the spatial reference system for this dataset.
1059  *
1060  * @since GDAL 3.0
1061  *
1062  * @see GDALDataset::SetSpatialRef()
1063  */
1064 
GDALSetSpatialRef(GDALDatasetH hDS,OGRSpatialReferenceH hSRS)1065 CPLErr GDALSetSpatialRef( GDALDatasetH hDS, OGRSpatialReferenceH hSRS )
1066 
1067 {
1068     VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1069 
1070     return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1071         OGRSpatialReference::FromHandle(hSRS));
1072 }
1073 
1074 /************************************************************************/
1075 /*                          _SetProjection()                            */
1076 /************************************************************************/
1077 
1078 //! @cond Doxygen_Suppress
1079 /** Pre GDAL-2.5 way */
_SetProjection(const char *)1080 CPLErr GDALDataset::_SetProjection( const char * )
1081 {
1082     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1083         ReportError(CE_Failure, CPLE_NotSupported,
1084                     "Dataset does not support the SetProjection() method.");
1085     return CE_Failure;
1086 }
1087 //! @endcond
1088 
1089 /************************************************************************/
1090 /*                   OldSetProjectionFromSetSpatialRef()                */
1091 /************************************************************************/
1092 
1093 //! @cond Doxygen_Suppress
OldSetProjectionFromSetSpatialRef(const OGRSpatialReference * poSRS)1094 CPLErr GDALDataset::OldSetProjectionFromSetSpatialRef(
1095                             const OGRSpatialReference* poSRS)
1096 {
1097     if( !poSRS || poSRS->IsEmpty() )
1098     {
1099         return _SetProjection("");
1100     }
1101     char* pszWKT = nullptr;
1102     if( poSRS->exportToWkt(&pszWKT) != OGRERR_NONE )
1103     {
1104         CPLFree(pszWKT);
1105         return CE_Failure;
1106     }
1107     auto ret = _SetProjection(pszWKT);
1108     CPLFree(pszWKT);
1109     return ret;
1110 }
1111 //! @endcond
1112 
1113 /************************************************************************/
1114 /*                         GDALSetProjection()                          */
1115 /************************************************************************/
1116 
1117 /**
1118  * \brief Set the projection reference string for this dataset.
1119  *
1120  * @see GDALDataset::SetProjection()
1121  */
1122 
GDALSetProjection(GDALDatasetH hDS,const char * pszProjection)1123 CPLErr CPL_STDCALL GDALSetProjection( GDALDatasetH hDS,
1124                                       const char * pszProjection )
1125 
1126 {
1127     VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1128 
1129     return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
1130 }
1131 
1132 /************************************************************************/
1133 /*                          GetGeoTransform()                           */
1134 /************************************************************************/
1135 
1136 /**
1137  * \brief Fetch the affine transformation coefficients.
1138  *
1139  * Fetches the coefficients for transforming between pixel/line (P,L) raster
1140  * space, and projection coordinates (Xp,Yp) space.
1141  *
1142  * \code
1143  *   Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
1144  *   Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
1145  * \endcode
1146  *
1147  * In a north up image, padfTransform[1] is the pixel width, and
1148  * padfTransform[5] is the pixel height.  The upper left corner of the
1149  * upper left pixel is at position (padfTransform[0],padfTransform[3]).
1150  *
1151  * The default transform is (0,1,0,0,0,1) and should be returned even when
1152  * a CE_Failure error is returned, such as for formats that don't support
1153  * transformation to projection coordinates.
1154  *
1155  * This method does the same thing as the C GDALGetGeoTransform() function.
1156  *
1157  * @param padfTransform an existing six double buffer into which the
1158  * transformation will be placed.
1159  *
1160  * @return CE_None on success, or CE_Failure if no transform can be fetched.
1161  */
1162 
GetGeoTransform(double * padfTransform)1163 CPLErr GDALDataset::GetGeoTransform( double * padfTransform )
1164 
1165 {
1166     CPLAssert(padfTransform != nullptr);
1167 
1168     padfTransform[0] = 0.0;  // X Origin (top left corner)
1169     padfTransform[1] = 1.0;  // X Pixel size */
1170     padfTransform[2] = 0.0;
1171 
1172     padfTransform[3] = 0.0;  // Y Origin (top left corner)
1173     padfTransform[4] = 0.0;
1174     padfTransform[5] = 1.0;  // Y Pixel Size
1175 
1176     return CE_Failure;
1177 }
1178 
1179 /************************************************************************/
1180 /*                        GDALGetGeoTransform()                         */
1181 /************************************************************************/
1182 
1183 /**
1184  * \brief Fetch the affine transformation coefficients.
1185  *
1186  * @see GDALDataset::GetGeoTransform()
1187  */
1188 
GDALGetGeoTransform(GDALDatasetH hDS,double * padfTransform)1189 CPLErr CPL_STDCALL GDALGetGeoTransform( GDALDatasetH hDS,
1190                                         double * padfTransform )
1191 
1192 {
1193     VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1194 
1195     return GDALDataset::FromHandle(hDS)->GetGeoTransform(padfTransform);
1196 }
1197 
1198 /************************************************************************/
1199 /*                          SetGeoTransform()                           */
1200 /************************************************************************/
1201 
1202 /**
1203  * \fn GDALDataset::SetGeoTransform(double*)
1204  * \brief Set the affine transformation coefficients.
1205  *
1206  * See GetGeoTransform() for details on the meaning of the padfTransform
1207  * coefficients.
1208  *
1209  * This method does the same thing as the C GDALSetGeoTransform() function.
1210  *
1211  * @param padfTransform a six double buffer containing the transformation
1212  * coefficients to be written with the dataset.
1213  *
1214  * @return CE_None on success, or CE_Failure if this transform cannot be
1215  * written.
1216  */
1217 
SetGeoTransform(CPL_UNUSED double * padfTransform)1218 CPLErr GDALDataset::SetGeoTransform( CPL_UNUSED double *padfTransform )
1219 
1220 {
1221     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1222         ReportError(CE_Failure, CPLE_NotSupported,
1223                     "SetGeoTransform() not supported for this dataset.");
1224 
1225     return CE_Failure;
1226 }
1227 
1228 /************************************************************************/
1229 /*                        GDALSetGeoTransform()                         */
1230 /************************************************************************/
1231 
1232 /**
1233  * \brief Set the affine transformation coefficients.
1234  *
1235  * @see GDALDataset::SetGeoTransform()
1236  */
1237 
1238 CPLErr CPL_STDCALL
GDALSetGeoTransform(GDALDatasetH hDS,double * padfTransform)1239 GDALSetGeoTransform( GDALDatasetH hDS, double *padfTransform )
1240 
1241 {
1242     VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1243 
1244     return GDALDataset::FromHandle(hDS)->SetGeoTransform(padfTransform);
1245 }
1246 
1247 /************************************************************************/
1248 /*                         GetInternalHandle()                          */
1249 /************************************************************************/
1250 
1251 /**
1252  * \fn GDALDataset::GetInternalHandle(const char*)
1253  * \brief Fetch a format specific internally meaningful handle.
1254  *
1255  * This method is the same as the C GDALGetInternalHandle() method.
1256  *
1257  * @param pszHandleName the handle name desired.  The meaningful names
1258  * will be specific to the file format.
1259  *
1260  * @return the desired handle value, or NULL if not recognized/supported.
1261  */
1262 
GetInternalHandle(CPL_UNUSED const char * pszHandleName)1263 void *GDALDataset::GetInternalHandle( CPL_UNUSED const char *pszHandleName )
1264 
1265 {
1266     return nullptr;
1267 }
1268 
1269 /************************************************************************/
1270 /*                       GDALGetInternalHandle()                        */
1271 /************************************************************************/
1272 
1273 /**
1274  * \brief Fetch a format specific internally meaningful handle.
1275  *
1276  * @see GDALDataset::GetInternalHandle()
1277  */
1278 
1279 void * CPL_STDCALL
GDALGetInternalHandle(GDALDatasetH hDS,const char * pszRequest)1280 GDALGetInternalHandle( GDALDatasetH hDS, const char * pszRequest )
1281 
1282 {
1283     VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
1284 
1285     return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
1286 }
1287 
1288 /************************************************************************/
1289 /*                             GetDriver()                              */
1290 /************************************************************************/
1291 
1292 /**
1293  * \brief Fetch the driver to which this dataset relates.
1294  *
1295  * This method is the same as the C GDALGetDatasetDriver() function.
1296  *
1297  * @return the driver on which the dataset was created with GDALOpen() or
1298  * GDALCreate().
1299  */
1300 
GetDriver()1301 GDALDriver *GDALDataset::GetDriver() { return poDriver; }
1302 
1303 /************************************************************************/
1304 /*                        GDALGetDatasetDriver()                        */
1305 /************************************************************************/
1306 
1307 /**
1308  * \brief Fetch the driver to which this dataset relates.
1309  *
1310  * @see GDALDataset::GetDriver()
1311  */
1312 
GDALGetDatasetDriver(GDALDatasetH hDataset)1313 GDALDriverH CPL_STDCALL GDALGetDatasetDriver( GDALDatasetH hDataset )
1314 
1315 {
1316     VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1317 
1318     return static_cast<GDALDriverH>(
1319         GDALDataset::FromHandle(hDataset)->GetDriver());
1320 }
1321 
1322 /************************************************************************/
1323 /*                             Reference()                              */
1324 /************************************************************************/
1325 
1326 /**
1327  * \brief Add one to dataset reference count.
1328  *
1329  * The reference is one after instantiation.
1330  *
1331  * This method is the same as the C GDALReferenceDataset() function.
1332  *
1333  * @return the post-increment reference count.
1334  */
1335 
Reference()1336 int GDALDataset::Reference() { return ++nRefCount; }
1337 
1338 /************************************************************************/
1339 /*                        GDALReferenceDataset()                        */
1340 /************************************************************************/
1341 
1342 /**
1343  * \brief Add one to dataset reference count.
1344  *
1345  * @see GDALDataset::Reference()
1346  */
1347 
GDALReferenceDataset(GDALDatasetH hDataset)1348 int CPL_STDCALL GDALReferenceDataset( GDALDatasetH hDataset )
1349 
1350 {
1351     VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1352 
1353     return GDALDataset::FromHandle(hDataset)->Reference();
1354 }
1355 
1356 /************************************************************************/
1357 /*                            Dereference()                             */
1358 /************************************************************************/
1359 
1360 /**
1361  * \brief Subtract one from dataset reference count.
1362  *
1363  * The reference is one after instantiation.  Generally when the reference
1364  * count has dropped to zero the dataset may be safely deleted (closed).
1365  *
1366  * This method is the same as the C GDALDereferenceDataset() function.
1367  *
1368  * @return the post-decrement reference count.
1369  */
1370 
Dereference()1371 int GDALDataset::Dereference() { return --nRefCount; }
1372 
1373 /************************************************************************/
1374 /*                       GDALDereferenceDataset()                       */
1375 /************************************************************************/
1376 
1377 /**
1378  * \brief Subtract one from dataset reference count.
1379  *
1380  * @see GDALDataset::Dereference()
1381  */
1382 
GDALDereferenceDataset(GDALDatasetH hDataset)1383 int CPL_STDCALL GDALDereferenceDataset( GDALDatasetH hDataset )
1384 
1385 {
1386     VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1387 
1388     return GDALDataset::FromHandle(hDataset)->Dereference();
1389 }
1390 
1391 
1392 /************************************************************************/
1393 /*                            ReleaseRef()                              */
1394 /************************************************************************/
1395 
1396 /**
1397  * \brief Drop a reference to this object, and destroy if no longer referenced.
1398  * @return TRUE if the object has been destroyed.
1399  * @since GDAL 2.2
1400  */
1401 
ReleaseRef()1402 int GDALDataset::ReleaseRef()
1403 
1404 {
1405     if( Dereference() <= 0 )
1406     {
1407         nRefCount = 1;
1408         delete this;
1409         return TRUE;
1410     }
1411     return FALSE;
1412 }
1413 
1414 /************************************************************************/
1415 /*                        GDALReleaseDataset()                          */
1416 /************************************************************************/
1417 
1418 /**
1419  * \brief Drop a reference to this object, and destroy if no longer referenced.
1420  *
1421  * @see GDALDataset::ReleaseRef()
1422  * @since GDAL 2.2
1423  */
1424 
GDALReleaseDataset(GDALDatasetH hDataset)1425 int CPL_STDCALL GDALReleaseDataset( GDALDatasetH hDataset )
1426 
1427 {
1428     VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1429 
1430     return GDALDataset::FromHandle(hDataset)->ReleaseRef();
1431 }
1432 
1433 /************************************************************************/
1434 /*                             GetShared()                              */
1435 /************************************************************************/
1436 
1437 /**
1438  * \brief Returns shared flag.
1439  *
1440  * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1441  */
1442 
GetShared() const1443 int GDALDataset::GetShared() const { return bShared; }
1444 
1445 /************************************************************************/
1446 /*                            MarkAsShared()                            */
1447 /************************************************************************/
1448 
1449 /**
1450  * \brief Mark this dataset as available for sharing.
1451  */
1452 
MarkAsShared()1453 void GDALDataset::MarkAsShared()
1454 
1455 {
1456     CPLAssert(!bShared);
1457 
1458     bShared = true;
1459     if( bIsInternal )
1460         return;
1461 
1462     GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1463 
1464     // Insert the dataset in the set of shared opened datasets.
1465     CPLMutexHolderD(&hDLMutex);
1466     if (phSharedDatasetSet == nullptr)
1467         phSharedDatasetSet =
1468             CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1469                           GDALSharedDatasetFreeFunc);
1470 
1471     SharedDatasetCtxt *psStruct =
1472         static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1473     psStruct->poDS = this;
1474     psStruct->nPID = nPID;
1475     psStruct->eAccess = eAccess;
1476     psStruct->pszDescription = CPLStrdup(GetDescription());
1477     if(CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
1478     {
1479         CPLFree(psStruct->pszDescription);
1480         CPLFree(psStruct);
1481         ReportError(CE_Failure, CPLE_AppDefined,
1482                     "An existing shared dataset already has this description. "
1483                     "This should not happen.");
1484     }
1485     else
1486     {
1487         CPLHashSetInsert(phSharedDatasetSet, psStruct);
1488 
1489         (*poAllDatasetMap)[this] = nPID;
1490     }
1491 }
1492 
1493 /************************************************************************/
1494 /*                            GetGCPCount()                             */
1495 /************************************************************************/
1496 
1497 /**
1498  * \brief Get number of GCPs.
1499  *
1500  * This method is the same as the C function GDALGetGCPCount().
1501  *
1502  * @return number of GCPs for this dataset.  Zero if there are none.
1503  */
1504 
GetGCPCount()1505 int GDALDataset::GetGCPCount() { return 0; }
1506 
1507 /************************************************************************/
1508 /*                          GDALGetGCPCount()                           */
1509 /************************************************************************/
1510 
1511 /**
1512  * \brief Get number of GCPs.
1513  *
1514  * @see GDALDataset::GetGCPCount()
1515  */
1516 
GDALGetGCPCount(GDALDatasetH hDS)1517 int CPL_STDCALL GDALGetGCPCount( GDALDatasetH hDS )
1518 
1519 {
1520     VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
1521 
1522     return GDALDataset::FromHandle(hDS)->GetGCPCount();
1523 }
1524 
1525 /************************************************************************/
1526 /*                          GetGCPProjection()                          */
1527 /************************************************************************/
1528 
1529 /**
1530  * \brief Get output projection for GCPs.
1531  *
1532  * This method is the same as the C function GDALGetGCPProjection().
1533  *
1534  * The projection string follows the normal rules from GetProjectionRef().
1535  *
1536  * \note Starting with GDAL 3.0, this is a compatibility layer around
1537  * GetGCPSpatialRef()
1538  *
1539  * @return internal projection string or "" if there are no GCPs.
1540  *  It should not be altered, freed or expected to last for long.
1541  */
1542 
GetGCPProjection()1543 const char *GDALDataset::GetGCPProjection()
1544 {
1545     return GetGCPProjectionFromSpatialRef(GetGCPSpatialRef());
1546 }
1547 
1548 //! @cond Doxygen_Suppress
GetGCPProjectionFromSpatialRef(const OGRSpatialReference * poSRS) const1549 const char *GDALDataset::GetGCPProjectionFromSpatialRef(const OGRSpatialReference* poSRS) const
1550 {
1551     if( !poSRS || !m_poPrivate )
1552     {
1553         return "";
1554     }
1555     char* pszWKT = nullptr;
1556     poSRS->exportToWkt(&pszWKT);
1557     if( !pszWKT )
1558     {
1559         return "";
1560     }
1561     if( m_poPrivate->m_pszWKTGCPCached &&
1562         strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0 )
1563     {
1564         CPLFree(pszWKT);
1565         return m_poPrivate->m_pszWKTGCPCached;
1566     }
1567     CPLFree(m_poPrivate->m_pszWKTGCPCached);
1568     m_poPrivate->m_pszWKTGCPCached = pszWKT;
1569     return m_poPrivate->m_pszWKTGCPCached;
1570 }
1571 //! @endcond
1572 
1573 /************************************************************************/
1574 /*                         _GetGCPProjection()                          */
1575 /************************************************************************/
1576 
1577 //! @cond Doxygen_Suppress
1578 /** Pre GDAL-2.5 way */
_GetGCPProjection()1579 const char *GDALDataset::_GetGCPProjection() { return ""; }
1580 //! @endcond
1581 
1582 /************************************************************************/
1583 /*                          GetGCPSpatialRef()                          */
1584 /************************************************************************/
1585 
1586 /**
1587  * \brief Get output spatial reference system for GCPs.
1588  *
1589  * Same as the C function GDALGetGCPSpatialRef().
1590  *
1591  * When a SRS is not available, null is returned. If used on
1592  * a dataset where there is a geotransform, and not GCPs, this method returns
1593  * null. Use GetSpatialRef() instead.
1594  *
1595  * @since GDAL 3.0
1596  *
1597  * @return a pointer to an internal object. It should not be altered or freed.
1598  * Its lifetime will be the one of the dataset object, or until the next
1599  * call to this method.
1600  */
1601 
GetGCPSpatialRef() const1602 const OGRSpatialReference* GDALDataset::GetGCPSpatialRef() const
1603 {
1604     return nullptr;
1605 }
1606 
1607 /************************************************************************/
1608 /*                       GDALGetGCPSpatialRef()                         */
1609 /************************************************************************/
1610 
1611 /**
1612  * \brief Get output spatial reference system for GCPs.
1613  *
1614  * @since GDAL 3.0
1615  *
1616  * @see GDALDataset::GetGCPSpatialRef()
1617  */
1618 
GDALGetGCPSpatialRef(GDALDatasetH hDS)1619 OGRSpatialReferenceH GDALGetGCPSpatialRef( GDALDatasetH hDS )
1620 
1621 {
1622     VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
1623 
1624     return OGRSpatialReference::ToHandle(
1625             const_cast<OGRSpatialReference*>(
1626                 GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
1627 }
1628 
1629 /************************************************************************/
1630 /*                GetGCPSpatialRefFromOldGetGCPProjection()             */
1631 /************************************************************************/
1632 
1633 //! @cond Doxygen_Suppress
GetGCPSpatialRefFromOldGetGCPProjection() const1634 const OGRSpatialReference* GDALDataset::GetGCPSpatialRefFromOldGetGCPProjection() const
1635 {
1636     const char* pszWKT = const_cast<GDALDataset*>(this)->_GetGCPProjection();
1637     if( !pszWKT || pszWKT[0] == '\0' || !m_poPrivate )
1638     {
1639         return nullptr;
1640     }
1641     if( !m_poPrivate->m_poSRSGCPCached)
1642     {
1643         m_poPrivate->m_poSRSGCPCached = new OGRSpatialReference();
1644         m_poPrivate->m_poSRSGCPCached->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1645     }
1646     if( m_poPrivate->m_poSRSGCPCached->importFromWkt(pszWKT) != OGRERR_NONE )
1647     {
1648         return nullptr;
1649     }
1650     return m_poPrivate->m_poSRSGCPCached;
1651 }
1652 //! @endcond
1653 
1654 /************************************************************************/
1655 /*                        GDALGetGCPProjection()                        */
1656 /************************************************************************/
1657 
1658 /**
1659  * \brief Get output projection for GCPs.
1660  *
1661  * @see GDALDataset::GetGCPProjection()
1662  */
1663 
GDALGetGCPProjection(GDALDatasetH hDS)1664 const char * CPL_STDCALL GDALGetGCPProjection( GDALDatasetH hDS )
1665 
1666 {
1667     VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
1668 
1669     return GDALDataset::FromHandle(hDS)->GetGCPProjection();
1670 }
1671 
1672 /************************************************************************/
1673 /*                               GetGCPs()                              */
1674 /************************************************************************/
1675 
1676 /**
1677  * \brief Fetch GCPs.
1678  *
1679  * This method is the same as the C function GDALGetGCPs().
1680  *
1681  * @return pointer to internal GCP structure list.  It should not be modified,
1682  * and may change on the next GDAL call.
1683  */
1684 
GetGCPs()1685 const GDAL_GCP *GDALDataset::GetGCPs() { return nullptr; }
1686 
1687 /************************************************************************/
1688 /*                            GDALGetGCPs()                             */
1689 /************************************************************************/
1690 
1691 /**
1692  * \brief Fetch GCPs.
1693  *
1694  * @see GDALDataset::GetGCPs()
1695  */
1696 
GDALGetGCPs(GDALDatasetH hDS)1697 const GDAL_GCP * CPL_STDCALL GDALGetGCPs( GDALDatasetH hDS )
1698 
1699 {
1700     VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
1701 
1702     return GDALDataset::FromHandle(hDS)->GetGCPs();
1703 }
1704 
1705 /************************************************************************/
1706 /*                              SetGCPs()                               */
1707 /************************************************************************/
1708 
1709 /**
1710  * \brief Assign GCPs.
1711  *
1712  * This method is the same as the C function GDALSetGCPs().
1713  *
1714  * This method assigns the passed set of GCPs to this dataset, as well as
1715  * setting their coordinate system.  Internally copies are made of the
1716  * coordinate system and list of points, so the caller remains responsible for
1717  * deallocating these arguments if appropriate.
1718  *
1719  * Most formats do not support setting of GCPs, even formats that can
1720  * handle GCPs.  These formats will return CE_Failure.
1721  *
1722  * \note Startig with GDAL 3.0, this is a compatibility layer around
1723  * SetGCPs(int, const GDAL_GCP*, const char*)
1724  *
1725  * @param nGCPCount number of GCPs being assigned.
1726  *
1727  * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
1728  *
1729  * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
1730  * GCP output coordinates.  This parameter should be "" if no output coordinate
1731  * system is known.
1732  *
1733  * @return CE_None on success, CE_Failure on failure (including if action is
1734  * not supported for this format).
1735  */
1736 
SetGCPs(int nGCPCount,const GDAL_GCP * pasGCPList,const char * pszGCPProjection)1737 CPLErr GDALDataset::SetGCPs( int nGCPCount,
1738                              const GDAL_GCP *pasGCPList,
1739                              const char *pszGCPProjection )
1740 
1741 {
1742     if( pszGCPProjection && pszGCPProjection[0] != '\0' )
1743     {
1744         OGRSpatialReference oSRS;
1745         oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1746         if( oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE )
1747         {
1748             return CE_Failure;
1749         }
1750         return SetGCPs(nGCPCount, pasGCPList, &oSRS);
1751     }
1752     else
1753     {
1754         return SetGCPs(nGCPCount, pasGCPList,
1755                        static_cast<const OGRSpatialReference*>(nullptr));
1756     }
1757 }
1758 
1759 /************************************************************************/
1760 /*                              SetGCPs()                               */
1761 /************************************************************************/
1762 
1763 /**
1764  * \brief Assign GCPs.
1765  *
1766  * This method is the same as the C function GDALSetGCPs().
1767  *
1768  * This method assigns the passed set of GCPs to this dataset, as well as
1769  * setting their coordinate system.  Internally copies are made of the
1770  * coordinate system and list of points, so the caller remains responsible for
1771  * deallocating these arguments if appropriate.
1772  *
1773  * Most formats do not support setting of GCPs, even formats that can
1774  * handle GCPs.  These formats will return CE_Failure.
1775  *
1776  * @since GDAL 3.0
1777  *
1778  * @param nGCPCount number of GCPs being assigned.
1779  *
1780  * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
1781  *
1782  * @param poGCP_SRS the new coordinate reference system to assign for the
1783  * GCP output coordinates.  This parameter should be null if no output coordinate
1784  * system is known.
1785  *
1786  * @return CE_None on success, CE_Failure on failure (including if action is
1787  * not supported for this format).
1788  */
1789 
SetGCPs(CPL_UNUSED int nGCPCount,CPL_UNUSED const GDAL_GCP * pasGCPList,CPL_UNUSED const OGRSpatialReference * poGCP_SRS)1790 CPLErr GDALDataset::SetGCPs( CPL_UNUSED int nGCPCount,
1791                              CPL_UNUSED const GDAL_GCP *pasGCPList,
1792                              CPL_UNUSED const OGRSpatialReference * poGCP_SRS )
1793 
1794 {
1795     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1796         ReportError(CE_Failure, CPLE_NotSupported,
1797                     "Dataset does not support the SetGCPs() method.");
1798 
1799     return CE_Failure;
1800 }
1801 
1802 /************************************************************************/
1803 /*                            _SetGCPs()                                */
1804 /************************************************************************/
1805 
1806 //! @cond Doxygen_Suppress
1807 /** Pre GDAL-2.5 way */
_SetGCPs(int,const GDAL_GCP *,const char *)1808 CPLErr GDALDataset::_SetGCPs( int,
1809                               const GDAL_GCP*,
1810                               const char * )
1811 
1812 {
1813     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1814         ReportError(CE_Failure, CPLE_NotSupported,
1815                     "Dataset does not support the SetGCPs() method.");
1816 
1817     return CE_Failure;
1818 }
1819 //! @endcond
1820 
1821 /************************************************************************/
1822 /*                           OldSetGCPsFromNew()                        */
1823 /************************************************************************/
1824 
1825 //! @cond Doxygen_Suppress
OldSetGCPsFromNew(int nGCPCount,const GDAL_GCP * pasGCPList,const OGRSpatialReference * poGCP_SRS)1826 CPLErr GDALDataset::OldSetGCPsFromNew(
1827                               int nGCPCount, const GDAL_GCP *pasGCPList,
1828                               const OGRSpatialReference * poGCP_SRS )
1829 {
1830     if( !poGCP_SRS || poGCP_SRS->IsEmpty() )
1831     {
1832         return _SetGCPs(nGCPCount, pasGCPList, "");
1833     }
1834     char* pszWKT = nullptr;
1835     if( poGCP_SRS->exportToWkt(&pszWKT) != OGRERR_NONE )
1836     {
1837         CPLFree(pszWKT);
1838         return CE_Failure;
1839     }
1840     auto ret = _SetGCPs(nGCPCount, pasGCPList, pszWKT);
1841     CPLFree(pszWKT);
1842     return ret;
1843 }
1844 //! @endcond
1845 
1846 /************************************************************************/
1847 /*                            GDALSetGCPs()                             */
1848 /************************************************************************/
1849 
1850 /**
1851  * \brief Assign GCPs.
1852  *
1853  * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
1854  */
1855 
GDALSetGCPs(GDALDatasetH hDS,int nGCPCount,const GDAL_GCP * pasGCPList,const char * pszGCPProjection)1856 CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount,
1857                                 const GDAL_GCP *pasGCPList,
1858                                 const char *pszGCPProjection )
1859 
1860 {
1861     VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
1862 
1863     return GDALDataset::FromHandle(hDS)
1864         ->SetGCPs(nGCPCount, pasGCPList, pszGCPProjection);
1865 }
1866 
1867 /************************************************************************/
1868 /*                           GDALSetGCPs2()                             */
1869 /************************************************************************/
1870 
1871 /**
1872  * \brief Assign GCPs.
1873  *
1874  * @since GDAL 3.0
1875  * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
1876  */
1877 
GDALSetGCPs2(GDALDatasetH hDS,int nGCPCount,const GDAL_GCP * pasGCPList,OGRSpatialReferenceH hSRS)1878 CPLErr GDALSetGCPs2( GDALDatasetH hDS, int nGCPCount,
1879                      const GDAL_GCP *pasGCPList,
1880                      OGRSpatialReferenceH hSRS )
1881 
1882 {
1883     VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
1884 
1885     return GDALDataset::FromHandle(hDS)
1886         ->SetGCPs(nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
1887 }
1888 
1889 /************************************************************************/
1890 /*                           BuildOverviews()                           */
1891 /************************************************************************/
1892 
1893 /**
1894  * \brief Build raster overview(s)
1895  *
1896  * If the operation is unsupported for the indicated dataset, then
1897  * CE_Failure is returned, and CPLGetLastErrorNo() will return
1898  * CPLE_NotSupported.
1899  *
1900  * Depending on the actual file format, all overviews level can be also
1901  * deleted by specifying nOverviews == 0. This works at least for external
1902  * overviews (.ovr), TIFF internal overviews, etc.
1903  *
1904  * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
1905  * to "ALL_CPUS" or a integer value to specify the number of threads to use for
1906  * overview computation.
1907  *
1908  * This method is the same as the C function GDALBuildOverviews().
1909  *
1910  * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
1911  * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
1912  * or "NONE" controlling the downsampling method applied.
1913  * @param nOverviews number of overviews to build, or 0 to clean overviews.
1914  * @param panOverviewList the list of overview decimation factors to build, or
1915  *                        NULL if nOverviews == 0.
1916  * @param nListBands number of bands to build overviews for in panBandList.
1917  * Build for all bands if this is 0.
1918  * @param panBandList list of band numbers.
1919  * @param pfnProgress a function to call to report progress, or NULL.
1920  * @param pProgressData application data to pass to the progress function.
1921  *
1922  * @return CE_None on success or CE_Failure if the operation doesn't work.
1923  *
1924  * For example, to build overview level 2, 4 and 8 on all bands the following
1925  * call could be made:
1926  * \code{.cpp}
1927  *   int       anOverviewList[3] = { 2, 4, 8 };
1928  *
1929  *   poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
1930  *                              GDALDummyProgress, nullptr );
1931  * \endcode
1932  *
1933  * @see GDALRegenerateOverviews()
1934  */
1935 
BuildOverviews(const char * pszResampling,int nOverviews,int * panOverviewList,int nListBands,int * panBandList,GDALProgressFunc pfnProgress,void * pProgressData)1936 CPLErr GDALDataset::BuildOverviews( const char *pszResampling,
1937                                     int nOverviews, int *panOverviewList,
1938                                     int nListBands, int *panBandList,
1939                                     GDALProgressFunc pfnProgress,
1940                                     void * pProgressData )
1941 
1942 {
1943     int *panAllBandList = nullptr;
1944 
1945     if( nListBands == 0 )
1946     {
1947         nListBands = GetRasterCount();
1948         panAllBandList =
1949             static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
1950         for( int i = 0; i < nListBands; ++i )
1951             panAllBandList[i] = i + 1;
1952 
1953         panBandList = panAllBandList;
1954     }
1955 
1956     if( pfnProgress == nullptr )
1957         pfnProgress = GDALDummyProgress;
1958 
1959     const CPLErr eErr =
1960         IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
1961                         panBandList, pfnProgress, pProgressData);
1962 
1963     if( panAllBandList != nullptr )
1964         CPLFree(panAllBandList);
1965 
1966     return eErr;
1967 }
1968 
1969 /************************************************************************/
1970 /*                         GDALBuildOverviews()                         */
1971 /************************************************************************/
1972 
1973 /**
1974  * \brief Build raster overview(s)
1975  *
1976  * @see GDALDataset::BuildOverviews()
1977  */
1978 
GDALBuildOverviews(GDALDatasetH hDataset,const char * pszResampling,int nOverviews,int * panOverviewList,int nListBands,int * panBandList,GDALProgressFunc pfnProgress,void * pProgressData)1979 CPLErr CPL_STDCALL GDALBuildOverviews( GDALDatasetH hDataset,
1980                                        const char *pszResampling,
1981                                        int nOverviews, int *panOverviewList,
1982                                        int nListBands, int *panBandList,
1983                                        GDALProgressFunc pfnProgress,
1984                                        void * pProgressData )
1985 
1986 {
1987     VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
1988 
1989     return GDALDataset::FromHandle(hDataset)
1990         ->BuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
1991                          panBandList, pfnProgress, pProgressData);
1992 }
1993 
1994 /************************************************************************/
1995 /*                          IBuildOverviews()                           */
1996 /*                                                                      */
1997 /*      Default implementation.                                         */
1998 /************************************************************************/
1999 
2000 //! @cond Doxygen_Suppress
IBuildOverviews(const char * pszResampling,int nOverviews,int * panOverviewList,int nListBands,int * panBandList,GDALProgressFunc pfnProgress,void * pProgressData)2001 CPLErr GDALDataset::IBuildOverviews( const char *pszResampling,
2002                                      int nOverviews, int *panOverviewList,
2003                                      int nListBands, int *panBandList,
2004                                      GDALProgressFunc pfnProgress,
2005                                      void * pProgressData )
2006 
2007 {
2008     if( oOvManager.IsInitialized() )
2009         return oOvManager.BuildOverviews(
2010             nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2011             panBandList, pfnProgress, pProgressData);
2012     else
2013     {
2014         ReportError(CE_Failure, CPLE_NotSupported,
2015                     "BuildOverviews() not supported for this dataset.");
2016 
2017         return CE_Failure;
2018     }
2019 }
2020 //! @endcond
2021 
2022 /************************************************************************/
2023 /*                             IRasterIO()                              */
2024 /*                                                                      */
2025 /*      The default implementation of IRasterIO() is, in the general    */
2026 /*      case to pass the request off to each band objects rasterio      */
2027 /*      methods with appropriate arguments. In some cases, it might     */
2028 /*      choose instead the BlockBasedRasterIO() implementation.         */
2029 /************************************************************************/
2030 
2031 //! @cond Doxygen_Suppress
IRasterIO(GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,GSpacing nPixelSpace,GSpacing nLineSpace,GSpacing nBandSpace,GDALRasterIOExtraArg * psExtraArg)2032 CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
2033                                int nXOff, int nYOff, int nXSize, int nYSize,
2034                                void * pData, int nBufXSize, int nBufYSize,
2035                                GDALDataType eBufType,
2036                                int nBandCount, int *panBandMap,
2037                                GSpacing nPixelSpace, GSpacing nLineSpace,
2038                                GSpacing nBandSpace,
2039                                GDALRasterIOExtraArg* psExtraArg )
2040 
2041 {
2042     const char *pszInterleave = nullptr;
2043 
2044     CPLAssert(nullptr != pData);
2045 
2046     const bool bHasSubpixelShift =
2047        psExtraArg->bFloatingPointWindowValidity &&
2048        psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2049        (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2050 
2051     if (!bHasSubpixelShift &&
2052         nXSize == nBufXSize && nYSize == nBufYSize && nBandCount > 1 &&
2053         (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2054             nullptr &&
2055         EQUAL(pszInterleave, "PIXEL"))
2056     {
2057         return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2058                                   nBufXSize, nBufYSize, eBufType, nBandCount,
2059                                   panBandMap, nPixelSpace, nLineSpace,
2060                                   nBandSpace, psExtraArg);
2061     }
2062 
2063     if( eRWFlag == GF_Read &&
2064         (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2065          psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2066          psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2067          psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2068         !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1 )
2069     {
2070         if( nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled() )
2071         {
2072             int bTried = FALSE;
2073             const CPLErr eErr =
2074                 TryOverviewRasterIO( eRWFlag,
2075                                     nXOff, nYOff, nXSize, nYSize,
2076                                     pData, nBufXSize, nBufYSize,
2077                                     eBufType,
2078                                     nBandCount, panBandMap,
2079                                     nPixelSpace, nLineSpace,
2080                                     nBandSpace,
2081                                     psExtraArg,
2082                                     &bTried );
2083             if( bTried )
2084                 return eErr;
2085         }
2086 
2087         GDALDataType eFirstBandDT = GDT_Unknown;
2088         int nFirstMaskFlags = 0;
2089         GDALRasterBand *poFirstMaskBand = nullptr;
2090         int nOKBands = 0;
2091 
2092         // Check if bands share the same mask band
2093         for( int i = 0; i < nBandCount; ++i )
2094         {
2095             GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2096             if( (nBufXSize < nXSize || nBufYSize < nYSize) &&
2097                 poBand->GetOverviewCount() )
2098             {
2099                 // Could be improved to select the appropriate overview.
2100                 break;
2101             }
2102             if( poBand->GetColorTable() != nullptr )
2103             {
2104                 break;
2105             }
2106             const GDALDataType eDT = poBand->GetRasterDataType();
2107             if( GDALDataTypeIsComplex(eDT) )
2108             {
2109                 break;
2110             }
2111             if( i == 0 )
2112             {
2113                 eFirstBandDT = eDT;
2114                 nFirstMaskFlags = poBand->GetMaskFlags();
2115                 if( nFirstMaskFlags == GMF_NODATA)
2116                 {
2117                     // The dataset-level resampling code is not ready for nodata
2118                     // Fallback to band-level resampling
2119                     break;
2120                 }
2121                 poFirstMaskBand = poBand->GetMaskBand();
2122             }
2123             else
2124             {
2125                 if( eDT != eFirstBandDT )
2126                 {
2127                     break;
2128                 }
2129                 int nMaskFlags = poBand->GetMaskFlags();
2130                 if( nMaskFlags == GMF_NODATA)
2131                 {
2132                     // The dataset-level resampling code is not ready for nodata
2133                     // Fallback to band-level resampling
2134                     break;
2135                 }
2136                 GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2137                 if( nFirstMaskFlags == GMF_ALL_VALID &&
2138                     nMaskFlags == GMF_ALL_VALID )
2139                 {
2140                     // Ok.
2141                 }
2142                 else if( poFirstMaskBand == poMaskBand )
2143                 {
2144                     // Ok.
2145                 }
2146                 else
2147                 {
2148                     break;
2149                 }
2150             }
2151 
2152             ++nOKBands;
2153         }
2154 
2155         GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2156         void *pProgressDataGlobal = psExtraArg->pProgressData;
2157 
2158         CPLErr eErr = CE_None;
2159         if( nOKBands > 0 )
2160         {
2161             if( nOKBands < nBandCount )
2162             {
2163                 psExtraArg->pfnProgress = GDALScaledProgress;
2164                 psExtraArg->pProgressData = GDALCreateScaledProgress(
2165                     0.0, static_cast<double>(nOKBands) / nBandCount,
2166                     pfnProgressGlobal,
2167                     pProgressDataGlobal);
2168                 if( psExtraArg->pProgressData == nullptr )
2169                     psExtraArg->pfnProgress = nullptr;
2170             }
2171 
2172             eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2173                                      pData, nBufXSize, nBufYSize, eBufType,
2174                                      nOKBands, panBandMap, nPixelSpace,
2175                                      nLineSpace, nBandSpace, psExtraArg);
2176 
2177             if( nOKBands < nBandCount )
2178             {
2179                 GDALDestroyScaledProgress(psExtraArg->pProgressData);
2180             }
2181         }
2182         if( eErr == CE_None && nOKBands < nBandCount )
2183         {
2184             if( nOKBands > 0 )
2185             {
2186                 psExtraArg->pfnProgress = GDALScaledProgress;
2187                 psExtraArg->pProgressData = GDALCreateScaledProgress(
2188                     static_cast<double>(nOKBands) / nBandCount,
2189                     1.0, pfnProgressGlobal,
2190                     pProgressDataGlobal);
2191                 if( psExtraArg->pProgressData == nullptr )
2192                     psExtraArg->pfnProgress = nullptr;
2193             }
2194             eErr = BandBasedRasterIO(
2195                 eRWFlag, nXOff, nYOff, nXSize, nYSize,
2196                 static_cast<GByte *>(pData) + nBandSpace * nOKBands,
2197                 nBufXSize, nBufYSize,
2198                 eBufType, nBandCount - nOKBands, panBandMap + nOKBands,
2199                 nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
2200             if( nOKBands > 0 )
2201             {
2202                 GDALDestroyScaledProgress(psExtraArg->pProgressData);
2203             }
2204         }
2205 
2206         psExtraArg->pfnProgress = pfnProgressGlobal;
2207         psExtraArg->pProgressData = pProgressDataGlobal;
2208 
2209         return eErr;
2210     }
2211 
2212     return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2213                              nBufXSize, nBufYSize, eBufType, nBandCount,
2214                              panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2215                              psExtraArg);
2216 }
2217 //! @endcond
2218 
2219 /************************************************************************/
2220 /*                         BandBasedRasterIO()                          */
2221 /*                                                                      */
2222 /*      Pass the request off to each band objects rasterio methods with */
2223 /*      appropriate arguments.                                          */
2224 /************************************************************************/
2225 
2226 //! @cond Doxygen_Suppress
BandBasedRasterIO(GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,GSpacing nPixelSpace,GSpacing nLineSpace,GSpacing nBandSpace,GDALRasterIOExtraArg * psExtraArg)2227 CPLErr GDALDataset::BandBasedRasterIO( GDALRWFlag eRWFlag,
2228                                int nXOff, int nYOff, int nXSize, int nYSize,
2229                                void * pData, int nBufXSize, int nBufYSize,
2230                                GDALDataType eBufType,
2231                                int nBandCount, int *panBandMap,
2232                                GSpacing nPixelSpace, GSpacing nLineSpace,
2233                                GSpacing nBandSpace,
2234                                GDALRasterIOExtraArg* psExtraArg )
2235 
2236 {
2237     int iBandIndex;
2238     CPLErr eErr = CE_None;
2239 
2240     GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2241     void *pProgressDataGlobal = psExtraArg->pProgressData;
2242 
2243     for( iBandIndex = 0;
2244          iBandIndex < nBandCount && eErr == CE_None;
2245          ++iBandIndex )
2246     {
2247         GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2248 
2249         if (poBand == nullptr)
2250         {
2251             eErr = CE_Failure;
2252             break;
2253         }
2254 
2255         GByte *pabyBandData =
2256             static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2257 
2258         if( nBandCount > 1 )
2259         {
2260             psExtraArg->pfnProgress = GDALScaledProgress;
2261             psExtraArg->pProgressData = GDALCreateScaledProgress(
2262                 1.0 * iBandIndex / nBandCount,
2263                 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2264                 pProgressDataGlobal);
2265             if( psExtraArg->pProgressData == nullptr )
2266                 psExtraArg->pfnProgress = nullptr;
2267         }
2268 
2269         eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2270                                  pabyBandData, nBufXSize, nBufYSize,
2271                                  eBufType, nPixelSpace, nLineSpace, psExtraArg);
2272 
2273         if( nBandCount > 1 )
2274             GDALDestroyScaledProgress(psExtraArg->pProgressData);
2275     }
2276 
2277     psExtraArg->pfnProgress = pfnProgressGlobal;
2278     psExtraArg->pProgressData = pProgressDataGlobal;
2279 
2280     return eErr;
2281 }
2282 //! @endcond
2283 
2284 /************************************************************************/
2285 /*               ValidateRasterIOOrAdviseReadParameters()               */
2286 /************************************************************************/
2287 
2288 //! @cond Doxygen_Suppress
ValidateRasterIOOrAdviseReadParameters(const char * pszCallingFunc,int * pbStopProcessingOnCENone,int nXOff,int nYOff,int nXSize,int nYSize,int nBufXSize,int nBufYSize,int nBandCount,int * panBandMap)2289 CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
2290                                const char* pszCallingFunc,
2291                                int* pbStopProcessingOnCENone,
2292                                int nXOff, int nYOff, int nXSize, int nYSize,
2293                                int nBufXSize, int nBufYSize,
2294                                int nBandCount, int *panBandMap)
2295 {
2296 
2297 /* -------------------------------------------------------------------- */
2298 /*      Some size values are "noop".  Lets just return to avoid         */
2299 /*      stressing lower level functions.                                */
2300 /* -------------------------------------------------------------------- */
2301     if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
2302     {
2303         CPLDebug("GDAL",
2304                  "%s skipped for odd window or buffer size.\n"
2305                  "  Window = (%d,%d)x%dx%d\n"
2306                  "  Buffer = %dx%d",
2307                  pszCallingFunc,
2308                  nXOff, nYOff, nXSize, nYSize,
2309                  nBufXSize, nBufYSize);
2310 
2311         *pbStopProcessingOnCENone = TRUE;
2312         return CE_None;
2313     }
2314 
2315     CPLErr eErr = CE_None;
2316     *pbStopProcessingOnCENone = FALSE;
2317 
2318     if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
2319         || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
2320     {
2321         ReportError(CE_Failure, CPLE_IllegalArg,
2322                     "Access window out of range in %s.  Requested "
2323                     "(%d,%d) of size %dx%d on raster of %dx%d.",
2324                     pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
2325                     nRasterYSize);
2326         eErr = CE_Failure;
2327     }
2328 
2329     if( panBandMap == nullptr && nBandCount > GetRasterCount() )
2330     {
2331         ReportError( CE_Failure, CPLE_IllegalArg,
2332                     "%s: nBandCount cannot be greater than %d",
2333                     pszCallingFunc, GetRasterCount() );
2334         eErr = CE_Failure;
2335     }
2336 
2337     for( int i = 0; i < nBandCount && eErr == CE_None; ++i )
2338     {
2339         int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2340         if( iBand < 1 || iBand > GetRasterCount() )
2341         {
2342             ReportError(
2343                 CE_Failure, CPLE_IllegalArg,
2344                 "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
2345                 pszCallingFunc, i, iBand);
2346             eErr = CE_Failure;
2347         }
2348 
2349         if( eErr == CE_None && GetRasterBand( iBand ) == nullptr )
2350         {
2351             ReportError(
2352                 CE_Failure, CPLE_IllegalArg,
2353                 "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
2354                 pszCallingFunc, i, iBand);
2355             eErr = CE_Failure;
2356         }
2357     }
2358 
2359     return eErr;
2360 }
2361 //! @endcond
2362 
2363 /************************************************************************/
2364 /*                              RasterIO()                              */
2365 /************************************************************************/
2366 
2367 /**
2368  * \brief Read/write a region of image data from multiple bands.
2369  *
2370  * This method allows reading a region of one or more GDALRasterBands from
2371  * this dataset into a buffer,  or writing data from a buffer into a region
2372  * of the GDALRasterBands.  It automatically takes care of data type
2373  * translation if the data type (eBufType) of the buffer is different than
2374  * that of the GDALRasterBand.
2375  * The method also takes care of image decimation / replication if the
2376  * buffer size (nBufXSize x nBufYSize) is different than the size of the
2377  * region being accessed (nXSize x nYSize).
2378  *
2379  * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
2380  * writing from various organization of buffers.
2381  *
2382  * For highest performance full resolution data access, read and write
2383  * on "block boundaries" as returned by GetBlockSize(), or use the
2384  * ReadBlock() and WriteBlock() methods.
2385  *
2386  * This method is the same as the C GDALDatasetRasterIO() or
2387  * GDALDatasetRasterIOEx() functions.
2388  *
2389  * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
2390  * write a region of data.
2391  *
2392  * @param nXOff The pixel offset to the top left corner of the region
2393  * of the band to be accessed.  This would be zero to start from the left side.
2394  *
2395  * @param nYOff The line offset to the top left corner of the region
2396  * of the band to be accessed.  This would be zero to start from the top.
2397  *
2398  * @param nXSize The width of the region of the band to be accessed in pixels.
2399  *
2400  * @param nYSize The height of the region of the band to be accessed in lines.
2401  *
2402  * @param pData The buffer into which the data should be read, or from which
2403  * it should be written.  This buffer must contain at least
2404  * nBufXSize * nBufYSize * nBandCount words of type eBufType.  It is organized
2405  * in left to right,top to bottom pixel order.  Spacing is controlled by the
2406  * nPixelSpace, and nLineSpace parameters.
2407  *
2408  * @param nBufXSize the width of the buffer image into which the desired region
2409  * is to be read, or from which it is to be written.
2410  *
2411  * @param nBufYSize the height of the buffer image into which the desired
2412  * region is to be read, or from which it is to be written.
2413  *
2414  * @param eBufType the type of the pixel values in the pData data buffer. The
2415  * pixel values will automatically be translated to/from the GDALRasterBand
2416  * data type as needed.
2417  *
2418  * @param nBandCount the number of bands being read or written.
2419  *
2420  * @param panBandMap the list of nBandCount band numbers being read/written.
2421  * Note band numbers are 1 based. This may be NULL to select the first
2422  * nBandCount bands.
2423  *
2424  * @param nPixelSpace The byte offset from the start of one pixel value in
2425  * pData to the start of the next pixel value within a scanline. If defaulted
2426  * (0) the size of the datatype eBufType is used.
2427  *
2428  * @param nLineSpace The byte offset from the start of one scanline in
2429  * pData to the start of the next. If defaulted (0) the size of the datatype
2430  * eBufType * nBufXSize is used.
2431  *
2432  * @param nBandSpace the byte offset from the start of one bands data to the
2433  * start of the next. If defaulted (0) the value will be
2434  * nLineSpace * nBufYSize implying band sequential organization
2435  * of the data buffer.
2436  *
2437  * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
2438  * structure with additional arguments to specify resampling and progress
2439  * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
2440  * configuration option can also be defined to override the default resampling
2441  * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
2442  *
2443  * @return CE_Failure if the access fails, otherwise CE_None.
2444  */
2445 
RasterIO(GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,GSpacing nPixelSpace,GSpacing nLineSpace,GSpacing nBandSpace,GDALRasterIOExtraArg * psExtraArg)2446 CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
2447                               int nXOff, int nYOff, int nXSize, int nYSize,
2448                               void * pData, int nBufXSize, int nBufYSize,
2449                               GDALDataType eBufType,
2450                               int nBandCount, int *panBandMap,
2451                               GSpacing nPixelSpace, GSpacing nLineSpace,
2452                               GSpacing nBandSpace,
2453                               GDALRasterIOExtraArg* psExtraArg )
2454 
2455 {
2456     GDALRasterIOExtraArg sExtraArg;
2457     if( psExtraArg == nullptr )
2458     {
2459         INIT_RASTERIO_EXTRA_ARG(sExtraArg);
2460         psExtraArg = &sExtraArg;
2461     }
2462     else if( psExtraArg->nVersion != RASTERIO_EXTRA_ARG_CURRENT_VERSION )
2463     {
2464         ReportError(CE_Failure, CPLE_AppDefined,
2465                     "Unhandled version of GDALRasterIOExtraArg");
2466         return CE_Failure;
2467     }
2468 
2469     GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
2470                                        nBufYSize);
2471 
2472     if( nullptr == pData )
2473     {
2474         ReportError(CE_Failure, CPLE_AppDefined,
2475                     "The buffer into which the data should be read is null");
2476         return CE_Failure;
2477     }
2478 
2479 /* -------------------------------------------------------------------- */
2480 /*      Do some validation of parameters.                               */
2481 /* -------------------------------------------------------------------- */
2482 
2483     if( eRWFlag != GF_Read && eRWFlag != GF_Write )
2484     {
2485         ReportError(
2486             CE_Failure, CPLE_IllegalArg,
2487             "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
2488             eRWFlag);
2489         return CE_Failure;
2490     }
2491 
2492     if( eRWFlag == GF_Write )
2493     {
2494         if( eAccess != GA_Update )
2495         {
2496             ReportError( CE_Failure, CPLE_AppDefined,
2497                         "Write operation not permitted on dataset opened "
2498                         "in read-only mode" );
2499             return CE_Failure;
2500         }
2501     }
2502 
2503     int bStopProcessing = FALSE;
2504     CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2505         "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2506         nBufYSize, nBandCount, panBandMap);
2507     if( eErr != CE_None || bStopProcessing )
2508         return eErr;
2509 
2510 /* -------------------------------------------------------------------- */
2511 /*      If pixel and line spacing are defaulted assign reasonable      */
2512 /*      value assuming a packed buffer.                                 */
2513 /* -------------------------------------------------------------------- */
2514     if( nPixelSpace == 0 )
2515         nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
2516 
2517     if( nLineSpace == 0 )
2518     {
2519         nLineSpace = nPixelSpace * nBufXSize;
2520     }
2521 
2522     if( nBandSpace == 0 && nBandCount > 1 )
2523     {
2524         nBandSpace = nLineSpace * nBufYSize;
2525     }
2526 
2527     bool bNeedToFreeBandMap = false;
2528     int anBandMap[] = { 1, 2, 3, 4 };
2529     if( panBandMap == nullptr )
2530     {
2531         if( nBandCount > 4 )
2532         {
2533             panBandMap =
2534                 static_cast<int *>(VSIMalloc2(sizeof(int), nBandCount));
2535             if (panBandMap == nullptr)
2536             {
2537                 ReportError(CE_Failure, CPLE_OutOfMemory,
2538                             "Out of memory while allocating band map array");
2539                 return CE_Failure;
2540             }
2541 
2542             for( int i = 0; i < nBandCount; ++i )
2543                 panBandMap[i] = i + 1;
2544 
2545             bNeedToFreeBandMap = true;
2546         }
2547         else
2548         {
2549             panBandMap = anBandMap;
2550         }
2551     }
2552 
2553     int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
2554 
2555 /* -------------------------------------------------------------------- */
2556 /*      We are being forced to use cached IO instead of a driver        */
2557 /*      specific implementation.                                        */
2558 /* -------------------------------------------------------------------- */
2559     if( bForceCachedIO )
2560     {
2561         eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2562                                   nBufXSize, nBufYSize, eBufType, nBandCount,
2563                                   panBandMap, nPixelSpace, nLineSpace,
2564                                   nBandSpace, psExtraArg);
2565     }
2566 
2567 /* -------------------------------------------------------------------- */
2568 /*      Call the format specific function.                              */
2569 /* -------------------------------------------------------------------- */
2570     else
2571     {
2572         eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2573                          nBufXSize, nBufYSize, eBufType, nBandCount, panBandMap,
2574                          nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
2575     }
2576 
2577     if( bCallLeaveReadWrite ) LeaveReadWrite();
2578 
2579 /* -------------------------------------------------------------------- */
2580 /*      Cleanup                                                         */
2581 /* -------------------------------------------------------------------- */
2582     if( bNeedToFreeBandMap )
2583         CPLFree(panBandMap);
2584 
2585     return eErr;
2586 }
2587 
2588 /************************************************************************/
2589 /*                        GDALDatasetRasterIO()                         */
2590 /************************************************************************/
2591 
2592 /**
2593  * \brief Read/write a region of image data from multiple bands.
2594  *
2595  * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
2596  * resolution, progress callback, etc. are needed)
2597  *
2598  * @see GDALDataset::RasterIO()
2599  */
2600 
2601 CPLErr CPL_STDCALL
GDALDatasetRasterIO(GDALDatasetH hDS,GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,int nPixelSpace,int nLineSpace,int nBandSpace)2602 GDALDatasetRasterIO( GDALDatasetH hDS, GDALRWFlag eRWFlag,
2603                      int nXOff, int nYOff, int nXSize, int nYSize,
2604                      void * pData, int nBufXSize, int nBufYSize,
2605                      GDALDataType eBufType,
2606                      int nBandCount, int *panBandMap,
2607                      int nPixelSpace, int nLineSpace, int nBandSpace )
2608 
2609 {
2610     VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
2611 
2612     GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2613 
2614     return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2615                           nBufXSize, nBufYSize, eBufType, nBandCount,
2616                           panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2617                           nullptr);
2618 }
2619 
2620 /************************************************************************/
2621 /*                       GDALDatasetRasterIOEx()                        */
2622 /************************************************************************/
2623 
2624 /**
2625  * \brief Read/write a region of image data from multiple bands.
2626  *
2627  * @see GDALDataset::RasterIO()
2628  * @since GDAL 2.0
2629  */
2630 
GDALDatasetRasterIOEx(GDALDatasetH hDS,GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,GSpacing nPixelSpace,GSpacing nLineSpace,GSpacing nBandSpace,GDALRasterIOExtraArg * psExtraArg)2631 CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
2632     GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
2633     int nYSize, void *pData, int nBufXSize, int nBufYSize,
2634     GDALDataType eBufType, int nBandCount, int *panBandMap,
2635     GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
2636     GDALRasterIOExtraArg *psExtraArg )
2637 
2638 {
2639     VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
2640 
2641     GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2642 
2643     return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2644                           nBufXSize, nBufYSize, eBufType, nBandCount,
2645                           panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2646                           psExtraArg);
2647 }
2648 /************************************************************************/
2649 /*                          GetOpenDatasets()                           */
2650 /************************************************************************/
2651 
2652 /**
2653  * \brief Fetch all open GDAL dataset handles.
2654  *
2655  * This method is the same as the C function GDALGetOpenDatasets().
2656  *
2657  * NOTE: This method is not thread safe.  The returned list may change
2658  * at any time and it should not be freed.
2659  *
2660  * @param pnCount integer into which to place the count of dataset pointers
2661  * being returned.
2662  *
2663  * @return a pointer to an array of dataset handles.
2664  */
2665 
GetOpenDatasets(int * pnCount)2666 GDALDataset **GDALDataset::GetOpenDatasets( int *pnCount )
2667 
2668 {
2669     CPLMutexHolderD(&hDLMutex);
2670 
2671     if (poAllDatasetMap == nullptr)
2672     {
2673         *pnCount = 0;
2674         return nullptr;
2675     }
2676 
2677     *pnCount = static_cast<int>(poAllDatasetMap->size());
2678     ppDatasets = static_cast<GDALDataset **>(
2679         CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
2680     std::map<GDALDataset *, GIntBig>::iterator oIter =
2681         poAllDatasetMap->begin();
2682     for( int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i )
2683         ppDatasets[i] = oIter->first;
2684     return ppDatasets;
2685 }
2686 
2687 /************************************************************************/
2688 /*                        GDALGetOpenDatasets()                         */
2689 /************************************************************************/
2690 
2691 /**
2692  * \brief Fetch all open GDAL dataset handles.
2693  *
2694  * @see GDALDataset::GetOpenDatasets()
2695  */
2696 
GDALGetOpenDatasets(GDALDatasetH ** ppahDSList,int * pnCount)2697 void CPL_STDCALL GDALGetOpenDatasets( GDALDatasetH **ppahDSList, int *pnCount )
2698 
2699 {
2700     VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
2701     VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
2702 
2703     *ppahDSList = reinterpret_cast<GDALDatasetH *>(
2704         GDALDataset::GetOpenDatasets(pnCount));
2705 }
2706 
2707 /************************************************************************/
2708 /*                        GDALCleanOpenDatasetsList()                   */
2709 /************************************************************************/
2710 
2711 // Useful when called from the child of a fork(), to avoid closing
2712 // the datasets of the parent at the child termination.
GDALNullifyOpenDatasetsList()2713 void GDALNullifyOpenDatasetsList()
2714 {
2715     poAllDatasetMap = nullptr;
2716     phSharedDatasetSet = nullptr;
2717     ppDatasets = nullptr;
2718     hDLMutex = nullptr;
2719 }
2720 
2721 /************************************************************************/
2722 /*                             GDALGetAccess()                          */
2723 /************************************************************************/
2724 
2725 /**
2726  * \brief Return access flag
2727  *
2728  * @see GDALDataset::GetAccess()
2729  */
2730 
GDALGetAccess(GDALDatasetH hDS)2731 int CPL_STDCALL GDALGetAccess( GDALDatasetH hDS )
2732 {
2733     VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
2734 
2735     return GDALDataset::FromHandle(hDS)->GetAccess();
2736 }
2737 
2738 /************************************************************************/
2739 /*                             AdviseRead()                             */
2740 /************************************************************************/
2741 
2742 /**
2743  * \brief Advise driver of upcoming read requests.
2744  *
2745  * Some GDAL drivers operate more efficiently if they know in advance what
2746  * set of upcoming read requests will be made.  The AdviseRead() method allows
2747  * an application to notify the driver of the region and bands of interest,
2748  * and at what resolution the region will be read.
2749  *
2750  * Many drivers just ignore the AdviseRead() call, but it can dramatically
2751  * accelerate access via some drivers.
2752  *
2753  * Depending on call paths, drivers might receive several calls to
2754  * AdviseRead() with the same parameters.
2755  *
2756  * @param nXOff The pixel offset to the top left corner of the region
2757  * of the band to be accessed.  This would be zero to start from the left side.
2758  *
2759  * @param nYOff The line offset to the top left corner of the region
2760  * of the band to be accessed.  This would be zero to start from the top.
2761  *
2762  * @param nXSize The width of the region of the band to be accessed in pixels.
2763  *
2764  * @param nYSize The height of the region of the band to be accessed in lines.
2765  *
2766  * @param nBufXSize the width of the buffer image into which the desired region
2767  * is to be read, or from which it is to be written.
2768  *
2769  * @param nBufYSize the height of the buffer image into which the desired
2770  * region is to be read, or from which it is to be written.
2771  *
2772  * @param eBufType the type of the pixel values in the pData data buffer.  The
2773  * pixel values will automatically be translated to/from the GDALRasterBand
2774  * data type as needed.
2775  *
2776  * @param nBandCount the number of bands being read or written.
2777  *
2778  * @param panBandMap the list of nBandCount band numbers being read/written.
2779  * Note band numbers are 1 based.   This may be NULL to select the first
2780  * nBandCount bands.
2781  *
2782  * @param papszOptions a list of name=value strings with special control
2783  * options.  Normally this is NULL.
2784  *
2785  * @return CE_Failure if the request is invalid and CE_None if it works or
2786  * is ignored.
2787  */
2788 
AdviseRead(int nXOff,int nYOff,int nXSize,int nYSize,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,char ** papszOptions)2789 CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
2790                                 int nBufXSize, int nBufYSize,
2791                                 GDALDataType eBufType,
2792                                 int nBandCount, int *panBandMap,
2793                                 char **papszOptions )
2794 
2795 {
2796 /* -------------------------------------------------------------------- */
2797 /*      Do some validation of parameters.                               */
2798 /* -------------------------------------------------------------------- */
2799     int bStopProcessing = FALSE;
2800     CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2801         "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
2802         nBufXSize, nBufYSize, nBandCount, panBandMap);
2803     if( eErr != CE_None || bStopProcessing )
2804         return eErr;
2805 
2806     for( int iBand = 0; iBand < nBandCount; ++iBand )
2807     {
2808         GDALRasterBand *poBand = nullptr;
2809 
2810         if( panBandMap == nullptr )
2811             poBand = GetRasterBand(iBand + 1);
2812         else
2813             poBand = GetRasterBand(panBandMap[iBand]);
2814 
2815         if ( poBand == nullptr )
2816             return CE_Failure;
2817 
2818         eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
2819                                   nBufYSize, eBufType, papszOptions);
2820 
2821         if( eErr != CE_None )
2822             return eErr;
2823     }
2824 
2825     return CE_None;
2826 }
2827 
2828 /************************************************************************/
2829 /*                       GDALDatasetAdviseRead()                        */
2830 /************************************************************************/
2831 
2832 /**
2833  * \brief Advise driver of upcoming read requests.
2834  *
2835  * @see GDALDataset::AdviseRead()
2836  */
2837 CPLErr CPL_STDCALL
GDALDatasetAdviseRead(GDALDatasetH hDS,int nXOff,int nYOff,int nXSize,int nYSize,int nBufXSize,int nBufYSize,GDALDataType eDT,int nBandCount,int * panBandMap,CSLConstList papszOptions)2838 GDALDatasetAdviseRead( GDALDatasetH hDS,
2839                        int nXOff, int nYOff, int nXSize, int nYSize,
2840                        int nBufXSize, int nBufYSize, GDALDataType eDT,
2841                        int nBandCount, int *panBandMap,
2842                        CSLConstList papszOptions )
2843 
2844 {
2845     VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
2846 
2847     return GDALDataset::FromHandle(hDS)
2848         ->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT,
2849                      nBandCount, panBandMap, const_cast<char**>(papszOptions));
2850 }
2851 
2852 /************************************************************************/
2853 /*                         AntiRecursionStruct                          */
2854 /************************************************************************/
2855 
2856 namespace {
2857 // Prevent infinite recursion.
2858 struct AntiRecursionStruct
2859 {
2860     struct DatasetContext
2861     {
2862         std::string osFilename;
2863         int         nOpenFlags;
2864         int         nSizeAllowedDrivers;
2865 
DatasetContext__anoneda167420111::AntiRecursionStruct::DatasetContext2866         DatasetContext(const std::string& osFilenameIn,
2867                         int nOpenFlagsIn,
2868                         int nSizeAllowedDriversIn) :
2869             osFilename(osFilenameIn),
2870             nOpenFlags(nOpenFlagsIn),
2871             nSizeAllowedDrivers(nSizeAllowedDriversIn) {}
2872     };
2873 
2874     struct DatasetContextCompare {
operator ()__anoneda167420111::AntiRecursionStruct::DatasetContextCompare2875         bool operator() (const DatasetContext& lhs, const DatasetContext& rhs) const {
2876             return lhs.osFilename < rhs.osFilename ||
2877                     (lhs.osFilename == rhs.osFilename &&
2878                     (lhs.nOpenFlags < rhs.nOpenFlags ||
2879                         (lhs.nOpenFlags == rhs.nOpenFlags &&
2880                         lhs.nSizeAllowedDrivers < rhs.nSizeAllowedDrivers)));
2881         }
2882     };
2883 
2884     std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
2885     int nRecLevel = 0;
2886 };
2887 } // namespace
2888 
2889 #ifdef WIN32
2890 // Currently thread_local and C++ objects don't work well with DLL on Windows
FreeAntiRecursion(void * pData)2891 static void FreeAntiRecursion( void* pData )
2892 {
2893     delete static_cast<AntiRecursionStruct*>(pData);
2894 }
2895 
GetAntiRecursion()2896 static AntiRecursionStruct& GetAntiRecursion()
2897 {
2898     static AntiRecursionStruct dummy;
2899     int bMemoryErrorOccurred = false;
2900     void* pData = CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
2901     if( bMemoryErrorOccurred )
2902     {
2903         return dummy;
2904     }
2905     if( pData == nullptr)
2906     {
2907         auto pAntiRecursion = new AntiRecursionStruct();
2908         CPLSetTLSWithFreeFuncEx( CTLS_GDALOPEN_ANTIRECURSION,
2909                                  pAntiRecursion,
2910                                  FreeAntiRecursion, &bMemoryErrorOccurred );
2911         if( bMemoryErrorOccurred )
2912         {
2913             delete pAntiRecursion;
2914             return dummy;
2915         }
2916         return *pAntiRecursion;
2917     }
2918     return *static_cast<AntiRecursionStruct*>(pData);
2919 }
2920 #else
2921 static thread_local AntiRecursionStruct g_tls_antiRecursion;
GetAntiRecursion()2922 static AntiRecursionStruct& GetAntiRecursion()
2923 {
2924     return g_tls_antiRecursion;
2925 }
2926 #endif
2927 
2928 /************************************************************************/
2929 /*                            GetFileList()                             */
2930 /************************************************************************/
2931 
2932 /**
2933  * \brief Fetch files forming dataset.
2934  *
2935  * Returns a list of files believed to be part of this dataset.  If it returns
2936  * an empty list of files it means there is believed to be no local file
2937  * system files associated with the dataset (for instance a virtual dataset).
2938  * The returned file list is owned by the caller and should be deallocated
2939  * with CSLDestroy().
2940  *
2941  * The returned filenames will normally be relative or absolute paths
2942  * depending on the path used to originally open the dataset.  The strings
2943  * will be UTF-8 encoded.
2944  *
2945  * This method is the same as the C GDALGetFileList() function.
2946  *
2947  * @return NULL or a NULL terminated array of file names.
2948  */
2949 
GetFileList()2950 char **GDALDataset::GetFileList()
2951 
2952 {
2953     CPLString osMainFilename = GetDescription();
2954     VSIStatBufL sStat;
2955 
2956     AntiRecursionStruct& sAntiRecursion = GetAntiRecursion();
2957     const AntiRecursionStruct::DatasetContext datasetCtxt(
2958         osMainFilename, 0, 0);
2959     auto& aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
2960     if( aosDatasetList.find(datasetCtxt) != aosDatasetList.end() )
2961         return nullptr;
2962 
2963 /* -------------------------------------------------------------------- */
2964 /*      Is the main filename even a real filesystem object?             */
2965 /* -------------------------------------------------------------------- */
2966     int bMainFileReal =
2967         VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
2968 
2969 /* -------------------------------------------------------------------- */
2970 /*      Form new list.                                                  */
2971 /* -------------------------------------------------------------------- */
2972     char **papszList = nullptr;
2973 
2974     if( bMainFileReal )
2975         papszList = CSLAddString(papszList, osMainFilename);
2976 
2977     if( sAntiRecursion.nRecLevel == 100 )
2978     {
2979         CPLError(CE_Failure, CPLE_AppDefined,
2980                     "GetFileList() called with too many recursion levels");
2981         return papszList;
2982     }
2983     ++sAntiRecursion.nRecLevel;
2984 
2985 /* -------------------------------------------------------------------- */
2986 /*      Do we have a known overview file?                               */
2987 /* -------------------------------------------------------------------- */
2988     if(oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
2989     {
2990         auto iter = aosDatasetList.insert(datasetCtxt).first;
2991         char **papszOvrList = oOvManager.poODS->GetFileList();
2992         papszList = CSLInsertStrings(papszList, -1, papszOvrList);
2993         CSLDestroy(papszOvrList);
2994         aosDatasetList.erase(iter);
2995     }
2996 
2997 /* -------------------------------------------------------------------- */
2998 /*      Do we have a known mask file?                                   */
2999 /* -------------------------------------------------------------------- */
3000     if( oOvManager.HaveMaskFile() )
3001     {
3002         auto iter = aosDatasetList.insert(datasetCtxt).first;
3003         char **papszMskList = oOvManager.poMaskDS->GetFileList();
3004         char **papszIter = papszMskList;
3005         while( papszIter && *papszIter )
3006         {
3007             if( CSLFindString( papszList, *papszIter ) < 0 )
3008                 papszList = CSLAddString( papszList, *papszIter );
3009             ++papszIter;
3010         }
3011         CSLDestroy(papszMskList);
3012         aosDatasetList.erase(iter);
3013     }
3014 
3015     --sAntiRecursion.nRecLevel;
3016 
3017     return papszList;
3018 }
3019 
3020 /************************************************************************/
3021 /*                          GDALGetFileList()                           */
3022 /************************************************************************/
3023 
3024 /**
3025  * \brief Fetch files forming dataset.
3026  *
3027  * @see GDALDataset::GetFileList()
3028  */
3029 
GDALGetFileList(GDALDatasetH hDS)3030 char ** CPL_STDCALL GDALGetFileList( GDALDatasetH hDS )
3031 
3032 {
3033     VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3034 
3035     return GDALDataset::FromHandle(hDS)->GetFileList();
3036 }
3037 
3038 /************************************************************************/
3039 /*                           CreateMaskBand()                           */
3040 /************************************************************************/
3041 
3042 /**
3043  * \brief Adds a mask band to the dataset
3044  *
3045  * The default implementation of the CreateMaskBand() method is implemented
3046  * based on similar rules to the .ovr handling implemented using the
3047  * GDALDefaultOverviews object. A TIFF file with the extension .msk will
3048  * be created with the same basename as the original file, and it will have
3049  * one band.
3050  * The mask images will be deflate compressed tiled images with the same
3051  * block size as the original image if possible.
3052  * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
3053  * level, where xx matches the band number of a band of the main dataset. The
3054  * value of those items will be the one of the nFlagsIn parameter.
3055  *
3056  * Note that if you got a mask band with a previous call to GetMaskBand(), it
3057  * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
3058  * again.
3059  *
3060  * @since GDAL 1.5.0
3061  *
3062  * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
3063  *                 GMF_PER_DATASET will be always set, even if not explicitly
3064  *                 specified.
3065  * @return CE_None on success or CE_Failure on an error.
3066  *
3067  * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
3068  * @see GDALRasterBand::CreateMaskBand()
3069  *
3070  */
CreateMaskBand(int nFlagsIn)3071 CPLErr GDALDataset::CreateMaskBand( int nFlagsIn )
3072 
3073 {
3074     if( oOvManager.IsInitialized() )
3075     {
3076         CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
3077         if (eErr != CE_None)
3078             return eErr;
3079 
3080         // Invalidate existing raster band masks.
3081         for( int i = 0; i < nBands; ++i )
3082         {
3083             GDALRasterBand *poBand = papoBands[i];
3084             if (poBand->bOwnMask)
3085                 delete poBand->poMask;
3086             poBand->bOwnMask = false;
3087             poBand->poMask = nullptr;
3088         }
3089 
3090         return CE_None;
3091     }
3092 
3093     ReportError(CE_Failure, CPLE_NotSupported,
3094                 "CreateMaskBand() not supported for this dataset.");
3095 
3096     return CE_Failure;
3097 }
3098 
3099 /************************************************************************/
3100 /*                     GDALCreateDatasetMaskBand()                      */
3101 /************************************************************************/
3102 
3103 /**
3104  * \brief Adds a mask band to the dataset
3105  * @see GDALDataset::CreateMaskBand()
3106  */
GDALCreateDatasetMaskBand(GDALDatasetH hDS,int nFlags)3107 CPLErr CPL_STDCALL GDALCreateDatasetMaskBand( GDALDatasetH hDS, int nFlags )
3108 
3109 {
3110     VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3111 
3112     return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
3113 }
3114 
3115 /************************************************************************/
3116 /*                              GDALOpen()                              */
3117 /************************************************************************/
3118 
3119 /**
3120  * \brief Open a raster file as a GDALDataset.
3121  *
3122  * This function will try to open the passed file, or virtual dataset
3123  * name by invoking the Open method of each registered GDALDriver in turn.
3124  * The first successful open will result in a returned dataset.  If all
3125  * drivers fail then NULL is returned and an error is issued.
3126  *
3127  * Several recommendations :
3128  * <ul>
3129  * <li>If you open a dataset object with GA_Update access, it is not recommended
3130  * to open a new dataset on the same underlying file.</li>
3131  * <li>The returned dataset should only be accessed by one thread at a time. If
3132  * you want to use it from different threads, you must add all necessary code
3133  * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such
3134  * as GeoTIFF, maintain internal state variables that are updated each time a
3135  * new block is read, thus preventing concurrent use.) </li>
3136  * </ul>
3137  *
3138  * For drivers supporting the VSI virtual file API, it is possible to open a
3139  * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3140  * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3141  * server (see VSIInstallCurlFileHandler())
3142  *
3143  * \sa GDALOpenShared()
3144  * \sa GDALOpenEx()
3145  *
3146  * @param pszFilename the name of the file to access.  In the case of
3147  * exotic drivers this may not refer to a physical file, but instead contain
3148  * information for the driver on how to access a dataset.  It should be in UTF-8
3149  * encoding.
3150  *
3151  * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
3152  * drivers support only read only access.
3153  *
3154  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
3155  * this handle can be cast to a GDALDataset *.
3156  */
3157 
3158 GDALDatasetH CPL_STDCALL
GDALOpen(const char * pszFilename,GDALAccess eAccess)3159 GDALOpen( const char * pszFilename, GDALAccess eAccess )
3160 
3161 {
3162     const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3163     const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3164     GDALDatasetH hDataset =
3165         GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3166     return hDataset;
3167 }
3168 
3169 /************************************************************************/
3170 /*                             GDALOpenEx()                             */
3171 /************************************************************************/
3172 
3173 /**
3174  * \brief Open a raster or vector file as a GDALDataset.
3175  *
3176  * This function will try to open the passed file, or virtual dataset
3177  * name by invoking the Open method of each registered GDALDriver in turn.
3178  * The first successful open will result in a returned dataset.  If all
3179  * drivers fail then NULL is returned and an error is issued.
3180  *
3181  * Several recommendations :
3182  * <ul>
3183  * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
3184  * recommended to open a new dataset on the same underlying file.</li>
3185  * <li>The returned dataset should only be accessed by one thread at a time. If
3186  * you want to use it from different threads, you must add all necessary code
3187  * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such
3188  * as GeoTIFF, maintain internal state variables that are updated each time a
3189  * new block is read, thus preventing concurrent use.) </li>
3190  * </ul>
3191  *
3192  * For drivers supporting the VSI virtual file API, it is possible to open a
3193  * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3194  * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3195  * server (see VSIInstallCurlFileHandler())
3196  *
3197  * In order to reduce the need for searches through the operating system
3198  * file system machinery, it is possible to give an optional list of files with
3199  * the papszSiblingFiles parameter.
3200  * This is the list of all files at the same level in the file system as the
3201  * target file, including the target file. The filenames must not include any
3202  * path components, are essentially just the output of VSIReadDir() on the
3203  * parent directory. If the target object does not have filesystem semantics
3204  * then the file list should be NULL.
3205  *
3206  * @param pszFilename the name of the file to access.  In the case of
3207  * exotic drivers this may not refer to a physical file, but instead contain
3208  * information for the driver on how to access a dataset.  It should be in UTF-8
3209  * encoding.
3210  *
3211  * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
3212  * through logical or operator.
3213  * <ul>
3214  * <li>Driver kind: GDAL_OF_RASTER for raster drivers, GDAL_OF_VECTOR for vector
3215  *     drivers, GDAL_OF_GNM for Geographic Network Model drivers.
3216  *     If none of the value is specified, all kinds are implied.</li>
3217  * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.</li>
3218  * <li>Shared mode: GDAL_OF_SHARED. If set, it allows the sharing of GDALDataset
3219  * handles for a dataset with other callers that have set GDAL_OF_SHARED.
3220  * In particular, GDALOpenEx() will first consult its list of currently
3221  * open and shared GDALDataset's, and if the GetDescription() name for one
3222  * exactly matches the pszFilename passed to GDALOpenEx() it will be
3223  * referenced and returned, if GDALOpenEx() is called from the same thread.</li>
3224  * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set, a failed attempt to open
3225  * the file will lead to an error message to be reported.</li>
3226  * </ul>
3227  *
3228  * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
3229  * terminated list of strings with the driver short names that must be
3230  * considered.
3231  *
3232  * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
3233  * options passed to candidate drivers. An option exists for all drivers,
3234  * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
3235  * The level index starts at 0. The level number can be suffixed by "only" to
3236  * specify that only this overview level must be visible, and not sub-levels.
3237  * Open options are validated by default, and a warning is emitted in case the
3238  * option is not recognized. In some scenarios, it might be not desirable (e.g.
3239  * when not knowing which driver will open the file), so the special open option
3240  * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
3241  * since GDAL 2.1, an option name can be preceded by the @ character to indicate
3242  * that it may not cause a warning if the driver doesn't declare this option.
3243  * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
3244  * no overviews should be exposed.
3245  *
3246  * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
3247  * filenames that are auxiliary to the main filename. If NULL is passed, a
3248  * probing of the file system will be done.
3249  *
3250  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
3251  * this handle can be cast to a GDALDataset *.
3252  *
3253  * @since GDAL 2.0
3254  */
3255 
GDALOpenEx(const char * pszFilename,unsigned int nOpenFlags,const char * const * papszAllowedDrivers,const char * const * papszOpenOptions,const char * const * papszSiblingFiles)3256 GDALDatasetH CPL_STDCALL GDALOpenEx( const char *pszFilename,
3257                                      unsigned int nOpenFlags,
3258                                      const char *const *papszAllowedDrivers,
3259                                      const char *const *papszOpenOptions,
3260                                      const char *const *papszSiblingFiles )
3261 {
3262     VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
3263 /* -------------------------------------------------------------------- */
3264 /*      In case of shared dataset, first scan the existing list to see  */
3265 /*      if it could already contain the requested dataset.              */
3266 /* -------------------------------------------------------------------- */
3267     if( nOpenFlags & GDAL_OF_SHARED )
3268     {
3269         if( nOpenFlags & GDAL_OF_INTERNAL )
3270         {
3271             CPLError(CE_Failure, CPLE_IllegalArg,
3272                      "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
3273             return nullptr;
3274         }
3275 
3276         CPLMutexHolderD(&hDLMutex);
3277 
3278         if (phSharedDatasetSet != nullptr)
3279         {
3280             const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3281             SharedDatasetCtxt sStruct;
3282 
3283             sStruct.nPID = nThisPID;
3284             sStruct.pszDescription = const_cast<char *>(pszFilename);
3285             sStruct.eAccess =
3286                 (nOpenFlags & GDAL_OF_UPDATE) ? GA_Update : GA_ReadOnly;
3287             SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3288                 CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3289             if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3290             {
3291                 sStruct.eAccess = GA_Update;
3292                 psStruct = static_cast<SharedDatasetCtxt *>(
3293                     CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3294             }
3295             if (psStruct)
3296             {
3297                 psStruct->poDS->Reference();
3298                 return psStruct->poDS;
3299             }
3300         }
3301     }
3302 
3303     // If no driver kind is specified, assume all are to be probed.
3304     if( (nOpenFlags & GDAL_OF_KIND_MASK) == 0 )
3305         nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
3306 
3307     GDALDriverManager *poDM = GetGDALDriverManager();
3308     // CPLLocaleC  oLocaleForcer;
3309 
3310     CPLErrorReset();
3311     VSIErrorReset();
3312     CPLAssert(nullptr != poDM);
3313 
3314     // Build GDALOpenInfo just now to avoid useless file stat'ing if a
3315     // shared dataset was asked before.
3316     GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
3317                            const_cast<char **>(papszSiblingFiles));
3318     oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3319 
3320     AntiRecursionStruct& sAntiRecursion = GetAntiRecursion();
3321     if( sAntiRecursion.nRecLevel == 100 )
3322     {
3323         CPLError(CE_Failure, CPLE_AppDefined,
3324                     "GDALOpen() called with too many recursion levels");
3325         return nullptr;
3326     }
3327 
3328     auto dsCtxt = AntiRecursionStruct::DatasetContext(
3329         std::string(pszFilename), nOpenFlags, CSLCount(papszAllowedDrivers));
3330     if( sAntiRecursion.aosDatasetNamesWithFlags.find(dsCtxt) !=
3331                 sAntiRecursion.aosDatasetNamesWithFlags.end() )
3332     {
3333         CPLError(CE_Failure, CPLE_AppDefined,
3334                     "GDALOpen() called on %s recursively", pszFilename);
3335         return nullptr;
3336     }
3337 
3338     // Remove leading @ if present.
3339     char **papszOpenOptionsCleaned =
3340         CSLDuplicate(const_cast<char **>(papszOpenOptions));
3341     for(char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
3342         ++papszIter)
3343     {
3344         char *pszOption = *papszIter;
3345         if( pszOption[0] == '@' )
3346             memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
3347     }
3348 
3349     oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3350 
3351 #ifdef OGRAPISPY_ENABLED
3352     const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
3353     const int iSnapshot = (nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3354                           (nOpenFlags & GDAL_OF_RASTER) == 0 ?
3355         OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate) : INT_MIN;
3356 #endif
3357 
3358     const int nDriverCount = poDM->GetDriverCount();
3359     for( int iDriver = 0; iDriver < nDriverCount; ++iDriver )
3360     {
3361         GDALDriver *poDriver = poDM->GetDriver(iDriver);
3362         if (papszAllowedDrivers != nullptr &&
3363             CSLFindString(papszAllowedDrivers,
3364                             GDALGetDriverShortName(poDriver)) == -1)
3365         {
3366             continue;
3367         }
3368 
3369         if( (nOpenFlags & GDAL_OF_RASTER) != 0 &&
3370             (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
3371             poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr )
3372             continue;
3373         if( (nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3374             (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3375             poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr )
3376             continue;
3377         if( (nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
3378             (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3379             poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr )
3380             continue;
3381         if( poDriver->pfnOpen == nullptr &&
3382             poDriver->pfnOpenWithDriverArg == nullptr )
3383         {
3384             continue;
3385         }
3386 
3387         // Remove general OVERVIEW_LEVEL open options from list before passing
3388         // it to the driver, if it isn't a driver specific option already.
3389         char **papszTmpOpenOptions = nullptr;
3390         char **papszTmpOpenOptionsToValidate = nullptr;
3391         char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
3392         if( CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
3393                nullptr &&
3394             (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) == nullptr ||
3395              CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST))
3396                     .ifind("OVERVIEW_LEVEL") == std::string::npos) )
3397         {
3398             papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
3399             papszTmpOpenOptions =
3400                 CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
3401             oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
3402 
3403             papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
3404             papszOptionsToValidate =
3405                 CSLSetNameValue(papszOptionsToValidate, "OVERVIEW_LEVEL", nullptr);
3406             papszTmpOpenOptionsToValidate = papszOptionsToValidate;
3407         }
3408 
3409         const bool bIdentifyRes =
3410             poDriver->pfnIdentifyEx ?
3411                 poDriver->pfnIdentifyEx(poDriver, &oOpenInfo) > 0:
3412             poDriver->pfnIdentify && poDriver->pfnIdentify(&oOpenInfo) > 0;
3413         if( bIdentifyRes )
3414         {
3415             GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3416         }
3417 
3418 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3419         const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
3420         CPLErrorReset();
3421 #endif
3422 
3423         sAntiRecursion.nRecLevel ++;
3424         sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
3425 
3426         GDALDataset *poDS = nullptr;
3427         if ( poDriver->pfnOpen != nullptr )
3428         {
3429             poDS = poDriver->pfnOpen(&oOpenInfo);
3430             // If we couldn't determine for sure with Identify() (it returned
3431             // -1), but Open() managed to open the file, post validate options.
3432             if( poDS != nullptr &&
3433                 (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) && !bIdentifyRes )
3434             {
3435                 GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3436             }
3437         }
3438         else if( poDriver->pfnOpenWithDriverArg != nullptr )
3439         {
3440             poDS = poDriver->pfnOpenWithDriverArg(poDriver, &oOpenInfo);
3441         }
3442 
3443         sAntiRecursion.nRecLevel --;
3444         sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
3445 
3446         CSLDestroy(papszTmpOpenOptions);
3447         CSLDestroy(papszTmpOpenOptionsToValidate);
3448         oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3449 
3450         if( poDS != nullptr )
3451         {
3452             poDS->nOpenFlags = nOpenFlags;
3453 
3454             if( strlen(poDS->GetDescription()) == 0 )
3455                 poDS->SetDescription(pszFilename);
3456 
3457             if( poDS->poDriver == nullptr )
3458                 poDS->poDriver = poDriver;
3459 
3460             if( poDS->papszOpenOptions == nullptr )
3461             {
3462                 poDS->papszOpenOptions = papszOpenOptionsCleaned;
3463                 papszOpenOptionsCleaned = nullptr;
3464             }
3465 
3466             if( !(nOpenFlags & GDAL_OF_INTERNAL) )
3467             {
3468                 if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() )
3469                     CPLDebug("GDAL",
3470                              "GDALOpen(%s, this=%p) succeeds as "
3471                              "%s (pid=%d, responsiblePID=%d).",
3472                              pszFilename, poDS, poDriver->GetDescription(),
3473                              static_cast<int>(CPLGetPID()),
3474                              static_cast<int>(
3475                                  GDALGetResponsiblePIDForCurrentThread()));
3476                 else
3477                     CPLDebug("GDAL", "GDALOpen(%s, this=%p) succeeds as %s.",
3478                              pszFilename, poDS, poDriver->GetDescription());
3479 
3480                 poDS->AddToDatasetOpenList();
3481             }
3482 
3483             if( nOpenFlags & GDAL_OF_SHARED )
3484             {
3485                 if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3486                 {
3487                     CPLError(CE_Warning, CPLE_NotSupported,
3488                              "A dataset opened by GDALOpenShared should have "
3489                              "the same filename (%s) "
3490                              "and description (%s)",
3491                              pszFilename, poDS->GetDescription());
3492                 }
3493                 else
3494                 {
3495                     poDS->MarkAsShared();
3496                 }
3497             }
3498 
3499             // Deal with generic OVERVIEW_LEVEL open option, unless it is
3500             // driver specific.
3501             if( CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") != nullptr &&
3502                 (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) == nullptr ||
3503                 CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST))
3504                         .ifind("OVERVIEW_LEVEL") == std::string::npos) )
3505             {
3506                 CPLString osVal(
3507                     CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
3508                 const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
3509                 const bool bThisLevelOnly =
3510                     nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
3511                 GDALDataset *poOvrDS = GDALCreateOverviewDataset(
3512                     poDS, nOvrLevel, bThisLevelOnly);
3513                 poDS->ReleaseRef();
3514                 poDS = poOvrDS;
3515                 if( poDS == nullptr )
3516                 {
3517                     if( nOpenFlags & GDAL_OF_VERBOSE_ERROR )
3518                     {
3519                         CPLError(CE_Failure, CPLE_OpenFailed,
3520                                  "Cannot open overview level %d of %s",
3521                                  nOvrLevel, pszFilename);
3522                     }
3523                 }
3524             }
3525             VSIErrorReset();
3526 
3527             CSLDestroy(papszOpenOptionsCleaned);
3528 
3529 #ifdef OGRAPISPY_ENABLED
3530             if( iSnapshot != INT_MIN )
3531             {
3532                 GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
3533                 OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3534                 poDS = GDALDataset::FromHandle(hDS);
3535             }
3536 #endif
3537 
3538             return poDS;
3539         }
3540 
3541 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3542         if( bFpAvailableBefore && oOpenInfo.fpL == nullptr )
3543         {
3544             // In case the file descriptor was "consumed" by a driver
3545             // that ultimately failed, re-open it for next drivers.
3546             oOpenInfo.fpL = VSIFOpenL(
3547                 pszFilename,
3548                 (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
3549         }
3550 #else
3551         if( CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
3552         {
3553             CSLDestroy(papszOpenOptionsCleaned);
3554 
3555 #ifdef OGRAPISPY_ENABLED
3556             if( iSnapshot != INT_MIN )
3557             {
3558                 GDALDatasetH hDS = nullptr;
3559                 OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3560             }
3561 #endif
3562             return nullptr;
3563         }
3564 #endif
3565     }
3566 
3567     CSLDestroy(papszOpenOptionsCleaned);
3568 
3569 #ifdef OGRAPISPY_ENABLED
3570     if( iSnapshot != INT_MIN )
3571     {
3572         GDALDatasetH hDS = nullptr;
3573         OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3574     }
3575 #endif
3576 
3577     if( nOpenFlags & GDAL_OF_VERBOSE_ERROR )
3578     {
3579         // Check to see if there was a filesystem error, and report it if so.
3580         // If not, return a more generic error.
3581         if(!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
3582         {
3583             if( nDriverCount == 0 )
3584             {
3585                 CPLError(CE_Failure, CPLE_OpenFailed,
3586                          "No driver registered.");
3587             }
3588             else if( oOpenInfo.bStatOK )
3589             {
3590                 CPLError(CE_Failure, CPLE_OpenFailed,
3591                          "`%s' not recognized as a supported file format.",
3592                          pszFilename);
3593             }
3594             else
3595             {
3596                 // If Stat failed and no VSI error was set, assume it is because
3597                 // the file did not exist on the filesystem.
3598                 CPLError(CE_Failure, CPLE_OpenFailed,
3599                          "`%s' does not exist in the file system, "
3600                          "and is not recognized as a supported dataset name.",
3601                          pszFilename);
3602             }
3603         }
3604     }
3605 
3606     return nullptr;
3607 }
3608 
3609 /************************************************************************/
3610 /*                           GDALOpenShared()                           */
3611 /************************************************************************/
3612 
3613 /**
3614  * \brief Open a raster file as a GDALDataset.
3615  *
3616  * This function works the same as GDALOpen(), but allows the sharing of
3617  * GDALDataset handles for a dataset with other callers to GDALOpenShared().
3618  *
3619  * In particular, GDALOpenShared() will first consult its list of currently
3620  * open and shared GDALDataset's, and if the GetDescription() name for one
3621  * exactly matches the pszFilename passed to GDALOpenShared() it will be
3622  * referenced and returned.
3623  *
3624  * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
3625  * pszFilename from two different threads, a different GDALDataset object will
3626  * be returned as it is not safe to use the same dataset from different threads,
3627  * unless the user does explicitly use mutexes in its code.
3628  *
3629  * For drivers supporting the VSI virtual file API, it is possible to open a
3630  * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3631  * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3632  * server (see VSIInstallCurlFileHandler())
3633  *
3634  * \sa GDALOpen()
3635  * \sa GDALOpenEx()
3636  *
3637  * @param pszFilename the name of the file to access.  In the case of
3638  * exotic drivers this may not refer to a physical file, but instead contain
3639  * information for the driver on how to access a dataset.  It should be in
3640  * UTF-8 encoding.
3641  *
3642  * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
3643  * drivers support only read only access.
3644  *
3645  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
3646  * this handle can be cast to a GDALDataset *.
3647  */
3648 
3649 GDALDatasetH CPL_STDCALL
GDALOpenShared(const char * pszFilename,GDALAccess eAccess)3650 GDALOpenShared( const char *pszFilename, GDALAccess eAccess )
3651 {
3652     VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
3653     return GDALOpenEx(pszFilename,
3654                       GDAL_OF_RASTER |
3655                           (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
3656                           GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
3657                       nullptr, nullptr, nullptr);
3658 }
3659 
3660 /************************************************************************/
3661 /*                             GDALClose()                              */
3662 /************************************************************************/
3663 
3664 /**
3665  * \brief Close GDAL dataset.
3666  *
3667  * For non-shared datasets (opened with GDALOpen()) the dataset is closed
3668  * using the C++ "delete" operator, recovering all dataset related resources.
3669  * For shared datasets (opened with GDALOpenShared()) the dataset is
3670  * dereferenced, and closed only if the referenced count has dropped below 1.
3671  *
3672  * @param hDS The dataset to close.  May be cast from a "GDALDataset *".
3673  */
3674 
GDALClose(GDALDatasetH hDS)3675 void CPL_STDCALL GDALClose( GDALDatasetH hDS )
3676 
3677 {
3678     if( hDS == nullptr )
3679         return;
3680 
3681 #ifdef OGRAPISPY_ENABLED
3682     if( bOGRAPISpyEnabled )
3683         OGRAPISpyPreClose(hDS);
3684 #endif
3685 
3686     GDALDataset *poDS = GDALDataset::FromHandle(hDS);
3687 
3688     if (poDS->GetShared())
3689     {
3690 /* -------------------------------------------------------------------- */
3691 /*      If this file is in the shared dataset list then dereference     */
3692 /*      it, and only delete/remote it if the reference count has        */
3693 /*      dropped to zero.                                                */
3694 /* -------------------------------------------------------------------- */
3695         if( poDS->Dereference() > 0 )
3696             return;
3697 
3698         delete poDS;
3699 
3700 #ifdef OGRAPISPY_ENABLED
3701         if( bOGRAPISpyEnabled )
3702             OGRAPISpyPostClose();
3703 #endif
3704 
3705         return;
3706     }
3707 
3708 /* -------------------------------------------------------------------- */
3709 /*      This is not shared dataset, so directly delete it.              */
3710 /* -------------------------------------------------------------------- */
3711     delete poDS;
3712 
3713 #ifdef OGRAPISPY_ENABLED
3714     if( bOGRAPISpyEnabled )
3715         OGRAPISpyPostClose();
3716 #endif
3717 }
3718 
3719 /************************************************************************/
3720 /*                        GDALDumpOpenDataset()                         */
3721 /************************************************************************/
3722 
GDALDumpOpenSharedDatasetsForeach(void * elt,void * user_data)3723 static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
3724 {
3725     SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
3726     FILE *fp = static_cast<FILE *>(user_data);
3727     GDALDataset *poDS = psStruct->poDS;
3728 
3729     const char *pszDriverName = poDS->GetDriver() == nullptr
3730                                     ? "DriverIsNULL"
3731                                     : poDS->GetDriver()->GetDescription();
3732 
3733     poDS->Reference();
3734     CPL_IGNORE_RET_VAL(
3735         VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
3736                    poDS->GetShared() ? 'S' : 'N', pszDriverName,
3737                    static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
3738                    poDS->GetRasterYSize(), poDS->GetRasterCount(),
3739                    poDS->GetDescription()));
3740 
3741     return TRUE;
3742 }
3743 
GDALDumpOpenDatasetsForeach(GDALDataset * poDS,FILE * fp)3744 static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
3745 {
3746 
3747     // Don't list shared datasets. They have already been listed by
3748     // GDALDumpOpenSharedDatasetsForeach.
3749     if (poDS->GetShared())
3750         return TRUE;
3751 
3752     const char *pszDriverName = poDS->GetDriver() == nullptr
3753                                     ? "DriverIsNULL"
3754                                     : poDS->GetDriver()->GetDescription();
3755 
3756     poDS->Reference();
3757     CPL_IGNORE_RET_VAL(
3758         VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
3759                    poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
3760                    poDS->GetRasterXSize(), poDS->GetRasterYSize(),
3761                    poDS->GetRasterCount(), poDS->GetDescription()));
3762 
3763     return TRUE;
3764 }
3765 
3766 /**
3767  * \brief List open datasets.
3768  *
3769  * Dumps a list of all open datasets (shared or not) to the indicated
3770  * text file (may be stdout or stderr).   This function is primarily intended
3771  * to assist in debugging "dataset leaks" and reference counting issues.
3772  * The information reported includes the dataset name, referenced count,
3773  * shared status, driver name, size, and band count.
3774  */
3775 
GDALDumpOpenDatasets(FILE * fp)3776 int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp )
3777 
3778 {
3779     VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
3780 
3781     CPLMutexHolderD(&hDLMutex);
3782 
3783     if (poAllDatasetMap == nullptr)
3784         return 0;
3785 
3786     CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
3787 
3788     for( auto oIter: *poAllDatasetMap )
3789     {
3790         GDALDumpOpenDatasetsForeach(oIter.first, fp);
3791     }
3792 
3793     if (phSharedDatasetSet != nullptr)
3794     {
3795         CPLHashSetForeach(phSharedDatasetSet,
3796                           GDALDumpOpenSharedDatasetsForeach, fp);
3797     }
3798     return static_cast<int>(poAllDatasetMap->size());
3799 }
3800 
3801 /************************************************************************/
3802 /*                        BeginAsyncReader()                            */
3803 /************************************************************************/
3804 
3805 /**
3806  * \brief Sets up an asynchronous data request
3807  *
3808  * This method establish an asynchronous raster read request for the
3809  * indicated window on the dataset into the indicated buffer.  The parameters
3810  * for windowing, buffer size, buffer type and buffer organization are similar
3811  * to those for GDALDataset::RasterIO(); however, this call only launches
3812  * the request and filling the buffer is accomplished via calls to
3813  * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
3814  *
3815  * Once all processing for the created session is complete, or if no further
3816  * refinement of the request is required, the GDALAsyncReader object should
3817  * be destroyed with the GDALDataset::EndAsyncReader() method.
3818  *
3819  * Note that the data buffer (pData) will potentially continue to be
3820  * updated as long as the session lives, but it is not deallocated when
3821  * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It
3822  * should be deallocated by the application at that point.
3823  *
3824  * Additional information on asynchronous IO in GDAL may be found at:
3825  *   https://gdal.org/development/rfc/rfc24_progressive_data_support.html
3826  *
3827  * This method is the same as the C GDALBeginAsyncReader() function.
3828  *
3829  * @param nXOff The pixel offset to the top left corner of the region
3830  * of the band to be accessed.  This would be zero to start from the left side.
3831  *
3832  * @param nYOff The line offset to the top left corner of the region
3833  * of the band to be accessed.  This would be zero to start from the top.
3834  *
3835  * @param nXSize The width of the region of the band to be accessed in pixels.
3836  *
3837  * @param nYSize The height of the region of the band to be accessed in lines.
3838  *
3839  * @param pBuf The buffer into which the data should be read. This buffer must
3840  * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
3841  * It is organized in left to right,top to bottom pixel order.  Spacing is
3842  * controlled by the nPixelSpace, and nLineSpace parameters.
3843  *
3844  * @param nBufXSize the width of the buffer image into which the desired region
3845  * is to be read, or from which it is to be written.
3846  *
3847  * @param nBufYSize the height of the buffer image into which the desired
3848  * region is to be read, or from which it is to be written.
3849  *
3850  * @param eBufType the type of the pixel values in the pData data buffer.  The
3851  * pixel values will automatically be translated to/from the GDALRasterBand
3852  * data type as needed.
3853  *
3854  * @param nBandCount the number of bands being read or written.
3855  *
3856  * @param panBandMap the list of nBandCount band numbers being read/written.
3857  * Note band numbers are 1 based.   This may be NULL to select the first
3858  * nBandCount bands.
3859  *
3860  * @param nPixelSpace The byte offset from the start of one pixel value in
3861  * pData to the start of the next pixel value within a scanline.  If defaulted
3862  * (0) the size of the datatype eBufType is used.
3863  *
3864  * @param nLineSpace The byte offset from the start of one scanline in
3865  * pData to the start of the next.  If defaulted the size of the datatype
3866  * eBufType * nBufXSize is used.
3867  *
3868  * @param nBandSpace the byte offset from the start of one bands data to the
3869  * start of the next.  If defaulted (zero) the value will be
3870  * nLineSpace * nBufYSize implying band sequential organization
3871  * of the data buffer.
3872  *
3873  * @param papszOptions Driver specific control options in a string list or NULL.
3874  * Consult driver documentation for options supported.
3875  *
3876  * @return The GDALAsyncReader object representing the request.
3877  */
3878 
BeginAsyncReader(int nXOff,int nYOff,int nXSize,int nYSize,void * pBuf,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,int nPixelSpace,int nLineSpace,int nBandSpace,char ** papszOptions)3879 GDALAsyncReader *GDALDataset::BeginAsyncReader(
3880     int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
3881     int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
3882     int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions )
3883 {
3884     // See gdaldefaultasync.cpp
3885 
3886     return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
3887                                      nBufXSize, nBufYSize, eBufType, nBandCount,
3888                                      panBandMap, nPixelSpace, nLineSpace,
3889                                      nBandSpace, papszOptions);
3890 }
3891 
3892 /************************************************************************/
3893 /*                        GDALBeginAsyncReader()                      */
3894 /************************************************************************/
3895 
3896 /**
3897  * \brief Sets up an asynchronous data request
3898  *
3899  * This method establish an asynchronous raster read request for the
3900  * indicated window on the dataset into the indicated buffer.  The parameters
3901  * for windowing, buffer size, buffer type and buffer organization are similar
3902  * to those for GDALDataset::RasterIO(); however, this call only launches
3903  * the request and filling the buffer is accomplished via calls to
3904  * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
3905  *
3906  * Once all processing for the created session is complete, or if no further
3907  * refinement of the request is required, the GDALAsyncReader object should
3908  * be destroyed with the GDALDataset::EndAsyncReader() method.
3909  *
3910  * Note that the data buffer (pData) will potentially continue to be
3911  * updated as long as the session lives, but it is not deallocated when
3912  * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It
3913  * should be deallocated by the application at that point.
3914  *
3915  * Additional information on asynchronous IO in GDAL may be found at:
3916  *   https://gdal.org/development/rfc/rfc24_progressive_data_support.html
3917  *
3918  * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
3919  *
3920  * @param hDS handle to the dataset object.
3921  *
3922  * @param nXOff The pixel offset to the top left corner of the region
3923  * of the band to be accessed.  This would be zero to start from the left side.
3924  *
3925  * @param nYOff The line offset to the top left corner of the region
3926  * of the band to be accessed.  This would be zero to start from the top.
3927  *
3928  * @param nXSize The width of the region of the band to be accessed in pixels.
3929  *
3930  * @param nYSize The height of the region of the band to be accessed in lines.
3931  *
3932  * @param pBuf The buffer into which the data should be read. This buffer must
3933  * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
3934  * It is organized in left to right,top to bottom pixel order.  Spacing is
3935  * controlled by the nPixelSpace, and nLineSpace parameters.
3936  *
3937  * @param nBufXSize the width of the buffer image into which the desired region
3938  * is to be read, or from which it is to be written.
3939  *
3940  * @param nBufYSize the height of the buffer image into which the desired
3941  * region is to be read, or from which it is to be written.
3942  *
3943  * @param eBufType the type of the pixel values in the pData data buffer.  The
3944  * pixel values will automatically be translated to/from the GDALRasterBand
3945  * data type as needed.
3946  *
3947  * @param nBandCount the number of bands being read or written.
3948  *
3949  * @param panBandMap the list of nBandCount band numbers being read/written.
3950  * Note band numbers are 1 based.   This may be NULL to select the first
3951  * nBandCount bands.
3952  *
3953  * @param nPixelSpace The byte offset from the start of one pixel value in
3954  * pData to the start of the next pixel value within a scanline.  If defaulted
3955  * (0) the size of the datatype eBufType is used.
3956  *
3957  * @param nLineSpace The byte offset from the start of one scanline in
3958  * pData to the start of the next.  If defaulted the size of the datatype
3959  * eBufType * nBufXSize is used.
3960  *
3961  * @param nBandSpace the byte offset from the start of one bands data to the
3962  * start of the next.  If defaulted (zero) the value will be
3963  * nLineSpace * nBufYSize implying band sequential organization
3964  * of the data buffer.
3965  *
3966  * @param papszOptions Driver specific control options in a string list or NULL.
3967  * Consult driver documentation for options supported.
3968  *
3969  * @return handle representing the request.
3970  */
3971 
3972 GDALAsyncReaderH CPL_STDCALL
GDALBeginAsyncReader(GDALDatasetH hDS,int nXOff,int nYOff,int nXSize,int nYSize,void * pBuf,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,int nPixelSpace,int nLineSpace,int nBandSpace,CSLConstList papszOptions)3973 GDALBeginAsyncReader( GDALDatasetH hDS, int nXOff, int nYOff,
3974                       int nXSize, int nYSize,
3975                       void *pBuf,
3976                       int nBufXSize, int nBufYSize,
3977                       GDALDataType eBufType,
3978                       int nBandCount, int* panBandMap,
3979                       int nPixelSpace, int nLineSpace,
3980                       int nBandSpace,
3981                       CSLConstList papszOptions )
3982 
3983 {
3984     VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
3985     return static_cast<GDALAsyncReaderH>(
3986         GDALDataset::FromHandle(hDS)->BeginAsyncReader(
3987             nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
3988             nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
3989             const_cast<char**>(papszOptions)));
3990 }
3991 
3992 /************************************************************************/
3993 /*                        EndAsyncReader()                            */
3994 /************************************************************************/
3995 
3996 /**
3997  * End asynchronous request.
3998  *
3999  * This method destroys an asynchronous io request and recovers all
4000  * resources associated with it.
4001  *
4002  * This method is the same as the C function GDALEndAsyncReader().
4003  *
4004  * @param poARIO pointer to a GDALAsyncReader
4005  */
4006 
EndAsyncReader(GDALAsyncReader * poARIO)4007 void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO) { delete poARIO; }
4008 
4009 /************************************************************************/
4010 /*                        GDALEndAsyncReader()                        */
4011 /************************************************************************/
4012 
4013 /**
4014  * End asynchronous request.
4015  *
4016  * This method destroys an asynchronous io request and recovers all
4017  * resources associated with it.
4018  *
4019  * This method is the same as the C++ method GDALDataset::EndAsyncReader().
4020  *
4021  * @param hDS handle to the dataset object.
4022  * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
4023  */
4024 
GDALEndAsyncReader(GDALDatasetH hDS,GDALAsyncReaderH hAsyncReaderH)4025 void CPL_STDCALL GDALEndAsyncReader( GDALDatasetH hDS,
4026                                      GDALAsyncReaderH hAsyncReaderH )
4027 {
4028     VALIDATE_POINTER0(hDS, "GDALDataset");
4029     VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
4030     GDALDataset::FromHandle(hDS)
4031         ->EndAsyncReader(static_cast<GDALAsyncReader *>(hAsyncReaderH));
4032 }
4033 
4034 /************************************************************************/
4035 /*                       CloseDependentDatasets()                       */
4036 /************************************************************************/
4037 
4038 /**
4039  * Drop references to any other datasets referenced by this dataset.
4040  *
4041  * This method should release any reference to other datasets (e.g. a VRT
4042  * dataset to its sources), but not close the current dataset itself.
4043  *
4044  * If at least, one reference to a dependent dataset has been dropped,
4045  * this method should return TRUE. Otherwise it *should* return FALSE.
4046  * (Failure to return the proper value might result in infinite loop)
4047  *
4048  * This method can be called several times on a given dataset. After
4049  * the first time, it should not do anything and return FALSE.
4050  *
4051  * The driver implementation may choose to destroy its raster bands,
4052  * so be careful not to call any method on the raster bands afterwards.
4053  *
4054  * Basically the only safe action you can do after calling
4055  * CloseDependentDatasets() is to call the destructor.
4056  *
4057  * Note: the only legitimate caller of CloseDependentDatasets() is
4058  * GDALDriverManager::~GDALDriverManager()
4059  *
4060  * @return TRUE if at least one reference to another dataset has been dropped.
4061  */
CloseDependentDatasets()4062 int GDALDataset::CloseDependentDatasets()
4063 {
4064     return oOvManager.CloseDependentDatasets();
4065 }
4066 
4067 /************************************************************************/
4068 /*                            ReportError()                             */
4069 /************************************************************************/
4070 
4071 #ifndef DOXYGEN_XML
4072 /**
4073  * \brief Emits an error related to a dataset.
4074  *
4075  * This function is a wrapper for regular CPLError(). The only difference
4076  * with CPLError() is that it prepends the error message with the dataset
4077  * name.
4078  *
4079  * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4080  * @param err_no the error number (CPLE_*) from cpl_error.h.
4081  * @param fmt a printf() style format string.  Any additional arguments
4082  * will be treated as arguments to fill in this format in a manner
4083  * similar to printf().
4084  *
4085  * @since GDAL 1.9.0
4086  */
4087 
ReportError(CPLErr eErrClass,CPLErrorNum err_no,const char * fmt,...)4088 void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4089                               const char *fmt, ...)
4090 {
4091     va_list args;
4092     va_start(args, fmt);
4093     ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4094     va_end(args);
4095 }
4096 
4097 /**
4098  * \brief Emits an error related to a dataset (static method)
4099  *
4100  * This function is a wrapper for regular CPLError(). The only difference
4101  * with CPLError() is that it prepends the error message with the dataset
4102  * name.
4103  *
4104  * @param pszDSName dataset name.
4105  * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4106  * @param err_no the error number (CPLE_*) from cpl_error.h.
4107  * @param fmt a printf() style format string.  Any additional arguments
4108  * will be treated as arguments to fill in this format in a manner
4109  * similar to printf().
4110  *
4111  * @since GDAL 3.2.0
4112  */
4113 
ReportError(const char * pszDSName,CPLErr eErrClass,CPLErrorNum err_no,const char * fmt,...)4114 void GDALDataset::ReportError(const char* pszDSName,
4115                               CPLErr eErrClass, CPLErrorNum err_no,
4116                               const char *fmt, ...)
4117 {
4118     va_list args;
4119     va_start(args, fmt);
4120     ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4121     va_end(args);
4122 }
4123 
ReportErrorV(const char * pszDSName,CPLErr eErrClass,CPLErrorNum err_no,const char * fmt,va_list args)4124 void GDALDataset::ReportErrorV(const char* pszDSName,
4125                                CPLErr eErrClass, CPLErrorNum err_no,
4126                                const char *fmt, va_list args)
4127 {
4128     char szNewFmt[256] = {};
4129     if (strlen(fmt) + strlen(pszDSName) + 3 >= sizeof(szNewFmt) - 1)
4130         pszDSName = CPLGetFilename(pszDSName);
4131     if (pszDSName[0] != '\0' && strchr(pszDSName, '%') == nullptr &&
4132         strlen(fmt) + strlen(pszDSName) + 3 < sizeof(szNewFmt) - 1)
4133     {
4134         snprintf(szNewFmt, sizeof(szNewFmt), "%s: %s", pszDSName, fmt);
4135         CPLErrorV(eErrClass, err_no, szNewFmt, args);
4136     }
4137     else
4138     {
4139         CPLErrorV(eErrClass, err_no, fmt, args);
4140     }
4141 }
4142 #endif
4143 
4144 /************************************************************************/
4145 /*                            GetMetadata()                             */
4146 /************************************************************************/
GetMetadata(const char * pszDomain)4147 char **GDALDataset::GetMetadata(const char *pszDomain)
4148 {
4149     if( pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS") )
4150     {
4151         oDerivedMetadataList.Clear();
4152 
4153         // First condition: at least one raster band.
4154         if(GetRasterCount() > 0)
4155         {
4156             // Check if there is at least one complex band.
4157             bool hasAComplexBand = false;
4158 
4159             for(int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4160             {
4161                 if(GDALDataTypeIsComplex(
4162                        GetRasterBand(rasterId)->GetRasterDataType()))
4163                 {
4164                     hasAComplexBand = true;
4165                     break;
4166                 }
4167             }
4168 
4169             unsigned int nbSupportedDerivedDS = 0;
4170             const DerivedDatasetDescription *poDDSDesc =
4171                 GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4172 
4173             int nNumDataset = 1;
4174             for(unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4175                 ++derivedId)
4176             {
4177                 if(hasAComplexBand ||
4178                    CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4179                        "complex")
4180                 {
4181                     oDerivedMetadataList.SetNameValue(
4182                         CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4183                         CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4184                                    poDDSDesc[derivedId].pszDatasetName,
4185                                    GetDescription()));
4186 
4187                     CPLString osDesc(
4188                         CPLSPrintf("%s from %s",
4189                                    poDDSDesc[derivedId].pszDatasetDescription,
4190                                    GetDescription()));
4191                     oDerivedMetadataList.SetNameValue(
4192                         CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4193                         osDesc.c_str());
4194 
4195                     nNumDataset++;
4196                 }
4197             }
4198         }
4199         return oDerivedMetadataList.List();
4200     }
4201 
4202     return GDALMajorObject::GetMetadata(pszDomain);
4203 }
4204 
4205 /**
4206  * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
4207  * \brief Set metadata.
4208  *
4209  * CAUTION: depending on the format, older values of the updated information
4210  * might still be found in the file in a "ghost" state, even if no longer
4211  * accessible through the GDAL API. This is for example the case of the GTiff
4212  * format (this is not a exhaustive list)
4213  *
4214  * The C function GDALSetMetadata() does the same thing as this method.
4215  *
4216  * @param papszMetadata the metadata in name=value string list format to
4217  * apply.
4218  * @param pszDomain the domain of interest.  Use "" or NULL for the default
4219  * domain.
4220  * @return CE_None on success, CE_Failure on failure and CE_Warning if the
4221  * metadata has been accepted, but is likely not maintained persistently
4222  * by the underlying object between sessions.
4223  */
4224 
4225 /**
4226  * \fn GDALDataset::SetMetadataItem( const char * pszName, const char *
4227  * pszValue, const char * pszDomain)
4228  * \brief Set single metadata item.
4229  *
4230  * CAUTION: depending on the format, older values of the updated information
4231  * might still be found in the file in a "ghost" state, even if no longer
4232  * accessible through the GDAL API. This is for example the case of the GTiff
4233  * format (this is not a exhaustive list)
4234  *
4235  * The C function GDALSetMetadataItem() does the same thing as this method.
4236  *
4237  * @param pszName the key for the metadata item to fetch.
4238  * @param pszValue the value to assign to the key.
4239  * @param pszDomain the domain to set within, use NULL for the default domain.
4240  *
4241  * @return CE_None on success, or an error code on failure.
4242  */
4243 
4244 /************************************************************************/
4245 /*                            GetMetadataDomainList()                   */
4246 /************************************************************************/
4247 
GetMetadataDomainList()4248 char **GDALDataset::GetMetadataDomainList()
4249 {
4250     char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
4251 
4252     // Ensure that we do not duplicate DERIVED domain.
4253     if(GetRasterCount() > 0 &&
4254        CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
4255     {
4256         currentDomainList =
4257             CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
4258     }
4259     return currentDomainList;
4260 }
4261 
4262 /************************************************************************/
4263 /*                            GetDriverName()                           */
4264 /************************************************************************/
4265 
4266 /** Return driver name.
4267  * @return driver name.
4268  */
GetDriverName()4269 const char *GDALDataset::GetDriverName()
4270 {
4271     if( poDriver )
4272         return poDriver->GetDescription();
4273     return "";
4274 }
4275 
4276 /************************************************************************/
4277 /*                     GDALDatasetReleaseResultSet()                    */
4278 /************************************************************************/
4279 
4280 /**
4281  \brief Release results of ExecuteSQL().
4282 
4283  This function should only be used to deallocate OGRLayers resulting from
4284  an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
4285  results set before destroying the GDALDataset may cause errors.
4286 
4287  This function is the same as the C++ method GDALDataset::ReleaseResultSet()
4288 
4289  @since GDAL 2.0
4290 
4291  @param hDS the dataset handle.
4292  @param hLayer the result of a previous ExecuteSQL() call.
4293 
4294 */
GDALDatasetReleaseResultSet(GDALDatasetH hDS,OGRLayerH hLayer)4295 void GDALDatasetReleaseResultSet( GDALDatasetH hDS, OGRLayerH hLayer )
4296 
4297 {
4298     VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
4299 
4300 #ifdef OGRAPISPY_ENABLED
4301     if( bOGRAPISpyEnabled )
4302         OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
4303 #endif
4304 
4305     GDALDataset::FromHandle(hDS)
4306         ->ReleaseResultSet(OGRLayer::FromHandle(hLayer));
4307 }
4308 
4309 /************************************************************************/
4310 /*                       GDALDatasetGetLayerCount()                     */
4311 /************************************************************************/
4312 
4313 /**
4314  \brief Get the number of layers in this dataset.
4315 
4316  This function is the same as the C++ method GDALDataset::GetLayerCount()
4317 
4318  @since GDAL 2.0
4319 
4320  @param hDS the dataset handle.
4321  @return layer count.
4322 */
4323 
GDALDatasetGetLayerCount(GDALDatasetH hDS)4324 int GDALDatasetGetLayerCount( GDALDatasetH hDS )
4325 
4326 {
4327     VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
4328 
4329 #ifdef OGRAPISPY_ENABLED
4330     if( bOGRAPISpyEnabled )
4331         OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
4332 #endif
4333 
4334     return GDALDataset::FromHandle(hDS)->GetLayerCount();
4335 }
4336 
4337 /************************************************************************/
4338 /*                        GDALDatasetGetLayer()                         */
4339 /************************************************************************/
4340 
4341 /**
4342  \brief Fetch a layer by index.
4343 
4344  The returned layer remains owned by the
4345  GDALDataset and should not be deleted by the application.
4346 
4347  This function is the same as the C++ method GDALDataset::GetLayer()
4348 
4349  @since GDAL 2.0
4350 
4351  @param hDS the dataset handle.
4352  @param iLayer a layer number between 0 and GetLayerCount()-1.
4353 
4354  @return the layer, or NULL if iLayer is out of range or an error occurs.
4355 */
4356 
GDALDatasetGetLayer(GDALDatasetH hDS,int iLayer)4357 OGRLayerH GDALDatasetGetLayer( GDALDatasetH hDS, int iLayer )
4358 
4359 {
4360     VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
4361 
4362     OGRLayerH hLayer = OGRLayer::ToHandle(
4363         GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
4364 
4365 #ifdef OGRAPISPY_ENABLED
4366     if( bOGRAPISpyEnabled )
4367         OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
4368 #endif
4369 
4370     return hLayer;
4371 }
4372 
4373 /************************************************************************/
4374 /*                     GDALDatasetGetLayerByName()                      */
4375 /************************************************************************/
4376 
4377 /**
4378  \brief Fetch a layer by name.
4379 
4380  The returned layer remains owned by the
4381  GDALDataset and should not be deleted by the application.
4382 
4383  This function is the same as the C++ method GDALDataset::GetLayerByName()
4384 
4385  @since GDAL 2.0
4386 
4387  @param hDS the dataset handle.
4388  @param pszName the layer name of the layer to fetch.
4389 
4390  @return the layer, or NULL if Layer is not found or an error occurs.
4391 */
4392 
GDALDatasetGetLayerByName(GDALDatasetH hDS,const char * pszName)4393 OGRLayerH GDALDatasetGetLayerByName( GDALDatasetH hDS, const char *pszName )
4394 
4395 {
4396     VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
4397 
4398     OGRLayerH hLayer = OGRLayer::ToHandle(
4399         GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
4400 
4401 #ifdef OGRAPISPY_ENABLED
4402     if( bOGRAPISpyEnabled )
4403         OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
4404 #endif
4405 
4406     return hLayer;
4407 }
4408 
4409 /************************************************************************/
4410 /*                        GDALDatasetDeleteLayer()                      */
4411 /************************************************************************/
4412 
4413 /**
4414  \brief Delete the indicated layer from the datasource.
4415 
4416  If this function is supported
4417  the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
4418 
4419  This method is the same as the C++ method GDALDataset::DeleteLayer().
4420 
4421  @since GDAL 2.0
4422 
4423  @param hDS the dataset handle.
4424  @param iLayer the index of the layer to delete.
4425 
4426  @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
4427  layers is not supported for this datasource.
4428 
4429 */
GDALDatasetDeleteLayer(GDALDatasetH hDS,int iLayer)4430 OGRErr GDALDatasetDeleteLayer( GDALDatasetH hDS, int iLayer )
4431 
4432 {
4433     VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
4434 
4435     return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
4436 }
4437 
4438 /************************************************************************/
4439 /*                            CreateLayer()                             */
4440 /************************************************************************/
4441 
4442 /**
4443 \brief This method attempts to create a new layer on the dataset with the
4444 indicated name, coordinate system, geometry type.
4445 
4446 The papszOptions argument
4447 can be used to control driver specific creation options.  These options are
4448 normally documented in the format specific documentation.
4449 
4450 In GDAL 2.0, drivers should extend the ICreateLayer() method and not
4451 CreateLayer().  CreateLayer() adds validation of layer creation options, before
4452 delegating the actual work to ICreateLayer().
4453 
4454 This method is the same as the C function GDALDatasetCreateLayer() and the
4455 deprecated OGR_DS_CreateLayer().
4456 
4457 In GDAL 1.X, this method used to be in the OGRDataSource class.
4458 
4459 Example:
4460 
4461 \code{.cpp}
4462 #include "gdal.h"
4463 #include "cpl_string.h"
4464 
4465 ...
4466 
4467         OGRLayer *poLayer;
4468         char     **papszOptions;
4469 
4470         if( !poDS->TestCapability( ODsCCreateLayer ) )
4471         {
4472         ...
4473         }
4474 
4475         papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
4476         poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
4477                                      papszOptions );
4478         CSLDestroy( papszOptions );
4479 
4480         if( poLayer == NULL )
4481         {
4482             ...
4483         }
4484 \endcode
4485 
4486 @param pszName the name for the new layer.  This should ideally not
4487 match any existing layer on the datasource.
4488 @param poSpatialRef the coordinate system to use for the new layer, or NULL if
4489 no coordinate system is available.  The driver might only increase
4490 the reference counter of the object to take ownership, and not make a full copy,
4491 so do not use OSRDestroySpatialReference(), but OSRRelease() instead when you
4492 are done with the object.
4493 @param eGType the geometry type for the layer.  Use wkbUnknown if there
4494 are no constraints on the types geometry to be written.
4495 @param papszOptions a StringList of name=value options.  Options are driver
4496 specific.
4497 
4498 @return NULL is returned on failure, or a new OGRLayer handle on success.
4499 
4500 */
4501 
CreateLayer(const char * pszName,OGRSpatialReference * poSpatialRef,OGRwkbGeometryType eGType,char ** papszOptions)4502 OGRLayer *GDALDataset::CreateLayer( const char * pszName,
4503                                       OGRSpatialReference * poSpatialRef,
4504                                       OGRwkbGeometryType eGType,
4505                                       char **papszOptions )
4506 
4507 {
4508     ValidateLayerCreationOptions(papszOptions);
4509 
4510     if( OGR_GT_IsNonLinear(eGType) && !TestCapability(ODsCCurveGeometries) )
4511     {
4512         eGType = OGR_GT_GetLinear(eGType);
4513     }
4514 
4515     OGRLayer *poLayer =
4516         ICreateLayer(pszName, poSpatialRef, eGType, papszOptions);
4517 #ifdef DEBUG
4518     if( poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
4519         !poLayer->TestCapability(OLCCurveGeometries) )
4520     {
4521         CPLError(CE_Warning, CPLE_AppDefined,
4522                  "Inconsistent driver: Layer geometry type is non-linear, but "
4523                  "TestCapability(OLCCurveGeometries) returns FALSE.");
4524     }
4525 #endif
4526 
4527     return poLayer;
4528 }
4529 
4530 /************************************************************************/
4531 /*                         GDALDatasetCreateLayer()                     */
4532 /************************************************************************/
4533 
4534 /**
4535 \brief This function attempts to create a new layer on the dataset with the
4536 indicated name, coordinate system, geometry type.
4537 
4538 The papszOptions argument can be used to control driver specific creation
4539 options.  These options are normally documented in the format specific
4540 documentation.
4541 
4542 This method is the same as the C++ method GDALDataset::CreateLayer().
4543 
4544 Example:
4545 
4546 \code{.c}
4547 #include "gdal.h"
4548 #include "cpl_string.h"
4549 
4550 ...
4551 
4552         OGRLayerH  hLayer;
4553         char     **papszOptions;
4554 
4555         if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
4556         {
4557         ...
4558         }
4559 
4560         papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
4561         hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
4562                                          papszOptions );
4563         CSLDestroy( papszOptions );
4564 
4565         if( hLayer == NULL )
4566         {
4567             ...
4568         }
4569 \endcode
4570 
4571 @since GDAL 2.0
4572 
4573 @param hDS the dataset handle
4574 @param pszName the name for the new layer.  This should ideally not
4575 match any existing layer on the datasource.
4576 @param hSpatialRef the coordinate system to use for the new layer, or NULL if
4577 no coordinate system is available.  The driver might only increase
4578 the reference counter of the object to take ownership, and not make a full copy,
4579 so do not use OSRDestroySpatialReference(), but OSRRelease() instead when you
4580 are done with the object.
4581 @param eGType the geometry type for the layer.  Use wkbUnknown if there
4582 are no constraints on the types geometry to be written.
4583 @param papszOptions a StringList of name=value options.  Options are driver
4584 specific.
4585 
4586 @return NULL is returned on failure, or a new OGRLayer handle on success.
4587 
4588 */
4589 
GDALDatasetCreateLayer(GDALDatasetH hDS,const char * pszName,OGRSpatialReferenceH hSpatialRef,OGRwkbGeometryType eGType,CSLConstList papszOptions)4590 OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS,
4591                               const char * pszName,
4592                               OGRSpatialReferenceH hSpatialRef,
4593                               OGRwkbGeometryType eGType,
4594                               CSLConstList papszOptions )
4595 
4596 {
4597     VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
4598 
4599     if (pszName == nullptr)
4600     {
4601         CPLError(CE_Failure, CPLE_ObjectNull,
4602                  "Name was NULL in GDALDatasetCreateLayer");
4603         return nullptr;
4604     }
4605 
4606     OGRLayerH hLayer = OGRLayer::ToHandle(
4607         GDALDataset::FromHandle(hDS)->CreateLayer(
4608             pszName, OGRSpatialReference::FromHandle(hSpatialRef),
4609             eGType, const_cast<char**>(papszOptions)));
4610 
4611 #ifdef OGRAPISPY_ENABLED
4612     if( bOGRAPISpyEnabled )
4613         OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType, const_cast<char**>(papszOptions), hLayer);
4614 #endif
4615 
4616     return hLayer;
4617 }
4618 
4619 /************************************************************************/
4620 /*                         GDALDatasetCopyLayer()                       */
4621 /************************************************************************/
4622 
4623 /**
4624  \brief Duplicate an existing layer.
4625 
4626  This function creates a new layer, duplicate the field definitions of the
4627  source layer and then duplicate each features of the source layer.
4628  The papszOptions argument
4629  can be used to control driver specific creation options.  These options are
4630  normally documented in the format specific documentation.
4631  The source layer may come from another dataset.
4632 
4633  This method is the same as the C++ method GDALDataset::CopyLayer()
4634 
4635  @since GDAL 2.0
4636 
4637  @param hDS the dataset handle.
4638  @param hSrcLayer source layer.
4639  @param pszNewName the name of the layer to create.
4640  @param papszOptions a StringList of name=value options.  Options are driver
4641                      specific.
4642 
4643  @return a handle to the layer, or NULL if an error occurs.
4644 */
GDALDatasetCopyLayer(GDALDatasetH hDS,OGRLayerH hSrcLayer,const char * pszNewName,CSLConstList papszOptions)4645 OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS,
4646                                 OGRLayerH hSrcLayer, const char *pszNewName,
4647                                 CSLConstList papszOptions )
4648 
4649 {
4650     VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
4651     VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
4652     VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
4653 
4654     return OGRLayer::ToHandle(
4655         GDALDataset::FromHandle(hDS)->CopyLayer(
4656             OGRLayer::FromHandle(hSrcLayer), pszNewName,
4657             const_cast<char**>(papszOptions)));
4658 }
4659 
4660 /************************************************************************/
4661 /*                        GDALDatasetExecuteSQL()                       */
4662 /************************************************************************/
4663 
4664 /**
4665  \brief Execute an SQL statement against the data store.
4666 
4667  The result of an SQL query is either NULL for statements that are in error,
4668  or that have no results set, or an OGRLayer pointer representing a results
4669  set from the query.  Note that this OGRLayer is in addition to the layers
4670  in the data store and must be destroyed with
4671  ReleaseResultSet() before the dataset is closed
4672  (destroyed).
4673 
4674  This method is the same as the C++ method GDALDataset::ExecuteSQL()
4675 
4676  For more information on the SQL dialect supported internally by OGR
4677  review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a> document.  Some drivers (i.e.
4678  Oracle and PostGIS) pass the SQL directly through to the underlying RDBMS.
4679 
4680  Starting with OGR 1.10, the <a href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a>
4681  can also be used.
4682 
4683  @since GDAL 2.0
4684 
4685  @param hDS the dataset handle.
4686  @param pszStatement the SQL statement to execute.
4687  @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
4688 
4689  @param pszDialect allows control of the statement dialect. If set to NULL, the
4690  OGR SQL engine will be used, except for RDBMS drivers that will use their
4691  dedicated SQL engine, unless OGRSQL is explicitly passed as the
4692  dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
4693 
4694  @return an OGRLayer containing the results of the query.  Deallocate with
4695  GDALDatasetReleaseResultSet().
4696 
4697 */
4698 
GDALDatasetExecuteSQL(GDALDatasetH hDS,const char * pszStatement,OGRGeometryH hSpatialFilter,const char * pszDialect)4699 OGRLayerH GDALDatasetExecuteSQL( GDALDatasetH hDS,
4700                              const char *pszStatement,
4701                              OGRGeometryH hSpatialFilter,
4702                              const char *pszDialect )
4703 
4704 {
4705     VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
4706 
4707     OGRLayerH hLayer = OGRLayer::ToHandle(
4708         GDALDataset::FromHandle(hDS)->ExecuteSQL(
4709             pszStatement, OGRGeometry::FromHandle(hSpatialFilter),
4710             pszDialect));
4711 
4712 #ifdef OGRAPISPY_ENABLED
4713     if( bOGRAPISpyEnabled )
4714         OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect, hLayer);
4715 #endif
4716 
4717     return hLayer;
4718 }
4719 
4720 
4721 /************************************************************************/
4722 /*                        GDALDatasetAbortSQL()                         */
4723 /************************************************************************/
4724 
4725 /**
4726  \brief Abort any SQL statement running in the data store.
4727 
4728  This function can be safely called from any thread (pending that the dataset object is still alive). Driver implementations will make sure that it can be called in a thread-safe way.
4729 
4730  This might not be implemented by all drivers. At time of writing, only SQLite, GPKG and PG drivers implement it
4731 
4732  This method is the same as the C++ method GDALDataset::AbortSQL()
4733 
4734  @since GDAL 3.2.0
4735 
4736  @param hDS the dataset handle.
4737 
4738  @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
4739  is not supported for this datasource. .
4740 
4741 */
4742 
GDALDatasetAbortSQL(GDALDatasetH hDS)4743 OGRErr GDALDatasetAbortSQL( GDALDatasetH hDS )
4744 
4745 {
4746     VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE );
4747     return GDALDataset::FromHandle(hDS)->AbortSQL();
4748 }
4749 
4750 
4751 /************************************************************************/
4752 /*                      GDALDatasetGetStyleTable()                      */
4753 /************************************************************************/
4754 
4755 /**
4756  \brief Returns dataset style table.
4757 
4758  This function is the same as the C++ method GDALDataset::GetStyleTable()
4759 
4760  @since GDAL 2.0
4761 
4762  @param hDS the dataset handle
4763  @return handle to a style table which should not be modified or freed by the
4764  caller.
4765 */
4766 
GDALDatasetGetStyleTable(GDALDatasetH hDS)4767 OGRStyleTableH GDALDatasetGetStyleTable( GDALDatasetH hDS )
4768 
4769 {
4770     VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
4771 
4772     return reinterpret_cast<OGRStyleTableH>(
4773         GDALDataset::FromHandle(hDS)->GetStyleTable());
4774 }
4775 
4776 /************************************************************************/
4777 /*                    GDALDatasetSetStyleTableDirectly()                */
4778 /************************************************************************/
4779 
4780 /**
4781  \brief Set dataset style table.
4782 
4783  This function operate exactly as GDALDatasetSetStyleTable() except that it
4784  assumes ownership of the passed table.
4785 
4786  This function is the same as the C++ method
4787  GDALDataset::SetStyleTableDirectly()
4788 
4789  @since GDAL 2.0
4790 
4791  @param hDS the dataset handle
4792  @param hStyleTable style table handle to set
4793 
4794 */
4795 
GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,OGRStyleTableH hStyleTable)4796 void GDALDatasetSetStyleTableDirectly( GDALDatasetH hDS,
4797                                        OGRStyleTableH hStyleTable )
4798 
4799 {
4800     VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
4801 
4802     GDALDataset::FromHandle(hDS)
4803         ->SetStyleTableDirectly(reinterpret_cast<OGRStyleTable *>(hStyleTable));
4804 }
4805 
4806 /************************************************************************/
4807 /*                     GDALDatasetSetStyleTable()                       */
4808 /************************************************************************/
4809 
4810 /**
4811  \brief Set dataset style table.
4812 
4813  This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
4814  it assumes ownership of the passed table.
4815 
4816  This function is the same as the C++ method GDALDataset::SetStyleTable()
4817 
4818  @since GDAL 2.0
4819 
4820  @param hDS the dataset handle
4821  @param hStyleTable style table handle to set
4822 
4823 */
4824 
GDALDatasetSetStyleTable(GDALDatasetH hDS,OGRStyleTableH hStyleTable)4825 void GDALDatasetSetStyleTable( GDALDatasetH hDS, OGRStyleTableH hStyleTable )
4826 
4827 {
4828     VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
4829     VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
4830 
4831     GDALDataset::FromHandle(hDS)
4832         ->SetStyleTable(reinterpret_cast<OGRStyleTable *>(hStyleTable));
4833 }
4834 
4835 /************************************************************************/
4836 /*                    ValidateLayerCreationOptions()                    */
4837 /************************************************************************/
4838 
4839 //! @cond Doxygen_Suppress
ValidateLayerCreationOptions(const char * const * papszLCO)4840 int GDALDataset::ValidateLayerCreationOptions( const char* const* papszLCO )
4841 {
4842     const char *pszOptionList =
4843         GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
4844     if( pszOptionList == nullptr && poDriver != nullptr )
4845     {
4846         pszOptionList =
4847             poDriver->GetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST );
4848     }
4849     CPLString osDataset;
4850     osDataset.Printf("dataset %s", GetDescription());
4851     return GDALValidateOptions(pszOptionList, papszLCO,
4852                                "layer creation option",
4853                                osDataset);
4854 }
4855 //! @endcond
4856 
4857 /************************************************************************/
4858 /*                              Release()                               */
4859 /************************************************************************/
4860 
4861 /**
4862 \brief Drop a reference to this dataset, and if the reference count drops to one
4863 close (destroy) the dataset.
4864 
4865 This method is the same as the C function OGRReleaseDataSource().
4866 
4867 @deprecated. In GDAL 2, use GDALClose() instead
4868 
4869 @return OGRERR_NONE on success or an error code.
4870 */
4871 
Release()4872 OGRErr GDALDataset::Release()
4873 
4874 {
4875     ReleaseRef();
4876     return OGRERR_NONE;
4877 }
4878 
4879 /************************************************************************/
4880 /*                            GetRefCount()                             */
4881 /************************************************************************/
4882 
4883 /**
4884 \brief Fetch reference count.
4885 
4886 This method is the same as the C function OGR_DS_GetRefCount().
4887 
4888 In GDAL 1.X, this method used to be in the OGRDataSource class.
4889 
4890 @return the current reference count for the datasource object itself.
4891 */
4892 
GetRefCount() const4893 int GDALDataset::GetRefCount() const { return nRefCount; }
4894 
4895 /************************************************************************/
4896 /*                         GetSummaryRefCount()                         */
4897 /************************************************************************/
4898 
4899 /**
4900 \brief Fetch reference count of datasource and all owned layers.
4901 
4902 This method is the same as the C function  OGR_DS_GetSummaryRefCount().
4903 
4904 In GDAL 1.X, this method used to be in the OGRDataSource class.
4905 
4906 @deprecated
4907 
4908 @return the current summary reference count for the datasource and its layers.
4909 */
4910 
GetSummaryRefCount() const4911 int GDALDataset::GetSummaryRefCount() const
4912 
4913 {
4914     CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
4915     int nSummaryCount = nRefCount;
4916     GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
4917 
4918     for( int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer )
4919         nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
4920 
4921     return nSummaryCount;
4922 }
4923 
4924 /************************************************************************/
4925 /*                           ICreateLayer()                             */
4926 /************************************************************************/
4927 
4928 /**
4929  \brief This method attempts to create a new layer on the dataset with the
4930  indicated name, coordinate system, geometry type.
4931 
4932  This method is reserved to implementation by drivers.
4933 
4934  The papszOptions argument can be used to control driver specific creation
4935  options.  These options are normally documented in the format specific
4936  documentation.
4937 
4938  @param pszName the name for the new layer.  This should ideally not
4939  match any existing layer on the datasource.
4940  @param poSpatialRef the coordinate system to use for the new layer, or NULL if
4941  no coordinate system is available.
4942  @param eGType the geometry type for the layer.  Use wkbUnknown if there
4943  are no constraints on the types geometry to be written.
4944  @param papszOptions a StringList of name=value options.  Options are driver
4945  specific.
4946 
4947  @return NULL is returned on failure, or a new OGRLayer handle on success.
4948 
4949  @since GDAL 2.0
4950 */
4951 
ICreateLayer(CPL_UNUSED const char * pszName,CPL_UNUSED OGRSpatialReference * poSpatialRef,CPL_UNUSED OGRwkbGeometryType eGType,CPL_UNUSED char ** papszOptions)4952 OGRLayer *GDALDataset::ICreateLayer( CPL_UNUSED const char * pszName,
4953                                      CPL_UNUSED OGRSpatialReference * poSpatialRef,
4954                                      CPL_UNUSED OGRwkbGeometryType eGType,
4955                                      CPL_UNUSED char ** papszOptions )
4956 
4957 {
4958     CPLError(CE_Failure, CPLE_NotSupported,
4959              "CreateLayer() not supported by this dataset.");
4960 
4961     return nullptr;
4962 }
4963 
4964 /************************************************************************/
4965 /*                             CopyLayer()                              */
4966 /************************************************************************/
4967 
4968 /**
4969  \brief Duplicate an existing layer.
4970 
4971  This method creates a new layer, duplicate the field definitions of the
4972  source layer and then duplicate each features of the source layer.
4973  The papszOptions argument
4974  can be used to control driver specific creation options.  These options are
4975  normally documented in the format specific documentation.
4976  The source layer may come from another dataset.
4977 
4978  This method is the same as the C function GDALDatasetCopyLayer() and the
4979  deprecated OGR_DS_CopyLayer().
4980 
4981  In GDAL 1.X, this method used to be in the OGRDataSource class.
4982 
4983  @param poSrcLayer source layer.
4984  @param pszNewName the name of the layer to create.
4985  @param papszOptions a StringList of name=value options.  Options are driver
4986                      specific. There is a common option to set output layer
4987                      spatial reference: DST_SRSWKT. The option should be in
4988                      WKT format.
4989 
4990  @return a handle to the layer, or NULL if an error occurs.
4991 */
4992 
CopyLayer(OGRLayer * poSrcLayer,const char * pszNewName,char ** papszOptions)4993 OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
4994                                   const char *pszNewName,
4995                                   char **papszOptions )
4996 
4997 {
4998 /* -------------------------------------------------------------------- */
4999 /*      Create the layer.                                               */
5000 /* -------------------------------------------------------------------- */
5001     if( !TestCapability( ODsCCreateLayer ) )
5002     {
5003         CPLError(CE_Failure, CPLE_NotSupported,
5004                  "This datasource does not support creation of layers.");
5005         return nullptr;
5006     }
5007 
5008     const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
5009     OGRSpatialReference oDstSpaRef(pszSRSWKT);
5010     oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5011     OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
5012     OGRLayer *poDstLayer = nullptr;
5013 
5014     CPLErrorReset();
5015     if( poSrcDefn->GetGeomFieldCount() > 1 &&
5016         TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
5017     {
5018         poDstLayer = ICreateLayer(pszNewName, nullptr, wkbNone, papszOptions);
5019     }
5020     else
5021     {
5022         if(nullptr == pszSRSWKT)
5023         {
5024             poDstLayer = ICreateLayer(pszNewName, poSrcLayer->GetSpatialRef(),
5025                                       poSrcDefn->GetGeomType(), papszOptions);
5026         }
5027         else
5028         {
5029             // Remove DST_WKT from option list to prevent warning from driver.
5030             const int nSRSPos = CSLFindName(papszOptions, "DST_SRSWKT");
5031             CPLStringList aosOptionsWithoutDstSRSWKT(
5032                 CSLRemoveStrings(CSLDuplicate(papszOptions), nSRSPos, 1, nullptr));
5033             poDstLayer = ICreateLayer(pszNewName, &oDstSpaRef,
5034                                       poSrcDefn->GetGeomType(),
5035                                       aosOptionsWithoutDstSRSWKT.List());
5036         }
5037     }
5038 
5039     if( poDstLayer == nullptr )
5040         return nullptr;
5041 
5042 /* -------------------------------------------------------------------- */
5043 /*      Add fields.  Default to copy all fields, and make sure to       */
5044 /*      establish a mapping between indices, rather than names, in      */
5045 /*      case the target datasource has altered it (e.g. Shapefile       */
5046 /*      limited to 10 char field names).                                */
5047 /* -------------------------------------------------------------------- */
5048     const int nSrcFieldCount = poSrcDefn->GetFieldCount();
5049 
5050     // Initialize the index-to-index map to -1's.
5051     int *panMap = static_cast<int *>(CPLMalloc(sizeof(int) * nSrcFieldCount));
5052     for( int iField = 0; iField < nSrcFieldCount; ++iField )
5053         panMap[iField] = -1;
5054 
5055     // Caution: At the time of writing, the MapInfo driver
5056     // returns NULL until a field has been added.
5057     OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
5058     int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
5059     for( int iField = 0; iField < nSrcFieldCount; ++iField )
5060     {
5061         OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
5062         OGRFieldDefn oFieldDefn(poSrcFieldDefn);
5063 
5064         // The field may have been already created at layer creation.
5065         int iDstField = -1;
5066         if (poDstFDefn)
5067             iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
5068         if (iDstField >= 0)
5069         {
5070             panMap[iField] = iDstField;
5071         }
5072         else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
5073         {
5074             // Now that we've created a field, GetLayerDefn() won't return NULL.
5075             if (poDstFDefn == nullptr)
5076                 poDstFDefn = poDstLayer->GetLayerDefn();
5077 
5078             // Sanity check: if it fails, the driver is buggy.
5079             if (poDstFDefn != nullptr &&
5080                 poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
5081             {
5082                 CPLError(CE_Warning, CPLE_AppDefined,
5083                          "The output driver has claimed to have added the %s "
5084                          "field, but it did not!",
5085                          oFieldDefn.GetNameRef());
5086             }
5087             else
5088             {
5089                 panMap[iField] = nDstFieldCount;
5090                 ++nDstFieldCount;
5091             }
5092         }
5093     }
5094 
5095 /* -------------------------------------------------------------------- */
5096     OGRCoordinateTransformation *poCT = nullptr;
5097     OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
5098     if (sourceSRS != nullptr && pszSRSWKT != nullptr &&
5099             sourceSRS->IsSame(&oDstSpaRef) == FALSE)
5100     {
5101         poCT = OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef);
5102         if(nullptr == poCT)
5103         {
5104             CPLError(CE_Failure, CPLE_NotSupported,
5105                      "This input/output spatial reference is not supported.");
5106             CPLFree(panMap);
5107             return nullptr;
5108         }
5109     }
5110 /* -------------------------------------------------------------------- */
5111 /*      Create geometry fields.                                         */
5112 /* -------------------------------------------------------------------- */
5113     const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
5114     if( nSrcGeomFieldCount > 1 &&
5115         TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
5116     {
5117 
5118         for( int iField = 0; iField < nSrcGeomFieldCount; ++iField )
5119         {
5120             if(nullptr == pszSRSWKT)
5121             {
5122                 poDstLayer->CreateGeomField(
5123                     poSrcDefn->GetGeomFieldDefn(iField));
5124             }
5125             else
5126             {
5127                 OGRGeomFieldDefn *pDstGeomFieldDefn =
5128                     poSrcDefn->GetGeomFieldDefn(iField);
5129                 pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
5130                 poDstLayer->CreateGeomField(pDstGeomFieldDefn);
5131             }
5132         }
5133     }
5134 
5135 /* -------------------------------------------------------------------- */
5136 /*      Check if the destination layer supports transactions and set a  */
5137 /*      default number of features in a single transaction.             */
5138 /* -------------------------------------------------------------------- */
5139     const int nGroupTransactions =
5140         poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
5141 
5142 /* -------------------------------------------------------------------- */
5143 /*      Transfer features.                                              */
5144 /* -------------------------------------------------------------------- */
5145     OGRFeature *poFeature = nullptr;
5146 
5147     poSrcLayer->ResetReading();
5148 
5149     if( nGroupTransactions <= 0 )
5150     {
5151         while( true )
5152         {
5153             poFeature = poSrcLayer->GetNextFeature();
5154 
5155             if( poFeature == nullptr )
5156                 break;
5157 
5158             CPLErrorReset();
5159             OGRFeature *poDstFeature =
5160                 OGRFeature::CreateFeature(poDstLayer->GetLayerDefn());
5161 
5162             if( poDstFeature->SetFrom( poFeature, panMap, TRUE ) !=
5163                     OGRERR_NONE )
5164             {
5165                 CPLError(CE_Failure, CPLE_AppDefined,
5166                          "Unable to translate feature " CPL_FRMT_GIB
5167                          " from layer %s.",
5168                          poFeature->GetFID(), poSrcDefn->GetName());
5169                 OGRFeature::DestroyFeature(poFeature);
5170                 CPLFree(panMap);
5171                 if(nullptr != poCT)
5172                     OCTDestroyCoordinateTransformation(
5173                         OGRCoordinateTransformation::ToHandle(poCT));
5174                 return poDstLayer;
5175             }
5176 
5177             if(nullptr != poCT)
5178             {
5179                 for( int iField = 0; iField < nSrcGeomFieldCount; ++iField )
5180                 {
5181                     OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
5182                     if(nullptr == pGeom)
5183                         continue;
5184 
5185                     const OGRErr eErr = pGeom->transform(poCT);
5186                     if(eErr == OGRERR_NONE)
5187                         continue;
5188 
5189                     CPLError(
5190                         CE_Failure, CPLE_AppDefined,
5191                         "Unable to transform geometry " CPL_FRMT_GIB
5192                         " from layer %s.",
5193                         poFeature->GetFID(), poSrcDefn->GetName());
5194                     OGRFeature::DestroyFeature(poFeature);
5195                     CPLFree(panMap);
5196                     OCTDestroyCoordinateTransformation(
5197                         OGRCoordinateTransformation::ToHandle(poCT));
5198                     return poDstLayer;
5199                 }
5200             }
5201 
5202             poDstFeature->SetFID(poFeature->GetFID());
5203 
5204             OGRFeature::DestroyFeature(poFeature);
5205 
5206             CPLErrorReset();
5207             if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE )
5208             {
5209                 OGRFeature::DestroyFeature(poDstFeature);
5210                 CPLFree(panMap);
5211                 if(nullptr != poCT)
5212                     OCTDestroyCoordinateTransformation(
5213                         OGRCoordinateTransformation::ToHandle(poCT));
5214                 return poDstLayer;
5215             }
5216 
5217             OGRFeature::DestroyFeature(poDstFeature);
5218         }
5219     }
5220     else
5221     {
5222         OGRFeature **papoDstFeature = static_cast<OGRFeature **>(
5223             VSI_CALLOC_VERBOSE(sizeof(OGRFeature *), nGroupTransactions));
5224 
5225         bool bStopTransfer = papoDstFeature == nullptr;
5226         while( !bStopTransfer )
5227         {
5228 /* -------------------------------------------------------------------- */
5229 /*      Fill the array with features.                                   */
5230 /* -------------------------------------------------------------------- */
5231             // Number of features in the temporary array.
5232             int nFeatCount = 0;  // Used after for.
5233             for( nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount )
5234             {
5235                 poFeature = poSrcLayer->GetNextFeature();
5236 
5237                 if( poFeature == nullptr )
5238                 {
5239                     bStopTransfer = true;
5240                     break;
5241                 }
5242 
5243                 CPLErrorReset();
5244                 papoDstFeature[nFeatCount] =
5245                     OGRFeature::CreateFeature(poDstLayer->GetLayerDefn());
5246 
5247                 if( papoDstFeature[nFeatCount]->SetFrom(poFeature, panMap,
5248                                                        TRUE) != OGRERR_NONE )
5249                 {
5250                     CPLError(CE_Failure, CPLE_AppDefined,
5251                              "Unable to translate feature " CPL_FRMT_GIB
5252                              " from layer %s.",
5253                              poFeature->GetFID(), poSrcDefn->GetName());
5254                     OGRFeature::DestroyFeature( poFeature );
5255                     poFeature = nullptr;
5256                     bStopTransfer = true;
5257                     break;
5258                 }
5259 
5260                 if(nullptr != poCT)
5261                 {
5262                     for( int iField = 0; iField < nSrcGeomFieldCount; ++iField )
5263                     {
5264                         OGRGeometry *pGeom =
5265                             papoDstFeature[nFeatCount]->GetGeomFieldRef(iField);
5266                         if(nullptr == pGeom)
5267                             continue;
5268 
5269                         const OGRErr eErr = pGeom->transform(poCT);
5270                         if(eErr == OGRERR_NONE)
5271                             continue;
5272 
5273                         CPLError(
5274                             CE_Failure, CPLE_AppDefined,
5275                             "Unable to transform geometry " CPL_FRMT_GIB
5276                             " from layer %s.",
5277                             poFeature->GetFID(), poSrcDefn->GetName());
5278                         OGRFeature::DestroyFeature(poFeature);
5279                         bStopTransfer = true;
5280                         poFeature = nullptr;
5281                         break;
5282                     }
5283                 }
5284 
5285                 if (poFeature)
5286                 {
5287                     papoDstFeature[nFeatCount]->SetFID(poFeature->GetFID());
5288                     OGRFeature::DestroyFeature(poFeature);
5289                     poFeature = nullptr;
5290                 }
5291             }
5292             int nFeaturesToAdd = nFeatCount;
5293 
5294             CPLErrorReset();
5295             bool bStopTransaction = false;
5296             while( !bStopTransaction )
5297             {
5298                 bStopTransaction = true;
5299                 if( poDstLayer->StartTransaction() != OGRERR_NONE )
5300                     break;
5301                 for( int i = 0; i < nFeaturesToAdd; ++i )
5302                 {
5303                     if( poDstLayer->CreateFeature( papoDstFeature[i] ) !=
5304                        OGRERR_NONE )
5305                     {
5306                         nFeaturesToAdd = i;
5307                         bStopTransfer = true;
5308                         bStopTransaction = false;
5309                     }
5310                 }
5311                 if( bStopTransaction )
5312                 {
5313                     if( poDstLayer->CommitTransaction() != OGRERR_NONE )
5314                         break;
5315                 }
5316                 else
5317                 {
5318                     poDstLayer->RollbackTransaction();
5319                 }
5320             }
5321 
5322             for( int i = 0; i < nFeatCount; ++i )
5323                 OGRFeature::DestroyFeature(papoDstFeature[i]);
5324         }
5325         CPLFree(papoDstFeature);
5326     }
5327 
5328     if(nullptr != poCT)
5329         OCTDestroyCoordinateTransformation(
5330             OGRCoordinateTransformation::ToHandle(poCT));
5331 
5332     CPLFree(panMap);
5333 
5334     return poDstLayer;
5335 }
5336 
5337 /************************************************************************/
5338 /*                            DeleteLayer()                             */
5339 /************************************************************************/
5340 
5341 /**
5342  \fn GDALDataset::DeleteLayer(int)
5343  \brief Delete the indicated layer from the datasource.
5344 
5345  If this method is supported
5346  the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
5347 
5348  This method is the same as the C function GDALDatasetDeleteLayer() and the
5349  deprecated OGR_DS_DeleteLayer().
5350 
5351  In GDAL 1.X, this method used to be in the OGRDataSource class.
5352 
5353  @param iLayer the index of the layer to delete.
5354 
5355  @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
5356  layers is not supported for this datasource.
5357 
5358 */
5359 
DeleteLayer(CPL_UNUSED int iLayer)5360 OGRErr GDALDataset::DeleteLayer( CPL_UNUSED int iLayer )
5361 
5362 {
5363     CPLError(CE_Failure, CPLE_NotSupported,
5364              "DeleteLayer() not supported by this dataset.");
5365 
5366     return OGRERR_UNSUPPORTED_OPERATION;
5367 }
5368 
5369 /************************************************************************/
5370 /*                           GetLayerByName()                           */
5371 /************************************************************************/
5372 
5373 /**
5374  \brief Fetch a layer by name.
5375 
5376  The returned layer remains owned by the
5377  GDALDataset and should not be deleted by the application.
5378 
5379  This method is the same as the C function GDALDatasetGetLayerByName() and the
5380  deprecated OGR_DS_GetLayerByName().
5381 
5382  In GDAL 1.X, this method used to be in the OGRDataSource class.
5383 
5384  @param pszName the layer name of the layer to fetch.
5385 
5386  @return the layer, or NULL if Layer is not found or an error occurs.
5387 */
5388 
GetLayerByName(const char * pszName)5389 OGRLayer *GDALDataset::GetLayerByName( const char *pszName )
5390 
5391 {
5392     CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5393 
5394     if ( ! pszName )
5395         return nullptr;
5396 
5397     // First a case sensitive check.
5398     for( int i = 0; i < GetLayerCount(); ++i )
5399     {
5400         OGRLayer *poLayer = GetLayer(i);
5401 
5402         if( strcmp( pszName, poLayer->GetName() ) == 0 )
5403             return poLayer;
5404     }
5405 
5406     // Then case insensitive.
5407     for( int i = 0; i < GetLayerCount(); ++i )
5408     {
5409         OGRLayer *poLayer = GetLayer(i);
5410 
5411         if( EQUAL( pszName, poLayer->GetName() ) )
5412             return poLayer;
5413     }
5414 
5415     return nullptr;
5416 }
5417 
5418 //! @cond Doxygen_Suppress
5419 /************************************************************************/
5420 /*                       ProcessSQLCreateIndex()                        */
5421 /*                                                                      */
5422 /*      The correct syntax for creating an index in our dialect of      */
5423 /*      SQL is:                                                         */
5424 /*                                                                      */
5425 /*        CREATE INDEX ON <layername> USING <columnname>                */
5426 /************************************************************************/
5427 
ProcessSQLCreateIndex(const char * pszSQLCommand)5428 OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand )
5429 
5430 {
5431     char **papszTokens = CSLTokenizeString(pszSQLCommand);
5432 
5433 /* -------------------------------------------------------------------- */
5434 /*      Do some general syntax checking.                                */
5435 /* -------------------------------------------------------------------- */
5436     if( CSLCount(papszTokens) != 6
5437         || !EQUAL(papszTokens[0], "CREATE")
5438         || !EQUAL(papszTokens[1], "INDEX")
5439         || !EQUAL(papszTokens[2], "ON")
5440         || !EQUAL(papszTokens[4], "USING") )
5441     {
5442         CSLDestroy(papszTokens);
5443         CPLError(CE_Failure, CPLE_AppDefined,
5444                  "Syntax error in CREATE INDEX command.\n"
5445                  "Was '%s'\n"
5446                  "Should be of form 'CREATE INDEX ON <table> USING <field>'",
5447                  pszSQLCommand);
5448         return OGRERR_FAILURE;
5449     }
5450 
5451 /* -------------------------------------------------------------------- */
5452 /*      Find the named layer.                                           */
5453 /* -------------------------------------------------------------------- */
5454     OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
5455     if( poLayer == nullptr )
5456     {
5457         CPLError(CE_Failure, CPLE_AppDefined,
5458                     "CREATE INDEX ON failed, no such layer as `%s'.",
5459                     papszTokens[3]);
5460         CSLDestroy(papszTokens);
5461         return OGRERR_FAILURE;
5462     }
5463 
5464 /* -------------------------------------------------------------------- */
5465 /*      Does this layer even support attribute indexes?                 */
5466 /* -------------------------------------------------------------------- */
5467     if( poLayer->GetIndex() == nullptr )
5468     {
5469         CPLError(CE_Failure, CPLE_AppDefined,
5470                  "CREATE INDEX ON not supported by this driver.");
5471         CSLDestroy(papszTokens);
5472         return OGRERR_FAILURE;
5473     }
5474 
5475 /* -------------------------------------------------------------------- */
5476 /*      Find the named field.                                           */
5477 /* -------------------------------------------------------------------- */
5478     int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
5479 
5480     CSLDestroy(papszTokens);
5481 
5482     if( i >= poLayer->GetLayerDefn()->GetFieldCount() )
5483     {
5484         CPLError(CE_Failure, CPLE_AppDefined,
5485                  "`%s' failed, field not found.",
5486                  pszSQLCommand);
5487         return OGRERR_FAILURE;
5488     }
5489 
5490 /* -------------------------------------------------------------------- */
5491 /*      Attempt to create the index.                                    */
5492 /* -------------------------------------------------------------------- */
5493     OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
5494     if( eErr == OGRERR_NONE )
5495     {
5496         eErr = poLayer->GetIndex()->IndexAllFeatures(i);
5497     }
5498     else
5499     {
5500         if( strlen(CPLGetLastErrorMsg()) == 0 )
5501             CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
5502     }
5503 
5504     return eErr;
5505 }
5506 
5507 /************************************************************************/
5508 /*                        ProcessSQLDropIndex()                         */
5509 /*                                                                      */
5510 /*      The correct syntax for dropping one or more indexes in          */
5511 /*      the OGR SQL dialect is:                                         */
5512 /*                                                                      */
5513 /*          DROP INDEX ON <layername> [USING <columnname>]              */
5514 /************************************************************************/
5515 
ProcessSQLDropIndex(const char * pszSQLCommand)5516 OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand )
5517 
5518 {
5519     char **papszTokens = CSLTokenizeString(pszSQLCommand);
5520 
5521 /* -------------------------------------------------------------------- */
5522 /*      Do some general syntax checking.                                */
5523 /* -------------------------------------------------------------------- */
5524     if( (CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6)
5525         || !EQUAL(papszTokens[0], "DROP")
5526         || !EQUAL(papszTokens[1], "INDEX")
5527         || !EQUAL(papszTokens[2], "ON")
5528         || (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")) )
5529     {
5530         CSLDestroy(papszTokens);
5531         CPLError(CE_Failure, CPLE_AppDefined,
5532                  "Syntax error in DROP INDEX command.\n"
5533                  "Was '%s'\n"
5534                  "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
5535                  pszSQLCommand);
5536         return OGRERR_FAILURE;
5537     }
5538 
5539 /* -------------------------------------------------------------------- */
5540 /*      Find the named layer.                                           */
5541 /* -------------------------------------------------------------------- */
5542     OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
5543     if( poLayer == nullptr )
5544     {
5545         CPLError(CE_Failure, CPLE_AppDefined,
5546                     "DROP INDEX ON failed, no such layer as `%s'.",
5547                     papszTokens[3]);
5548         CSLDestroy(papszTokens);
5549         return OGRERR_FAILURE;
5550     }
5551 
5552 /* -------------------------------------------------------------------- */
5553 /*      Does this layer even support attribute indexes?                 */
5554 /* -------------------------------------------------------------------- */
5555     if( poLayer->GetIndex() == nullptr )
5556     {
5557         CPLError(CE_Failure, CPLE_AppDefined,
5558                  "Indexes not supported by this driver.");
5559         CSLDestroy(papszTokens);
5560         return OGRERR_FAILURE;
5561     }
5562 
5563 /* -------------------------------------------------------------------- */
5564 /*      If we were not given a field name, drop all indexes.            */
5565 /* -------------------------------------------------------------------- */
5566     if( CSLCount(papszTokens) == 4 )
5567     {
5568         for( int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i )
5569         {
5570             OGRAttrIndex *poAttrIndex;
5571 
5572             poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
5573             if( poAttrIndex != nullptr )
5574             {
5575                 const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
5576                 if(eErr != OGRERR_NONE)
5577                 {
5578                     CSLDestroy(papszTokens);
5579                     return eErr;
5580                 }
5581             }
5582         }
5583 
5584         CSLDestroy(papszTokens);
5585         return OGRERR_NONE;
5586     }
5587 
5588 /* -------------------------------------------------------------------- */
5589 /*      Find the named field.                                           */
5590 /* -------------------------------------------------------------------- */
5591     int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
5592     CSLDestroy(papszTokens);
5593 
5594     if( i >= poLayer->GetLayerDefn()->GetFieldCount() )
5595     {
5596         CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
5597                  pszSQLCommand);
5598         return OGRERR_FAILURE;
5599     }
5600 
5601 /* -------------------------------------------------------------------- */
5602 /*      Attempt to drop the index.                                      */
5603 /* -------------------------------------------------------------------- */
5604     const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
5605 
5606     return eErr;
5607 }
5608 
5609 /************************************************************************/
5610 /*                        ProcessSQLDropTable()                         */
5611 /*                                                                      */
5612 /*      The correct syntax for dropping a table (layer) in the OGR SQL  */
5613 /*      dialect is:                                                     */
5614 /*                                                                      */
5615 /*          DROP TABLE <layername>                                      */
5616 /************************************************************************/
5617 
ProcessSQLDropTable(const char * pszSQLCommand)5618 OGRErr GDALDataset::ProcessSQLDropTable( const char *pszSQLCommand )
5619 
5620 {
5621     char **papszTokens = CSLTokenizeString(pszSQLCommand);
5622 
5623 /* -------------------------------------------------------------------- */
5624 /*      Do some general syntax checking.                                */
5625 /* -------------------------------------------------------------------- */
5626     if( CSLCount(papszTokens) != 3
5627         || !EQUAL(papszTokens[0], "DROP")
5628         || !EQUAL(papszTokens[1], "TABLE") )
5629     {
5630         CSLDestroy(papszTokens);
5631         CPLError(CE_Failure, CPLE_AppDefined,
5632                  "Syntax error in DROP TABLE command.\n"
5633                  "Was '%s'\n"
5634                  "Should be of form 'DROP TABLE <table>'",
5635                  pszSQLCommand);
5636         return OGRERR_FAILURE;
5637     }
5638 
5639 /* -------------------------------------------------------------------- */
5640 /*      Find the named layer.                                           */
5641 /* -------------------------------------------------------------------- */
5642     OGRLayer *poLayer = nullptr;
5643 
5644     int i = 0;  // Used after for.
5645     for( ; i < GetLayerCount(); ++i )
5646     {
5647         poLayer = GetLayer(i);
5648 
5649         if( poLayer!= nullptr && EQUAL(poLayer->GetName(),papszTokens[2]) )
5650             break;
5651         poLayer = nullptr;
5652     }
5653 
5654     if( poLayer == nullptr )
5655     {
5656         CPLError(CE_Failure, CPLE_AppDefined,
5657                  "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
5658         CSLDestroy(papszTokens);
5659         return OGRERR_FAILURE;
5660     }
5661 
5662     CSLDestroy(papszTokens);
5663 
5664 /* -------------------------------------------------------------------- */
5665 /*      Delete it.                                                      */
5666 /* -------------------------------------------------------------------- */
5667 
5668     return DeleteLayer(i);
5669 }
5670 //! @endcond
5671 
5672 /************************************************************************/
5673 /*                    GDALDatasetParseSQLType()                       */
5674 /************************************************************************/
5675 
5676 /* All arguments will be altered */
GDALDatasetParseSQLType(char * pszType,int & nWidth,int & nPrecision)5677 static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
5678                                             int &nPrecision)
5679 {
5680     char *pszParenthesis = strchr(pszType, '(');
5681     if (pszParenthesis)
5682     {
5683         nWidth = atoi(pszParenthesis + 1);
5684         *pszParenthesis = '\0';
5685         char *pszComma = strchr(pszParenthesis + 1, ',');
5686         if (pszComma)
5687             nPrecision = atoi(pszComma + 1);
5688     }
5689 
5690     OGRFieldType eType = OFTString;
5691     if (EQUAL(pszType, "INTEGER"))
5692         eType = OFTInteger;
5693     else if (EQUAL(pszType, "INTEGER[]"))
5694         eType = OFTIntegerList;
5695     else if (EQUAL(pszType, "FLOAT") ||
5696              EQUAL(pszType, "NUMERIC") ||
5697              EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
5698              EQUAL(pszType, "REAL") /* unofficial alias */)
5699         eType = OFTReal;
5700     else if (EQUAL(pszType, "FLOAT[]") ||
5701              EQUAL(pszType, "NUMERIC[]") ||
5702              EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
5703              EQUAL(pszType, "REAL[]") /* unofficial alias */)
5704         eType = OFTRealList;
5705     else if (EQUAL(pszType, "CHARACTER") ||
5706              EQUAL(pszType, "TEXT") /* unofficial alias */ ||
5707              EQUAL(pszType, "STRING") /* unofficial alias */ ||
5708              EQUAL(pszType, "VARCHAR") /* unofficial alias */)
5709         eType = OFTString;
5710     else if (EQUAL(pszType, "TEXT[]") ||
5711              EQUAL(pszType, "STRING[]") /* unofficial alias */||
5712              EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
5713         eType = OFTStringList;
5714     else if (EQUAL(pszType, "DATE"))
5715         eType = OFTDate;
5716     else if (EQUAL(pszType, "TIME"))
5717         eType = OFTTime;
5718     else if (EQUAL(pszType, "TIMESTAMP") ||
5719              EQUAL(pszType, "DATETIME") /* unofficial alias */ )
5720         eType = OFTDateTime;
5721     else
5722         CPLError(CE_Warning, CPLE_NotSupported,
5723                  "Unsupported column type '%s'. Defaulting to VARCHAR",
5724                  pszType);
5725 
5726     return eType;
5727 }
5728 
5729 /************************************************************************/
5730 /*                    ProcessSQLAlterTableAddColumn()                   */
5731 /*                                                                      */
5732 /*      The correct syntax for adding a column in the OGR SQL           */
5733 /*      dialect is:                                                     */
5734 /*                                                                      */
5735 /*       ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
5736 /************************************************************************/
5737 
5738 //! @cond Doxygen_Suppress
ProcessSQLAlterTableAddColumn(const char * pszSQLCommand)5739 OGRErr GDALDataset::ProcessSQLAlterTableAddColumn( const char *pszSQLCommand )
5740 
5741 {
5742     char **papszTokens = CSLTokenizeString(pszSQLCommand);
5743 
5744 /* -------------------------------------------------------------------- */
5745 /*      Do some general syntax checking.                                */
5746 /* -------------------------------------------------------------------- */
5747     const char *pszLayerName = nullptr;
5748     const char *pszColumnName = nullptr;
5749     int iTypeIndex = 0;
5750     const int nTokens = CSLCount(papszTokens);
5751 
5752     if( nTokens >= 7
5753         && EQUAL(papszTokens[0], "ALTER")
5754         && EQUAL(papszTokens[1], "TABLE")
5755         && EQUAL(papszTokens[3], "ADD")
5756         && EQUAL(papszTokens[4], "COLUMN"))
5757     {
5758         pszLayerName = papszTokens[2];
5759         pszColumnName = papszTokens[5];
5760         iTypeIndex = 6;
5761     }
5762     else if( nTokens >= 6
5763              && EQUAL(papszTokens[0], "ALTER")
5764              && EQUAL(papszTokens[1], "TABLE")
5765              && EQUAL(papszTokens[3], "ADD"))
5766     {
5767         pszLayerName = papszTokens[2];
5768         pszColumnName = papszTokens[4];
5769         iTypeIndex = 5;
5770     }
5771     else
5772     {
5773         CSLDestroy(papszTokens);
5774         CPLError(CE_Failure, CPLE_AppDefined,
5775                  "Syntax error in ALTER TABLE ADD COLUMN command.\n"
5776                  "Was '%s'\n"
5777                  "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
5778                  "<columnname> <columntype>'",
5779                  pszSQLCommand);
5780         return OGRERR_FAILURE;
5781     }
5782 
5783 /* -------------------------------------------------------------------- */
5784 /*      Merge type components into a single string if there were split  */
5785 /*      with spaces                                                     */
5786 /* -------------------------------------------------------------------- */
5787     CPLString osType;
5788     for( int i = iTypeIndex; i < nTokens; ++i )
5789     {
5790         osType += papszTokens[i];
5791         CPLFree(papszTokens[i]);
5792     }
5793     char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
5794     papszTokens[iTypeIndex + 1] = nullptr;
5795 
5796 /* -------------------------------------------------------------------- */
5797 /*      Find the named layer.                                           */
5798 /* -------------------------------------------------------------------- */
5799     OGRLayer *poLayer = GetLayerByName(pszLayerName);
5800     if( poLayer == nullptr )
5801     {
5802         CPLError(CE_Failure, CPLE_AppDefined,
5803                  "%s failed, no such layer as `%s'.", pszSQLCommand,
5804                  pszLayerName);
5805         CSLDestroy(papszTokens);
5806         return OGRERR_FAILURE;
5807     }
5808 
5809 /* -------------------------------------------------------------------- */
5810 /*      Add column.                                                     */
5811 /* -------------------------------------------------------------------- */
5812 
5813     int nWidth = 0;
5814     int nPrecision = 0;
5815     OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
5816     OGRFieldDefn oFieldDefn(pszColumnName, eType);
5817     oFieldDefn.SetWidth(nWidth);
5818     oFieldDefn.SetPrecision(nPrecision);
5819 
5820     CSLDestroy(papszTokens);
5821 
5822     return poLayer->CreateField(&oFieldDefn);
5823 }
5824 
5825 /************************************************************************/
5826 /*                    ProcessSQLAlterTableDropColumn()                  */
5827 /*                                                                      */
5828 /*      The correct syntax for dropping a column in the OGR SQL         */
5829 /*      dialect is:                                                     */
5830 /*                                                                      */
5831 /*          ALTER TABLE <layername> DROP [COLUMN] <columnname>          */
5832 /************************************************************************/
5833 
ProcessSQLAlterTableDropColumn(const char * pszSQLCommand)5834 OGRErr GDALDataset::ProcessSQLAlterTableDropColumn( const char *pszSQLCommand )
5835 
5836 {
5837     char **papszTokens = CSLTokenizeString(pszSQLCommand);
5838 
5839 /* -------------------------------------------------------------------- */
5840 /*      Do some general syntax checking.                                */
5841 /* -------------------------------------------------------------------- */
5842     const char *pszLayerName = nullptr;
5843     const char *pszColumnName = nullptr;
5844     if( CSLCount(papszTokens) == 6
5845         && EQUAL(papszTokens[0], "ALTER")
5846         && EQUAL(papszTokens[1], "TABLE")
5847         && EQUAL(papszTokens[3], "DROP")
5848         && EQUAL(papszTokens[4], "COLUMN"))
5849     {
5850         pszLayerName = papszTokens[2];
5851         pszColumnName = papszTokens[5];
5852     }
5853     else if( CSLCount(papszTokens) == 5
5854              && EQUAL(papszTokens[0], "ALTER")
5855              && EQUAL(papszTokens[1], "TABLE")
5856              && EQUAL(papszTokens[3], "DROP"))
5857     {
5858         pszLayerName = papszTokens[2];
5859         pszColumnName = papszTokens[4];
5860     }
5861     else
5862     {
5863         CSLDestroy(papszTokens);
5864         CPLError(CE_Failure, CPLE_AppDefined,
5865                  "Syntax error in ALTER TABLE DROP COLUMN command.\n"
5866                  "Was '%s'\n"
5867                  "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
5868                  "<columnname>'",
5869                  pszSQLCommand);
5870         return OGRERR_FAILURE;
5871     }
5872 
5873 /* -------------------------------------------------------------------- */
5874 /*      Find the named layer.                                           */
5875 /* -------------------------------------------------------------------- */
5876     OGRLayer *poLayer = GetLayerByName(pszLayerName);
5877     if( poLayer == nullptr )
5878     {
5879         CPLError(CE_Failure, CPLE_AppDefined,
5880                  "%s failed, no such layer as `%s'.", pszSQLCommand,
5881                  pszLayerName);
5882         CSLDestroy(papszTokens);
5883         return OGRERR_FAILURE;
5884     }
5885 
5886 /* -------------------------------------------------------------------- */
5887 /*      Find the field.                                                 */
5888 /* -------------------------------------------------------------------- */
5889 
5890     int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
5891     if( nFieldIndex < 0 )
5892     {
5893         CPLError(CE_Failure, CPLE_AppDefined,
5894                  "%s failed, no such field as `%s'.", pszSQLCommand,
5895                  pszColumnName);
5896         CSLDestroy(papszTokens);
5897         return OGRERR_FAILURE;
5898     }
5899 
5900 /* -------------------------------------------------------------------- */
5901 /*      Remove it.                                                      */
5902 /* -------------------------------------------------------------------- */
5903 
5904     CSLDestroy(papszTokens);
5905 
5906     return poLayer->DeleteField(nFieldIndex);
5907 }
5908 
5909 /************************************************************************/
5910 /*                 ProcessSQLAlterTableRenameColumn()                   */
5911 /*                                                                      */
5912 /*      The correct syntax for renaming a column in the OGR SQL         */
5913 /*      dialect is:                                                     */
5914 /*                                                                      */
5915 /*       ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
5916 /************************************************************************/
5917 
5918 OGRErr
ProcessSQLAlterTableRenameColumn(const char * pszSQLCommand)5919 GDALDataset::ProcessSQLAlterTableRenameColumn( const char *pszSQLCommand )
5920 
5921 {
5922     char **papszTokens = CSLTokenizeString(pszSQLCommand);
5923 
5924 /* -------------------------------------------------------------------- */
5925 /*      Do some general syntax checking.                                */
5926 /* -------------------------------------------------------------------- */
5927     const char *pszLayerName = nullptr;
5928     const char *pszOldColName = nullptr;
5929     const char *pszNewColName = nullptr;
5930     if( CSLCount(papszTokens) == 8
5931         && EQUAL(papszTokens[0], "ALTER")
5932         && EQUAL(papszTokens[1], "TABLE")
5933         && EQUAL(papszTokens[3], "RENAME")
5934         && EQUAL(papszTokens[4], "COLUMN")
5935         && EQUAL(papszTokens[6], "TO"))
5936     {
5937         pszLayerName = papszTokens[2];
5938         pszOldColName = papszTokens[5];
5939         pszNewColName = papszTokens[7];
5940     }
5941     else if( CSLCount(papszTokens) == 7
5942              && EQUAL(papszTokens[0], "ALTER")
5943              && EQUAL(papszTokens[1], "TABLE")
5944              && EQUAL(papszTokens[3], "RENAME")
5945              && EQUAL(papszTokens[5], "TO"))
5946     {
5947         pszLayerName = papszTokens[2];
5948         pszOldColName = papszTokens[4];
5949         pszNewColName = papszTokens[6];
5950     }
5951     else
5952     {
5953         CSLDestroy(papszTokens);
5954         CPLError(CE_Failure, CPLE_AppDefined,
5955                  "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
5956                  "Was '%s'\n"
5957                  "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
5958                  "<columnname> TO <newname>'",
5959                  pszSQLCommand);
5960         return OGRERR_FAILURE;
5961     }
5962 
5963 /* -------------------------------------------------------------------- */
5964 /*      Find the named layer.                                           */
5965 /* -------------------------------------------------------------------- */
5966     OGRLayer *poLayer = GetLayerByName(pszLayerName);
5967     if( poLayer == nullptr )
5968     {
5969         CPLError(CE_Failure, CPLE_AppDefined,
5970                  "%s failed, no such layer as `%s'.", pszSQLCommand,
5971                  pszLayerName);
5972         CSLDestroy(papszTokens);
5973         return OGRERR_FAILURE;
5974     }
5975 
5976 /* -------------------------------------------------------------------- */
5977 /*      Find the field.                                                 */
5978 /* -------------------------------------------------------------------- */
5979 
5980     const int nFieldIndex =
5981         poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
5982     if( nFieldIndex < 0 )
5983     {
5984         CPLError(CE_Failure, CPLE_AppDefined,
5985                  "%s failed, no such field as `%s'.", pszSQLCommand,
5986                  pszOldColName);
5987         CSLDestroy(papszTokens);
5988         return OGRERR_FAILURE;
5989     }
5990 
5991 /* -------------------------------------------------------------------- */
5992 /*      Rename column.                                                  */
5993 /* -------------------------------------------------------------------- */
5994     OGRFieldDefn *poOldFieldDefn =
5995         poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
5996     OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
5997     oNewFieldDefn.SetName(pszNewColName);
5998 
5999     CSLDestroy(papszTokens);
6000 
6001     return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6002                                    ALTER_NAME_FLAG);
6003 }
6004 
6005 /************************************************************************/
6006 /*                 ProcessSQLAlterTableAlterColumn()                    */
6007 /*                                                                      */
6008 /*      The correct syntax for altering the type of a column in the     */
6009 /*      OGR SQL dialect is:                                             */
6010 /*                                                                      */
6011 /*   ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
6012 /************************************************************************/
6013 
ProcessSQLAlterTableAlterColumn(const char * pszSQLCommand)6014 OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
6015 
6016 {
6017     char **papszTokens = CSLTokenizeString(pszSQLCommand);
6018 
6019 /* -------------------------------------------------------------------- */
6020 /*      Do some general syntax checking.                                */
6021 /* -------------------------------------------------------------------- */
6022     const char *pszLayerName = nullptr;
6023     const char *pszColumnName = nullptr;
6024     int iTypeIndex = 0;
6025     const int nTokens = CSLCount(papszTokens);
6026 
6027     if( nTokens >= 8
6028         && EQUAL(papszTokens[0], "ALTER")
6029         && EQUAL(papszTokens[1], "TABLE")
6030         && EQUAL(papszTokens[3], "ALTER")
6031         && EQUAL(papszTokens[4], "COLUMN")
6032         && EQUAL(papszTokens[6], "TYPE"))
6033     {
6034         pszLayerName = papszTokens[2];
6035         pszColumnName = papszTokens[5];
6036         iTypeIndex = 7;
6037     }
6038     else if( nTokens >= 7
6039              && EQUAL(papszTokens[0], "ALTER")
6040              && EQUAL(papszTokens[1], "TABLE")
6041              && EQUAL(papszTokens[3], "ALTER")
6042              && EQUAL(papszTokens[5], "TYPE"))
6043     {
6044         pszLayerName = papszTokens[2];
6045         pszColumnName = papszTokens[4];
6046         iTypeIndex = 6;
6047     }
6048     else
6049     {
6050         CSLDestroy(papszTokens);
6051         CPLError(CE_Failure, CPLE_AppDefined,
6052                  "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
6053                  "Was '%s'\n"
6054                  "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
6055                  "<columnname> TYPE <columntype>'",
6056                  pszSQLCommand);
6057         return OGRERR_FAILURE;
6058     }
6059 
6060 /* -------------------------------------------------------------------- */
6061 /*      Merge type components into a single string if there were split  */
6062 /*      with spaces                                                     */
6063 /* -------------------------------------------------------------------- */
6064     CPLString osType;
6065     for( int i = iTypeIndex; i < nTokens; ++i )
6066     {
6067         osType += papszTokens[i];
6068         CPLFree(papszTokens[i]);
6069     }
6070     char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6071     papszTokens[iTypeIndex + 1] = nullptr;
6072 
6073 /* -------------------------------------------------------------------- */
6074 /*      Find the named layer.                                           */
6075 /* -------------------------------------------------------------------- */
6076     OGRLayer *poLayer = GetLayerByName(pszLayerName);
6077     if( poLayer == nullptr )
6078     {
6079         CPLError(CE_Failure, CPLE_AppDefined,
6080                  "%s failed, no such layer as `%s'.", pszSQLCommand,
6081                  pszLayerName);
6082         CSLDestroy(papszTokens);
6083         return OGRERR_FAILURE;
6084     }
6085 
6086 /* -------------------------------------------------------------------- */
6087 /*      Find the field.                                                 */
6088 /* -------------------------------------------------------------------- */
6089 
6090     const int nFieldIndex =
6091         poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6092     if( nFieldIndex < 0 )
6093     {
6094         CPLError(CE_Failure, CPLE_AppDefined,
6095                  "%s failed, no such field as `%s'.", pszSQLCommand,
6096                  pszColumnName);
6097         CSLDestroy(papszTokens);
6098         return OGRERR_FAILURE;
6099     }
6100 
6101 /* -------------------------------------------------------------------- */
6102 /*      Alter column.                                                   */
6103 /* -------------------------------------------------------------------- */
6104 
6105     OGRFieldDefn *poOldFieldDefn =
6106         poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6107     OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6108 
6109     int nWidth = 0;
6110     int nPrecision = 0;
6111     OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6112     oNewFieldDefn.SetType(eType);
6113     oNewFieldDefn.SetWidth(nWidth);
6114     oNewFieldDefn.SetPrecision(nPrecision);
6115 
6116     int l_nFlags = 0;
6117     if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
6118         l_nFlags |= ALTER_TYPE_FLAG;
6119     if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
6120         poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
6121         l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
6122 
6123     CSLDestroy(papszTokens);
6124 
6125     if (l_nFlags == 0)
6126         return OGRERR_NONE;
6127 
6128     return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
6129 }
6130 //! @endcond
6131 
6132 /************************************************************************/
6133 /*                             ExecuteSQL()                             */
6134 /************************************************************************/
6135 
6136 /**
6137  \brief Execute an SQL statement against the data store.
6138 
6139  The result of an SQL query is either NULL for statements that are in error,
6140  or that have no results set, or an OGRLayer pointer representing a results
6141  set from the query.  Note that this OGRLayer is in addition to the layers
6142  in the data store and must be destroyed with
6143  ReleaseResultSet() before the dataset is closed
6144  (destroyed).
6145 
6146  This method is the same as the C function GDALDatasetExecuteSQL() and the
6147  deprecated OGR_DS_ExecuteSQL().
6148 
6149  For more information on the SQL dialect supported internally by OGR
6150  review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a> document.  Some drivers (i.e.
6151  Oracle and PostGIS) pass the SQL directly through to the underlying RDBMS.
6152 
6153  Starting with OGR 1.10, the <a href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a>
6154  can also be used.
6155 
6156  In GDAL 1.X, this method used to be in the OGRDataSource class.
6157 
6158  @param pszStatement the SQL statement to execute.
6159  @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
6160  @param pszDialect allows control of the statement dialect. If set to NULL, the
6161  OGR SQL engine will be used, except for RDBMS drivers that will use their
6162  dedicated SQL engine, unless OGRSQL is explicitly passed as the
6163  dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
6164 
6165  @return an OGRLayer containing the results of the query.  Deallocate with
6166  ReleaseResultSet().
6167 
6168 */
6169 
ExecuteSQL(const char * pszStatement,OGRGeometry * poSpatialFilter,const char * pszDialect)6170 OGRLayer *GDALDataset::ExecuteSQL( const char *pszStatement,
6171                                    OGRGeometry *poSpatialFilter,
6172                                    const char *pszDialect )
6173 
6174 {
6175     return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
6176 }
6177 
6178 //! @cond Doxygen_Suppress
6179 OGRLayer *
ExecuteSQL(const char * pszStatement,OGRGeometry * poSpatialFilter,const char * pszDialect,swq_select_parse_options * poSelectParseOptions)6180 GDALDataset::ExecuteSQL( const char *pszStatement,
6181                          OGRGeometry *poSpatialFilter,
6182                          const char *pszDialect,
6183                          swq_select_parse_options *poSelectParseOptions )
6184 
6185 {
6186     if( pszDialect != nullptr && EQUAL(pszDialect, "SQLite") )
6187     {
6188 #ifdef SQLITE_ENABLED
6189         return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
6190                                    pszDialect);
6191 #else
6192         CPLError(CE_Failure, CPLE_NotSupported,
6193                  "The SQLite driver needs to be compiled to support the "
6194                  "SQLite SQL dialect");
6195         return nullptr;
6196 #endif
6197     }
6198 
6199 /* -------------------------------------------------------------------- */
6200 /*      Handle CREATE INDEX statements specially.                       */
6201 /* -------------------------------------------------------------------- */
6202     if( STARTS_WITH_CI(pszStatement, "CREATE INDEX") )
6203     {
6204         ProcessSQLCreateIndex(pszStatement);
6205         return nullptr;
6206     }
6207 
6208 /* -------------------------------------------------------------------- */
6209 /*      Handle DROP INDEX statements specially.                         */
6210 /* -------------------------------------------------------------------- */
6211     if( STARTS_WITH_CI(pszStatement, "DROP INDEX") )
6212     {
6213         ProcessSQLDropIndex(pszStatement);
6214         return nullptr;
6215     }
6216 
6217 /* -------------------------------------------------------------------- */
6218 /*      Handle DROP TABLE statements specially.                         */
6219 /* -------------------------------------------------------------------- */
6220     if( STARTS_WITH_CI(pszStatement, "DROP TABLE") )
6221     {
6222         ProcessSQLDropTable(pszStatement);
6223         return nullptr;
6224     }
6225 
6226 /* -------------------------------------------------------------------- */
6227 /*      Handle ALTER TABLE statements specially.                        */
6228 /* -------------------------------------------------------------------- */
6229     if( STARTS_WITH_CI(pszStatement, "ALTER TABLE") )
6230     {
6231         char **papszTokens = CSLTokenizeString(pszStatement);
6232         const int nTokens = CSLCount(papszTokens);
6233         if( nTokens >= 4 && EQUAL(papszTokens[3], "ADD") )
6234         {
6235             ProcessSQLAlterTableAddColumn(pszStatement);
6236             CSLDestroy(papszTokens);
6237             return nullptr;
6238         }
6239         else if( nTokens >= 4 && EQUAL(papszTokens[3], "DROP") )
6240         {
6241             ProcessSQLAlterTableDropColumn( pszStatement );
6242             CSLDestroy(papszTokens);
6243             return nullptr;
6244         }
6245         else if( nTokens >= 4 && EQUAL(papszTokens[3], "RENAME") )
6246         {
6247             ProcessSQLAlterTableRenameColumn(pszStatement);
6248             CSLDestroy(papszTokens);
6249             return nullptr;
6250         }
6251         else if( nTokens >= 4 && EQUAL(papszTokens[3], "ALTER") )
6252         {
6253             ProcessSQLAlterTableAlterColumn(pszStatement);
6254             CSLDestroy(papszTokens);
6255             return nullptr;
6256         }
6257         else
6258         {
6259             CPLError(CE_Failure, CPLE_AppDefined,
6260                      "Unsupported ALTER TABLE command : %s", pszStatement);
6261             CSLDestroy(papszTokens);
6262             return nullptr;
6263         }
6264     }
6265 
6266 /* -------------------------------------------------------------------- */
6267 /*      Preparse the SQL statement.                                     */
6268 /* -------------------------------------------------------------------- */
6269     swq_select *psSelectInfo = new swq_select();
6270     swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
6271     if( poSelectParseOptions != nullptr )
6272         poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
6273     if( psSelectInfo->preparse( pszStatement,
6274                                 poCustomFuncRegistrar != nullptr ) != CE_None )
6275     {
6276         delete psSelectInfo;
6277         return nullptr;
6278     }
6279 
6280 /* -------------------------------------------------------------------- */
6281 /*      If there is no UNION ALL, build result layer.                   */
6282 /* -------------------------------------------------------------------- */
6283     if( psSelectInfo->poOtherSelect == nullptr )
6284     {
6285         return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
6286                                         pszDialect, poSelectParseOptions);
6287     }
6288 
6289 /* -------------------------------------------------------------------- */
6290 /*      Build result union layer.                                       */
6291 /* -------------------------------------------------------------------- */
6292     int nSrcLayers = 0;
6293     OGRLayer **papoSrcLayers = nullptr;
6294 
6295     do
6296     {
6297         swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
6298         psSelectInfo->poOtherSelect = nullptr;
6299 
6300         OGRLayer *poLayer = BuildLayerFromSelectInfo(
6301             psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
6302         if( poLayer == nullptr )
6303         {
6304             // Each source layer owns an independent select info.
6305             for( int i = 0; i < nSrcLayers; ++i )
6306                 delete papoSrcLayers[i];
6307             CPLFree(papoSrcLayers);
6308 
6309             // So we just have to destroy the remaining select info.
6310             delete psNextSelectInfo;
6311 
6312             return nullptr;
6313         }
6314         else
6315         {
6316             papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
6317                 papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
6318             papoSrcLayers[nSrcLayers] = poLayer;
6319             ++nSrcLayers;
6320 
6321             psSelectInfo = psNextSelectInfo;
6322         }
6323     }
6324     while( psSelectInfo != nullptr );
6325 
6326     return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
6327 }
6328 //! @endcond
6329 
6330 
6331 /************************************************************************/
6332 /*                             AbortSQL()                             */
6333 /************************************************************************/
6334 
6335 /**
6336  \brief Abort any SQL statement running in the data store.
6337 
6338  This function can be safely called from any thread (pending that the dataset object is still alive). Driver implementations will make sure that it can be called in a thread-safe way.
6339 
6340  This might not be implemented by all drivers. At time of writing, only SQLite, GPKG and PG drivers implement it
6341 
6342  This method is the same as the C method GDALDatasetAbortSQL()
6343 
6344  @since GDAL 3.2.0
6345 
6346 
6347 */
6348 
AbortSQL()6349 OGRErr GDALDataset::AbortSQL(  )
6350 {
6351   CPLError(CE_Failure, CPLE_NotSupported, "AbortSQL is not supported for this driver.");
6352   return OGRERR_UNSUPPORTED_OPERATION;
6353 }
6354 
6355 
6356 /************************************************************************/
6357 /*                        BuildLayerFromSelectInfo()                    */
6358 /************************************************************************/
6359 
6360 struct GDALSQLParseInfo
6361 {
6362     swq_field_list sFieldList;
6363     int nExtraDSCount;
6364     GDALDataset **papoExtraDS;
6365     char *pszWHERE;
6366 };
6367 
BuildLayerFromSelectInfo(swq_select * psSelectInfo,OGRGeometry * poSpatialFilter,const char * pszDialect,swq_select_parse_options * poSelectParseOptions)6368 OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
6369     swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
6370     const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
6371 {
6372     OGRGenSQLResultsLayer *poResults = nullptr;
6373     GDALSQLParseInfo *psParseInfo =
6374         BuildParseInfo(psSelectInfo, poSelectParseOptions);
6375 
6376     if( psParseInfo )
6377     {
6378         poResults =
6379             new OGRGenSQLResultsLayer(this, psSelectInfo, poSpatialFilter,
6380                                       psParseInfo->pszWHERE, pszDialect);
6381     }
6382     else
6383     {
6384         delete psSelectInfo;
6385     }
6386     DestroyParseInfo(psParseInfo);
6387 
6388     return poResults;
6389 }
6390 
6391 /************************************************************************/
6392 /*                             DestroyParseInfo()                       */
6393 /************************************************************************/
6394 
6395 //! @cond Doxygen_Suppress
DestroyParseInfo(GDALSQLParseInfo * psParseInfo)6396 void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
6397 {
6398     if( psParseInfo == nullptr )
6399         return;
6400 
6401     CPLFree(psParseInfo->sFieldList.names);
6402     CPLFree(psParseInfo->sFieldList.types);
6403     CPLFree(psParseInfo->sFieldList.table_ids);
6404     CPLFree(psParseInfo->sFieldList.ids);
6405 
6406     // Release the datasets we have opened with OGROpenShared()
6407     // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
6408     // has taken a reference on them, which it will release in its
6409     // destructor.
6410     for( int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS )
6411         GDALClose(psParseInfo->papoExtraDS[iEDS]);
6412 
6413     CPLFree(psParseInfo->papoExtraDS);
6414     CPLFree(psParseInfo->pszWHERE);
6415     CPLFree(psParseInfo);
6416 }
6417 
6418 /************************************************************************/
6419 /*                            BuildParseInfo()                          */
6420 /************************************************************************/
6421 
6422 GDALSQLParseInfo *
BuildParseInfo(swq_select * psSelectInfo,swq_select_parse_options * poSelectParseOptions)6423 GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
6424                             swq_select_parse_options *poSelectParseOptions)
6425 {
6426     int nFirstLayerFirstSpecialFieldIndex = 0;
6427 
6428     GDALSQLParseInfo *psParseInfo =
6429         static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
6430 
6431 /* -------------------------------------------------------------------- */
6432 /*      Validate that all the source tables are recognized, count       */
6433 /*      fields.                                                         */
6434 /* -------------------------------------------------------------------- */
6435     int nFieldCount = 0;
6436 
6437     for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
6438     {
6439         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
6440         GDALDataset *poTableDS = this;
6441 
6442         if( psTableDef->data_source != nullptr )
6443         {
6444             poTableDS = GDALDataset::FromHandle(
6445                 OGROpenShared(psTableDef->data_source, FALSE, nullptr));
6446             if( poTableDS == nullptr )
6447             {
6448                 if( strlen(CPLGetLastErrorMsg()) == 0 )
6449                     CPLError(CE_Failure, CPLE_AppDefined,
6450                              "Unable to open secondary datasource "
6451                              "`%s' required by JOIN.",
6452                              psTableDef->data_source);
6453 
6454                 DestroyParseInfo(psParseInfo);
6455                 return nullptr;
6456             }
6457 
6458             // Keep in an array to release at the end of this function.
6459             psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
6460                 psParseInfo->papoExtraDS,
6461                 sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
6462             psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
6463         }
6464 
6465         OGRLayer *poSrcLayer =
6466             poTableDS->GetLayerByName(psTableDef->table_name);
6467 
6468         if( poSrcLayer == nullptr )
6469         {
6470             CPLError(CE_Failure, CPLE_AppDefined,
6471                      "SELECT from table %s failed, no such table/featureclass.",
6472                      psTableDef->table_name);
6473 
6474             DestroyParseInfo(psParseInfo);
6475             return nullptr;
6476         }
6477 
6478         nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
6479         if( iTable == 0 ||
6480             (poSelectParseOptions &&
6481             poSelectParseOptions->bAddSecondaryTablesGeometryFields) )
6482             nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
6483 
6484         const char* pszFID = poSrcLayer->GetFIDColumn();
6485         if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
6486             poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
6487             nFieldCount++;
6488     }
6489 
6490 /* -------------------------------------------------------------------- */
6491 /*      Build the field list for all indicated tables.                  */
6492 /* -------------------------------------------------------------------- */
6493 
6494     psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
6495     psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
6496 
6497     psParseInfo->sFieldList.count = 0;
6498     psParseInfo->sFieldList.names = static_cast<char **>(
6499         CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
6500     psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
6501         sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
6502     psParseInfo->sFieldList.table_ids = static_cast<int *>(
6503         CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
6504     psParseInfo->sFieldList.ids = static_cast<int *>(
6505         CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
6506 
6507     bool bIsFID64 = false;
6508     for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
6509     {
6510         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
6511         GDALDataset *poTableDS = this;
6512 
6513         if( psTableDef->data_source != nullptr )
6514         {
6515             poTableDS = GDALDataset::FromHandle(
6516                 OGROpenShared(psTableDef->data_source, FALSE, nullptr));
6517             CPLAssert(poTableDS != nullptr);
6518             poTableDS->Dereference();
6519         }
6520 
6521         OGRLayer *poSrcLayer =
6522             poTableDS->GetLayerByName(psTableDef->table_name);
6523 
6524         for( int iField = 0;
6525              iField < poSrcLayer->GetLayerDefn()->GetFieldCount();
6526              iField++ )
6527         {
6528             OGRFieldDefn *poFDefn =
6529                 poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
6530             const int iOutField = psParseInfo->sFieldList.count++;
6531             psParseInfo->sFieldList.names[iOutField] =
6532                 const_cast<char *>(poFDefn->GetNameRef());
6533             if( poFDefn->GetType() == OFTInteger )
6534             {
6535                 if( poFDefn->GetSubType() == OFSTBoolean )
6536                     psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
6537                 else
6538                     psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
6539             }
6540             else if( poFDefn->GetType() == OFTInteger64 )
6541             {
6542                 if( poFDefn->GetSubType() == OFSTBoolean )
6543                     psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
6544                 else
6545                     psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
6546             }
6547             else if( poFDefn->GetType() == OFTReal )
6548                 psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
6549             else if( poFDefn->GetType() == OFTString )
6550                 psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
6551             else if( poFDefn->GetType() == OFTTime )
6552                 psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
6553             else if( poFDefn->GetType() == OFTDate )
6554                 psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
6555             else if( poFDefn->GetType() == OFTDateTime )
6556                 psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
6557             else
6558                 psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
6559 
6560             psParseInfo->sFieldList.table_ids[iOutField] = iTable;
6561             psParseInfo->sFieldList.ids[iOutField] = iField;
6562         }
6563 
6564         if( iTable == 0 )
6565         {
6566             nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
6567         }
6568 
6569         if( iTable == 0 ||
6570             (poSelectParseOptions &&
6571              poSelectParseOptions->bAddSecondaryTablesGeometryFields) )
6572         {
6573 
6574             for( int iField = 0;
6575                  iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
6576                  iField++ )
6577             {
6578                 OGRGeomFieldDefn *poFDefn =
6579                     poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
6580                 const int iOutField = psParseInfo->sFieldList.count++;
6581                 psParseInfo->sFieldList.names[iOutField] =
6582                     const_cast<char *>(poFDefn->GetNameRef());
6583                 if( *psParseInfo->sFieldList.names[iOutField] == '\0' )
6584                     psParseInfo->sFieldList.names[iOutField] =
6585                         const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
6586                 psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
6587 
6588                 psParseInfo->sFieldList.table_ids[iOutField] = iTable;
6589                 psParseInfo->sFieldList.ids[iOutField] =
6590                     GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
6591                         poSrcLayer->GetLayerDefn(), iField);
6592             }
6593         }
6594 
6595         if( iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
6596             EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES") )
6597         {
6598             bIsFID64 = true;
6599         }
6600     }
6601 
6602 /* -------------------------------------------------------------------- */
6603 /*      Expand '*' in 'SELECT *' now before we add the pseudo fields    */
6604 /* -------------------------------------------------------------------- */
6605     const bool bAlwaysPrefixWithTableName =
6606         poSelectParseOptions &&
6607         poSelectParseOptions->bAlwaysPrefixWithTableName;
6608     if( psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
6609                                       bAlwaysPrefixWithTableName) != CE_None )
6610     {
6611         DestroyParseInfo(psParseInfo);
6612         return nullptr;
6613     }
6614 
6615     for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
6616     {
6617         psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
6618             const_cast<char *>(SpecialFieldNames[iField]);
6619         psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
6620             (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
6621                                             : SpecialFieldTypes[iField];
6622         psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
6623         psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
6624             nFirstLayerFirstSpecialFieldIndex + iField;
6625         psParseInfo->sFieldList.count++;
6626     }
6627 
6628     /* In the case a layer has an explicit FID column name, then add it */
6629     /* so it can be selected */
6630     for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
6631     {
6632         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
6633         GDALDataset *poTableDS = this;
6634 
6635         if( psTableDef->data_source != nullptr )
6636         {
6637             poTableDS = GDALDataset::FromHandle(
6638                 OGROpenShared(psTableDef->data_source, FALSE, nullptr));
6639             CPLAssert(poTableDS != nullptr);
6640             poTableDS->Dereference();
6641         }
6642 
6643         OGRLayer *poSrcLayer =
6644             poTableDS->GetLayerByName(psTableDef->table_name);
6645 
6646         const char* pszFID = poSrcLayer->GetFIDColumn();
6647         if( pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
6648             poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0 )
6649         {
6650             const int iOutField = psParseInfo->sFieldList.count++;
6651             psParseInfo->sFieldList.names[iOutField] =
6652                 const_cast<char*>(pszFID);
6653             if( poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
6654                 EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES") )
6655             {
6656                 psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
6657             }
6658             else
6659             {
6660                 psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
6661             }
6662             psParseInfo->sFieldList.table_ids[iOutField] = iTable;
6663             psParseInfo->sFieldList.ids[iOutField] =
6664                 poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
6665         }
6666     }
6667 
6668 /* -------------------------------------------------------------------- */
6669 /*      Finish the parse operation.                                     */
6670 /* -------------------------------------------------------------------- */
6671     if( psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
6672         CE_None )
6673     {
6674         DestroyParseInfo(psParseInfo);
6675         return nullptr;
6676     }
6677 
6678 /* -------------------------------------------------------------------- */
6679 /*      Extract the WHERE expression to use separately.                 */
6680 /* -------------------------------------------------------------------- */
6681     if( psSelectInfo->where_expr != nullptr )
6682     {
6683         psParseInfo->pszWHERE =
6684             psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
6685         // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
6686     }
6687 
6688     return psParseInfo;
6689 }
6690 //! @endcond
6691 
6692 /************************************************************************/
6693 /*                          ReleaseResultSet()                          */
6694 /************************************************************************/
6695 
6696 /**
6697  \brief Release results of ExecuteSQL().
6698 
6699  This method should only be used to deallocate OGRLayers resulting from
6700  an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
6701  results set before destroying the GDALDataset may cause errors.
6702 
6703  This method is the same as the C function GDALDatasetReleaseResultSet() and the
6704  deprecated OGR_DS_ReleaseResultSet().
6705 
6706  In GDAL 1.X, this method used to be in the OGRDataSource class.
6707 
6708  @param poResultsSet the result of a previous ExecuteSQL() call.
6709 */
6710 
ReleaseResultSet(OGRLayer * poResultsSet)6711 void GDALDataset::ReleaseResultSet( OGRLayer *poResultsSet )
6712 
6713 {
6714     delete poResultsSet;
6715 }
6716 
6717 /************************************************************************/
6718 /*                            GetStyleTable()                           */
6719 /************************************************************************/
6720 
6721 /**
6722  \brief Returns dataset style table.
6723 
6724  This method is the same as the C function GDALDatasetGetStyleTable() and the
6725  deprecated OGR_DS_GetStyleTable().
6726 
6727  In GDAL 1.X, this method used to be in the OGRDataSource class.
6728 
6729  @return pointer to a style table which should not be modified or freed by the
6730  caller.
6731 */
6732 
GetStyleTable()6733 OGRStyleTable *GDALDataset::GetStyleTable() { return m_poStyleTable; }
6734 
6735 /************************************************************************/
6736 /*                         SetStyleTableDirectly()                      */
6737 /************************************************************************/
6738 
6739 /**
6740  \brief Set dataset style table.
6741 
6742  This method operate exactly as SetStyleTable() except that it
6743  assumes ownership of the passed table.
6744 
6745  This method is the same as the C function GDALDatasetSetStyleTableDirectly()
6746  and the deprecated OGR_DS_SetStyleTableDirectly().
6747 
6748  In GDAL 1.X, this method used to be in the OGRDataSource class.
6749 
6750  @param poStyleTable pointer to style table to set
6751 
6752 */
SetStyleTableDirectly(OGRStyleTable * poStyleTable)6753 void GDALDataset::SetStyleTableDirectly( OGRStyleTable *poStyleTable )
6754 {
6755     if ( m_poStyleTable )
6756         delete m_poStyleTable;
6757     m_poStyleTable = poStyleTable;
6758 }
6759 
6760 /************************************************************************/
6761 /*                            SetStyleTable()                           */
6762 /************************************************************************/
6763 
6764 /**
6765  \brief Set dataset style table.
6766 
6767  This method operate exactly as SetStyleTableDirectly() except
6768  that it does not assume ownership of the passed table.
6769 
6770  This method is the same as the C function GDALDatasetSetStyleTable() and the
6771  deprecated OGR_DS_SetStyleTable().
6772 
6773  In GDAL 1.X, this method used to be in the OGRDataSource class.
6774 
6775  @param poStyleTable pointer to style table to set
6776 
6777 */
6778 
SetStyleTable(OGRStyleTable * poStyleTable)6779 void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
6780 {
6781     if ( m_poStyleTable )
6782         delete m_poStyleTable;
6783     if ( poStyleTable )
6784         m_poStyleTable = poStyleTable->Clone();
6785 }
6786 
6787 /************************************************************************/
6788 /*                         IsGenericSQLDialect()                        */
6789 /************************************************************************/
6790 
6791 //! @cond Doxygen_Suppress
IsGenericSQLDialect(const char * pszDialect)6792 int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
6793 {
6794     return pszDialect != nullptr &&
6795            (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
6796 }
6797 //! @endcond
6798 
6799 /************************************************************************/
6800 /*                            GetLayerCount()                           */
6801 /************************************************************************/
6802 
6803 /**
6804  \brief Get the number of layers in this dataset.
6805 
6806  This method is the same as the C function GDALDatasetGetLayerCount(),
6807  and the deprecated OGR_DS_GetLayerCount().
6808 
6809  In GDAL 1.X, this method used to be in the OGRDataSource class.
6810 
6811  @return layer count.
6812 */
6813 
GetLayerCount()6814 int GDALDataset::GetLayerCount() { return 0; }
6815 
6816 /************************************************************************/
6817 /*                                GetLayer()                            */
6818 /************************************************************************/
6819 
6820 /**
6821  \fn GDALDataset::GetLayer(int)
6822  \brief Fetch a layer by index.
6823 
6824  The returned layer remains owned by the
6825  GDALDataset and should not be deleted by the application.
6826 
6827  See GetLayers() for a C++ iterator version of this method.
6828 
6829  This method is the same as the C function GDALDatasetGetLayer() and the
6830  deprecated OGR_DS_GetLayer().
6831 
6832  In GDAL 1.X, this method used to be in the OGRDataSource class.
6833 
6834  @param iLayer a layer number between 0 and GetLayerCount()-1.
6835 
6836  @return the layer, or NULL if iLayer is out of range or an error occurs.
6837 
6838  @see GetLayers()
6839 */
6840 
GetLayer(CPL_UNUSED int iLayer)6841 OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer) { return nullptr; }
6842 
6843 /************************************************************************/
6844 /*                           ResetReading()                             */
6845 /************************************************************************/
6846 
6847 /**
6848  \brief Reset feature reading to start on the first feature.
6849 
6850  This affects GetNextFeature().
6851 
6852  Depending on drivers, this may also have the side effect of calling
6853  OGRLayer::ResetReading() on the layers of this dataset.
6854 
6855  This method is the same as the C function GDALDatasetResetReading().
6856 
6857  @since GDAL 2.2
6858 */
ResetReading()6859 void GDALDataset::ResetReading()
6860 {
6861     if( !m_poPrivate )
6862         return;
6863     m_poPrivate->nCurrentLayerIdx = 0;
6864     m_poPrivate->nLayerCount = -1;
6865     m_poPrivate->poCurrentLayer = nullptr;
6866     m_poPrivate->nFeatureReadInLayer = 0;
6867     m_poPrivate->nFeatureReadInDataset = 0;
6868     m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
6869     m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
6870 }
6871 
6872 /************************************************************************/
6873 /*                         GDALDatasetResetReading()                    */
6874 /************************************************************************/
6875 
6876 /**
6877  \brief Reset feature reading to start on the first feature.
6878 
6879  This affects GDALDatasetGetNextFeature().
6880 
6881  Depending on drivers, this may also have the side effect of calling
6882  OGR_L_ResetReading() on the layers of this dataset.
6883 
6884  This method is the same as the C++ method GDALDataset::ResetReading()
6885 
6886  @param hDS dataset handle
6887  @since GDAL 2.2
6888 */
GDALDatasetResetReading(GDALDatasetH hDS)6889 void CPL_DLL GDALDatasetResetReading( GDALDatasetH hDS )
6890 {
6891     VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
6892 
6893     return GDALDataset::FromHandle(hDS)->ResetReading();
6894 }
6895 
6896 /************************************************************************/
6897 /*                          GetNextFeature()                            */
6898 /************************************************************************/
6899 
6900 /**
6901  \brief Fetch the next available feature from this dataset.
6902 
6903  This method is intended for the few drivers where OGRLayer::GetNextFeature()
6904  is not efficient, but in general OGRLayer::GetNextFeature() is a more
6905  natural API.
6906 
6907  See GetFeatures() for a C++ iterator version of this method.
6908 
6909  The returned feature becomes the responsibility of the caller to
6910  delete with OGRFeature::DestroyFeature().
6911 
6912  Depending on the driver, this method may return features from layers in a
6913  non sequential way. This is what may happen when the
6914  ODsCRandomLayerRead capability is declared (for example for the
6915  OSM and GMLAS drivers). When datasets declare this capability, it is strongly
6916  advised to use GDALDataset::GetNextFeature() instead of
6917  OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
6918  implementation.
6919 
6920  The default implementation, used by most drivers, will
6921  however iterate over each layer, and then over each feature within this
6922  layer.
6923 
6924  This method takes into account spatial and attribute filters set on layers that
6925  will be iterated upon.
6926 
6927  The ResetReading() method can be used to start at the beginning again.
6928 
6929  Depending on drivers, this may also have the side effect of calling
6930  OGRLayer::GetNextFeature() on the layers of this dataset.
6931 
6932  This method is the same as the C function GDALDatasetGetNextFeature().
6933 
6934  @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
6935                           layer to which the object belongs to, or NULL.
6936                           It is possible that the output of *ppoBelongingLayer
6937                           to be NULL despite the feature not being NULL.
6938  @param pdfProgressPct    a pointer to a double variable to receive the
6939                           percentage progress (in [0,1] range), or NULL.
6940                           On return, the pointed value might be negative if
6941                           determining the progress is not possible.
6942  @param pfnProgress       a progress callback to report progress (for
6943                           GetNextFeature() calls that might have a long
6944                           duration) and offer cancellation possibility, or NULL.
6945  @param pProgressData     user data provided to pfnProgress, or NULL
6946  @return a feature, or NULL if no more features are available.
6947  @since GDAL 2.2
6948  @see GetFeatures()
6949 */
6950 
GetNextFeature(OGRLayer ** ppoBelongingLayer,double * pdfProgressPct,GDALProgressFunc pfnProgress,void * pProgressData)6951 OGRFeature *GDALDataset::GetNextFeature( OGRLayer **ppoBelongingLayer,
6952                                          double *pdfProgressPct,
6953                                          GDALProgressFunc pfnProgress,
6954                                          void *pProgressData )
6955 {
6956     if( !m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0 )
6957     {
6958         if( ppoBelongingLayer != nullptr )
6959             *ppoBelongingLayer = nullptr;
6960         if( pdfProgressPct != nullptr )
6961             *pdfProgressPct = 1.0;
6962         if( pfnProgress != nullptr )
6963             pfnProgress(1.0, "", pProgressData);
6964         return nullptr;
6965     }
6966 
6967     if ( m_poPrivate->poCurrentLayer == nullptr &&
6968          (pdfProgressPct != nullptr || pfnProgress != nullptr) )
6969     {
6970         if( m_poPrivate->nLayerCount < 0 )
6971         {
6972             m_poPrivate->nLayerCount = GetLayerCount();
6973         }
6974 
6975         if( m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT )
6976         {
6977             m_poPrivate->nTotalFeatures = 0;
6978             for(int i = 0; i < m_poPrivate->nLayerCount; i++)
6979             {
6980                 OGRLayer *poLayer = GetLayer(i);
6981                 if( poLayer == nullptr ||
6982                     !poLayer->TestCapability(OLCFastFeatureCount) )
6983                 {
6984                     m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
6985                     break;
6986                 }
6987                 GIntBig nCount = poLayer->GetFeatureCount(FALSE);
6988                 if( nCount < 0 )
6989                 {
6990                     m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
6991                     break;
6992                 }
6993                 m_poPrivate->nTotalFeatures += nCount;
6994             }
6995         }
6996     }
6997 
6998     while( true )
6999     {
7000         if( m_poPrivate->poCurrentLayer == nullptr )
7001         {
7002             m_poPrivate->poCurrentLayer = GetLayer(m_poPrivate->nCurrentLayerIdx);
7003             if( m_poPrivate->poCurrentLayer == nullptr )
7004             {
7005                 m_poPrivate->nCurrentLayerIdx = -1;
7006                 if( ppoBelongingLayer != nullptr )
7007                     *ppoBelongingLayer = nullptr;
7008                 if( pdfProgressPct != nullptr )
7009                     *pdfProgressPct = 1.0;
7010                 return nullptr;
7011             }
7012             m_poPrivate->poCurrentLayer->ResetReading();
7013             m_poPrivate->nFeatureReadInLayer = 0;
7014             if( m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr )
7015             {
7016                 if( m_poPrivate->poCurrentLayer->TestCapability(
7017                         OLCFastFeatureCount) )
7018                     m_poPrivate->nTotalFeaturesInLayer =
7019                         m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
7020                 else
7021                     m_poPrivate->nTotalFeaturesInLayer = 0;
7022             }
7023         }
7024         OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
7025         if( poFeature == nullptr )
7026         {
7027             m_poPrivate->nCurrentLayerIdx++;
7028             m_poPrivate->poCurrentLayer = nullptr;
7029             continue;
7030         }
7031 
7032         m_poPrivate->nFeatureReadInLayer++;
7033         m_poPrivate->nFeatureReadInDataset++;
7034         if( pdfProgressPct != nullptr || pfnProgress != nullptr )
7035         {
7036             double dfPct = 0.0;
7037             if( m_poPrivate->nTotalFeatures > 0 )
7038             {
7039                 dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
7040                         m_poPrivate->nTotalFeatures;
7041             }
7042             else
7043             {
7044                 dfPct =
7045                     1.0 * m_poPrivate->nCurrentLayerIdx / m_poPrivate->nLayerCount;
7046                 if( m_poPrivate->nTotalFeaturesInLayer > 0 )
7047                 {
7048                     dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
7049                              m_poPrivate->nTotalFeaturesInLayer /
7050                              m_poPrivate->nLayerCount;
7051                 }
7052             }
7053             if( pdfProgressPct )
7054                 *pdfProgressPct = dfPct;
7055             if( pfnProgress )
7056                 pfnProgress(dfPct, "", nullptr);
7057         }
7058 
7059         if( ppoBelongingLayer != nullptr )
7060             *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
7061         return poFeature;
7062     }
7063 }
7064 
7065 /************************************************************************/
7066 /*                     GDALDatasetGetNextFeature()                      */
7067 /************************************************************************/
7068 /**
7069  \brief Fetch the next available feature from this dataset.
7070 
7071  This method is intended for the few drivers where OGR_L_GetNextFeature()
7072  is not efficient, but in general OGR_L_GetNextFeature() is a more
7073  natural API.
7074 
7075  The returned feature becomes the responsibility of the caller to
7076  delete with OGRFeature::DestroyFeature().
7077 
7078  Depending on the driver, this method may return features from layers in a
7079  non sequential way. This is what may happen when the
7080  ODsCRandomLayerRead capability is declared (for example for the
7081  OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7082  advised to use GDALDataset::GetNextFeature() instead of
7083  OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7084  implementation.
7085 
7086  The default implementation, used by most drivers, will
7087  however iterate over each layer, and then over each feature within this
7088  layer.
7089 
7090  This method takes into account spatial and attribute filters set on layers that
7091  will be iterated upon.
7092 
7093  The ResetReading() method can be used to start at the beginning again.
7094 
7095  Depending on drivers, this may also have the side effect of calling
7096  OGRLayer::GetNextFeature() on the layers of this dataset.
7097 
7098  This method is the same as the C++ method GDALDataset::GetNextFeature()
7099 
7100  @param hDS               dataset handle.
7101  @param phBelongingLayer  a pointer to a OGRLayer* variable to receive the
7102                           layer to which the object belongs to, or NULL.
7103                           It is possible that the output of *ppoBelongingLayer
7104                           to be NULL despite the feature not being NULL.
7105  @param pdfProgressPct    a pointer to a double variable to receive the
7106                           percentage progress (in [0,1] range), or NULL.
7107                           On return, the pointed value might be negative if
7108                           determining the progress is not possible.
7109  @param pfnProgress       a progress callback to report progress (for
7110                           GetNextFeature() calls that might have a long
7111                           duration) and offer cancellation possibility, or NULL
7112  @param pProgressData     user data provided to pfnProgress, or NULL
7113  @return a feature, or NULL if no more features are available.
7114  @since GDAL 2.2
7115 */
GDALDatasetGetNextFeature(GDALDatasetH hDS,OGRLayerH * phBelongingLayer,double * pdfProgressPct,GDALProgressFunc pfnProgress,void * pProgressData)7116 OGRFeatureH CPL_DLL GDALDatasetGetNextFeature( GDALDatasetH hDS,
7117                                                OGRLayerH *phBelongingLayer,
7118                                                double *pdfProgressPct,
7119                                                GDALProgressFunc pfnProgress,
7120                                                void *pProgressData )
7121 {
7122     VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
7123 
7124     return OGRFeature::ToHandle(
7125         GDALDataset::FromHandle(hDS)
7126             ->GetNextFeature(reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
7127                              pfnProgress, pProgressData));
7128 }
7129 
7130 /************************************************************************/
7131 /*                            TestCapability()                          */
7132 /************************************************************************/
7133 
7134 /**
7135  \fn GDALDataset::TestCapability( const char * pszCap )
7136  \brief Test if capability is available.
7137 
7138  One of the following dataset capability names can be passed into this
7139  method, and a TRUE or FALSE value will be returned indicating whether or not
7140  the capability is available for this object.
7141 
7142  <ul>
7143   <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7144   <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7145           layers.<p>
7146   <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7147           datasource support CreateGeomField() just after layer creation.<p>
7148   <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7149           geometries.<p>
7150   <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7151           transactions.<p>
7152   <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7153           transactions through emulation.<p>
7154   <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7155           GetNextFeature() implementation, potentially returning features from
7156           layers in a non sequential way.<p>
7157   <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7158          CreateFeature() on layers in a non sequential way.<p>
7159  </ul>
7160 
7161  The \#define macro forms of the capability names should be used in preference
7162  to the strings themselves to avoid misspelling.
7163 
7164  This method is the same as the C function GDALDatasetTestCapability() and the
7165  deprecated OGR_DS_TestCapability().
7166 
7167  In GDAL 1.X, this method used to be in the OGRDataSource class.
7168 
7169  @param pszCap the capability to test.
7170 
7171  @return TRUE if capability available otherwise FALSE.
7172 */
7173 
TestCapability(CPL_UNUSED const char * pszCap)7174 int GDALDataset::TestCapability(CPL_UNUSED const char *pszCap) { return FALSE; }
7175 
7176 /************************************************************************/
7177 /*                     GDALDatasetTestCapability()                      */
7178 /************************************************************************/
7179 
7180 /**
7181  \brief Test if capability is available.
7182 
7183  One of the following dataset capability names can be passed into this
7184  function, and a TRUE or FALSE value will be returned indicating whether or not
7185  the capability is available for this object.
7186 
7187  <ul>
7188   <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7189   <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7190           layers.<p>
7191   <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7192           datasource support CreateGeomField() just after layer creation.<p>
7193   <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7194           geometries.<p>
7195   <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7196           transactions.<p>
7197   <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7198           transactions through emulation.<p>
7199   <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7200           GetNextFeature() implementation, potentially returning features from
7201           layers in a non sequential way.<p>
7202   <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7203           CreateFeature() on layers in a non sequential way.<p>
7204  </ul>
7205 
7206  The \#define macro forms of the capability names should be used in preference
7207  to the strings themselves to avoid misspelling.
7208 
7209  This function is the same as the C++ method GDALDataset::TestCapability()
7210 
7211  @since GDAL 2.0
7212 
7213  @param hDS the dataset handle.
7214  @param pszCap the capability to test.
7215 
7216  @return TRUE if capability available otherwise FALSE.
7217 */
GDALDatasetTestCapability(GDALDatasetH hDS,const char * pszCap)7218 int GDALDatasetTestCapability( GDALDatasetH hDS, const char *pszCap )
7219 
7220 {
7221     VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
7222     VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
7223 
7224     return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
7225 }
7226 
7227 /************************************************************************/
7228 /*                           StartTransaction()                         */
7229 /************************************************************************/
7230 
7231 /**
7232  \fn GDALDataset::StartTransaction(int)
7233  \brief For datasources which support transactions, StartTransaction creates a
7234 `transaction.
7235 
7236  If starting the transaction fails, will return
7237  OGRERR_FAILURE. Datasources which do not support transactions will
7238  always return OGRERR_UNSUPPORTED_OPERATION.
7239 
7240  Nested transactions are not supported.
7241 
7242  All changes done after the start of the transaction are definitely applied in
7243  the datasource if CommitTransaction() is called. They may be canceled by
7244  calling RollbackTransaction() instead.
7245 
7246  At the time of writing, transactions only apply on vector layers.
7247 
7248  Datasets that support transactions will advertise the ODsCTransactions
7249  capability.  Use of transactions at dataset level is generally preferred to
7250  transactions at layer level, whose scope is rarely limited to the layer from
7251  which it was started.
7252 
7253  In case StartTransaction() fails, neither CommitTransaction() or
7254  RollbackTransaction() should be called.
7255 
7256  If an error occurs after a successful StartTransaction(), the whole transaction
7257  may or may not be implicitly canceled, depending on drivers. (e.g.  the PG
7258  driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
7259  an explicit call to RollbackTransaction() should be done to keep things
7260  balanced.
7261 
7262  By default, when bForce is set to FALSE, only "efficient" transactions will be
7263  attempted. Some drivers may offer an emulation of transactions, but sometimes
7264  with significant overhead, in which case the user must explicitly allow for
7265  such an emulation by setting bForce to TRUE. Drivers that offer emulated
7266  transactions should advertise the ODsCEmulatedTransactions capability (and not
7267  ODsCTransactions).
7268 
7269  This function is the same as the C function GDALDatasetStartTransaction().
7270 
7271  @param bForce can be set to TRUE if an emulation, possibly slow, of a
7272  transaction
7273                mechanism is acceptable.
7274 
7275  @return OGRERR_NONE on success.
7276  @since GDAL 2.0
7277 */
7278 
StartTransaction(CPL_UNUSED int bForce)7279 OGRErr GDALDataset::StartTransaction( CPL_UNUSED int bForce )
7280 {
7281     return OGRERR_UNSUPPORTED_OPERATION;
7282 }
7283 
7284 /************************************************************************/
7285 /*                      GDALDatasetStartTransaction()                   */
7286 /************************************************************************/
7287 
7288 /**
7289  \brief For datasources which support transactions, StartTransaction creates a
7290  transaction.
7291 
7292  If starting the transaction fails, will return
7293  OGRERR_FAILURE. Datasources which do not support transactions will
7294  always return OGRERR_UNSUPPORTED_OPERATION.
7295 
7296  Nested transactions are not supported.
7297 
7298  All changes done after the start of the transaction are definitely applied in
7299  the datasource if CommitTransaction() is called. They may be canceled by
7300  calling RollbackTransaction() instead.
7301 
7302  At the time of writing, transactions only apply on vector layers.
7303 
7304  Datasets that support transactions will advertise the ODsCTransactions
7305  capability.
7306  Use of transactions at dataset level is generally preferred to transactions at
7307  layer level, whose scope is rarely limited to the layer from which it was
7308  started.
7309 
7310  In case StartTransaction() fails, neither CommitTransaction() or
7311  RollbackTransaction() should be called.
7312 
7313  If an error occurs after a successful StartTransaction(), the whole
7314  transaction may or may not be implicitly canceled, depending on drivers. (e.g.
7315  the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
7316  error, an explicit call to RollbackTransaction() should be done to keep things
7317  balanced.
7318 
7319  By default, when bForce is set to FALSE, only "efficient" transactions will be
7320  attempted. Some drivers may offer an emulation of transactions, but sometimes
7321  with significant overhead, in which case the user must explicitly allow for
7322  such an emulation by setting bForce to TRUE. Drivers that offer emulated
7323  transactions should advertise the ODsCEmulatedTransactions capability (and not
7324  ODsCTransactions).
7325 
7326  This function is the same as the C++ method GDALDataset::StartTransaction()
7327 
7328  @param hDS the dataset handle.
7329  @param bForce can be set to TRUE if an emulation, possibly slow, of a
7330  transaction
7331                mechanism is acceptable.
7332 
7333  @return OGRERR_NONE on success.
7334  @since GDAL 2.0
7335 */
GDALDatasetStartTransaction(GDALDatasetH hDS,int bForce)7336 OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
7337 {
7338     VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
7339                       OGRERR_INVALID_HANDLE);
7340 
7341 #ifdef OGRAPISPY_ENABLED
7342     if( bOGRAPISpyEnabled )
7343         OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
7344 #endif
7345 
7346     return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
7347 }
7348 
7349 /************************************************************************/
7350 /*                           CommitTransaction()                        */
7351 /************************************************************************/
7352 
7353 /**
7354  \brief For datasources which support transactions, CommitTransaction commits a
7355  transaction.
7356 
7357  If no transaction is active, or the commit fails, will return
7358  OGRERR_FAILURE. Datasources which do not support transactions will
7359  always return OGRERR_UNSUPPORTED_OPERATION.
7360 
7361  Depending on drivers, this may or may not abort layer sequential readings that
7362  are active.
7363 
7364  This function is the same as the C function GDALDatasetCommitTransaction().
7365 
7366  @return OGRERR_NONE on success.
7367  @since GDAL 2.0
7368 */
CommitTransaction()7369 OGRErr GDALDataset::CommitTransaction() { return OGRERR_UNSUPPORTED_OPERATION; }
7370 
7371 /************************************************************************/
7372 /*                        GDALDatasetCommitTransaction()                */
7373 /************************************************************************/
7374 
7375 /**
7376  \brief For datasources which support transactions, CommitTransaction commits a
7377  transaction.
7378 
7379  If no transaction is active, or the commit fails, will return
7380  OGRERR_FAILURE. Datasources which do not support transactions will
7381  always return OGRERR_UNSUPPORTED_OPERATION.
7382 
7383  Depending on drivers, this may or may not abort layer sequential readings that
7384  are active.
7385 
7386  This function is the same as the C++ method GDALDataset::CommitTransaction()
7387 
7388  @return OGRERR_NONE on success.
7389  @since GDAL 2.0
7390 */
GDALDatasetCommitTransaction(GDALDatasetH hDS)7391 OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
7392 {
7393     VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
7394                       OGRERR_INVALID_HANDLE);
7395 
7396 #ifdef OGRAPISPY_ENABLED
7397     if( bOGRAPISpyEnabled )
7398         OGRAPISpy_Dataset_CommitTransaction(hDS);
7399 #endif
7400 
7401     return GDALDataset::FromHandle(hDS)->CommitTransaction();
7402 }
7403 
7404 /************************************************************************/
7405 /*                           RollbackTransaction()                      */
7406 /************************************************************************/
7407 
7408 /**
7409  \brief For datasources which support transactions, RollbackTransaction will
7410  roll back a datasource to its state before the start of the current
7411  transaction.
7412  If no transaction is active, or the rollback fails, will return
7413  OGRERR_FAILURE. Datasources which do not support transactions will
7414  always return OGRERR_UNSUPPORTED_OPERATION.
7415 
7416  This function is the same as the C function GDALDatasetRollbackTransaction().
7417 
7418  @return OGRERR_NONE on success.
7419  @since GDAL 2.0
7420 */
RollbackTransaction()7421 OGRErr GDALDataset::RollbackTransaction()
7422 {
7423     return OGRERR_UNSUPPORTED_OPERATION;
7424 }
7425 
7426 /************************************************************************/
7427 /*                     GDALDatasetRollbackTransaction()                 */
7428 /************************************************************************/
7429 
7430 /**
7431  \brief For datasources which support transactions, RollbackTransaction will
7432  roll back a datasource to its state before the start of the current
7433  transaction.
7434  If no transaction is active, or the rollback fails, will return
7435  OGRERR_FAILURE. Datasources which do not support transactions will
7436  always return OGRERR_UNSUPPORTED_OPERATION.
7437 
7438  This function is the same as the C++ method GDALDataset::RollbackTransaction().
7439 
7440  @return OGRERR_NONE on success.
7441  @since GDAL 2.0
7442 */
GDALDatasetRollbackTransaction(GDALDatasetH hDS)7443 OGRErr GDALDatasetRollbackTransaction( GDALDatasetH hDS )
7444 {
7445     VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
7446                       OGRERR_INVALID_HANDLE);
7447 
7448 #ifdef OGRAPISPY_ENABLED
7449     if( bOGRAPISpyEnabled )
7450         OGRAPISpy_Dataset_RollbackTransaction(hDS);
7451 #endif
7452 
7453     return GDALDataset::FromHandle(hDS)->RollbackTransaction();
7454 }
7455 
7456 
7457 //! @cond Doxygen_Suppress
7458 
7459 /************************************************************************/
7460 /*                   ShareLockWithParentDataset()                       */
7461 /************************************************************************/
7462 
7463 /* To be used typically by the GTiff driver to link overview datasets */
7464 /* with their main dataset, so that they share the same lock */
7465 /* Cf https://github.com/OSGeo/gdal/issues/1488 */
7466 /* The parent dataset should remain alive while the this dataset is alive */
7467 
ShareLockWithParentDataset(GDALDataset * poParentDataset)7468 void GDALDataset::ShareLockWithParentDataset(GDALDataset* poParentDataset)
7469 {
7470     if( m_poPrivate != nullptr )
7471     {
7472         m_poPrivate->poParentDataset = poParentDataset;
7473     }
7474 }
7475 
7476 /************************************************************************/
7477 /*                          EnterReadWrite()                            */
7478 /************************************************************************/
7479 
EnterReadWrite(GDALRWFlag eRWFlag)7480 int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
7481 {
7482     if( m_poPrivate == nullptr )
7483         return FALSE;
7484 
7485     if( m_poPrivate->poParentDataset )
7486         return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
7487 
7488     if( eAccess == GA_Update )
7489     {
7490         if( m_poPrivate->eStateReadWriteMutex == GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN )
7491         {
7492             // In case dead-lock would occur, which is not impossible,
7493             // this can be used to prevent it, but at the risk of other
7494             // issues.
7495             if(CPLTestBool(
7496                    CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
7497             {
7498                 m_poPrivate->eStateReadWriteMutex = GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
7499             }
7500             else
7501             {
7502                 m_poPrivate->eStateReadWriteMutex = GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
7503             }
7504         }
7505         if( m_poPrivate->eStateReadWriteMutex == GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED )
7506         {
7507             // There should be no race related to creating this mutex since
7508             // it should be first created through IWriteBlock() / IRasterIO()
7509             // and then GDALRasterBlock might call it from another thread.
7510 #ifdef DEBUG_VERBOSE
7511             CPLDebug("GDAL",
7512                      "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
7513                      CPLGetPID(), GetDescription());
7514 #endif
7515             CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
7516 
7517             const int nCountMutex = m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
7518             if( nCountMutex == 0 && eRWFlag == GF_Read )
7519             {
7520                 CPLReleaseMutex(m_poPrivate->hMutex);
7521                 for( int i = 0; i < nBands; i++ )
7522                 {
7523                     auto blockCache = papoBands[i]->poBandBlockCache;
7524                     if( blockCache )
7525                         blockCache->WaitCompletionPendingTasks();
7526                 }
7527                 CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
7528             }
7529 
7530             return TRUE;
7531         }
7532     }
7533     return FALSE;
7534 }
7535 
7536 /************************************************************************/
7537 /*                         LeaveReadWrite()                             */
7538 /************************************************************************/
7539 
LeaveReadWrite()7540 void GDALDataset::LeaveReadWrite()
7541 {
7542     if( m_poPrivate )
7543     {
7544         if( m_poPrivate->poParentDataset )
7545         {
7546             m_poPrivate->poParentDataset->LeaveReadWrite();
7547             return;
7548         }
7549 
7550         m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
7551         CPLReleaseMutex(m_poPrivate->hMutex);
7552 #ifdef DEBUG_VERBOSE
7553         CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
7554                  CPLGetPID(), GetDescription());
7555 #endif
7556     }
7557 }
7558 
7559 /************************************************************************/
7560 /*                           InitRWLock()                               */
7561 /************************************************************************/
7562 
InitRWLock()7563 void GDALDataset::InitRWLock()
7564 {
7565     if( m_poPrivate )
7566     {
7567         if( m_poPrivate->poParentDataset )
7568         {
7569             m_poPrivate->poParentDataset->InitRWLock();
7570             return;
7571         }
7572 
7573         if( m_poPrivate->eStateReadWriteMutex == GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN )
7574         {
7575             if( EnterReadWrite(GF_Write) )
7576                 LeaveReadWrite();
7577         }
7578     }
7579 }
7580 
7581 /************************************************************************/
7582 /*                       DisableReadWriteMutex()                        */
7583 /************************************************************************/
7584 
7585 // The mutex logic is broken in multi-threaded situations, for example
7586 // with 2 WarpedVRT datasets being read at the same time. In that
7587 // particular case, the mutex is not needed, so allow the VRTWarpedDataset code
7588 // to disable it.
DisableReadWriteMutex()7589 void GDALDataset::DisableReadWriteMutex()
7590 {
7591     if( m_poPrivate )
7592     {
7593         if( m_poPrivate->poParentDataset )
7594         {
7595             m_poPrivate->poParentDataset->DisableReadWriteMutex();
7596             return;
7597         }
7598 
7599         m_poPrivate->eStateReadWriteMutex = GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
7600     }
7601 }
7602 
7603 /************************************************************************/
7604 /*                      TemporarilyDropReadWriteLock()                  */
7605 /************************************************************************/
7606 
TemporarilyDropReadWriteLock()7607 void GDALDataset::TemporarilyDropReadWriteLock()
7608 {
7609     if( m_poPrivate == nullptr )
7610         return;
7611 
7612     if( m_poPrivate->poParentDataset )
7613     {
7614         m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
7615         return;
7616     }
7617 
7618     if( m_poPrivate->hMutex )
7619     {
7620 #ifdef DEBUG_VERBOSE
7621         CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] "
7622                  "Temporarily drop RW mutex for %s",
7623                  CPLGetPID(), GetDescription());
7624 #endif
7625         CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
7626         const int nCount = m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
7627 #ifdef DEBUG_EXTRA
7628         m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
7629 #endif
7630         for(int i = 0; i < nCount + 1; i++)
7631         {
7632             // The mutex is recursive
7633             // coverity[double_unlock]
7634             CPLReleaseMutex(m_poPrivate->hMutex);
7635         }
7636     }
7637 }
7638 
7639 /************************************************************************/
7640 /*                       ReacquireReadWriteLock()                       */
7641 /************************************************************************/
7642 
ReacquireReadWriteLock()7643 void GDALDataset::ReacquireReadWriteLock()
7644 {
7645     if( m_poPrivate == nullptr )
7646         return;
7647 
7648     if( m_poPrivate->poParentDataset )
7649     {
7650         m_poPrivate->poParentDataset->ReacquireReadWriteLock();
7651         return;
7652     }
7653 
7654     if( m_poPrivate->hMutex )
7655     {
7656 #ifdef DEBUG_VERBOSE
7657         CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] "
7658                  "Reacquire temporarily dropped RW mutex for %s",
7659                  CPLGetPID(), GetDescription());
7660 #endif
7661         CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
7662         const int nCount = m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
7663 #ifdef DEBUG_EXTRA
7664         CPLAssert(nCount ==
7665                   m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
7666 #endif
7667         if( nCount == 0 )
7668             CPLReleaseMutex(m_poPrivate->hMutex);
7669         for(int i = 0; i < nCount - 1; i++)
7670         {
7671             // The mutex is recursive
7672             // coverity[double_lock]
7673             CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
7674         }
7675     }
7676 }
7677 
7678 /************************************************************************/
7679 /*                           AcquireMutex()                             */
7680 /************************************************************************/
7681 
AcquireMutex()7682 int GDALDataset::AcquireMutex()
7683 {
7684     if( m_poPrivate == nullptr )
7685         return 0;
7686     if( m_poPrivate->poParentDataset )
7687     {
7688         return m_poPrivate->poParentDataset->AcquireMutex();
7689     }
7690 
7691     return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
7692 }
7693 
7694 /************************************************************************/
7695 /*                          ReleaseMutex()                              */
7696 /************************************************************************/
7697 
ReleaseMutex()7698 void GDALDataset::ReleaseMutex()
7699 {
7700     if( m_poPrivate )
7701     {
7702         if( m_poPrivate->poParentDataset )
7703         {
7704             m_poPrivate->poParentDataset->ReleaseMutex();
7705             return;
7706         }
7707 
7708         CPLReleaseMutex(m_poPrivate->hMutex);
7709     }
7710 }
7711 //! @endcond
7712 
7713 
7714 /************************************************************************/
7715 /*              GDALDataset::Features::Iterator::Private                */
7716 /************************************************************************/
7717 
7718 struct GDALDataset::Features::Iterator::Private
7719 {
7720     GDALDataset::FeatureLayerPair m_oPair{};
7721     GDALDataset* m_poDS = nullptr;
7722     bool m_bEOF = true;
7723 };
7724 
Iterator(GDALDataset * poDS,bool bStart)7725 GDALDataset::Features::Iterator::Iterator(GDALDataset* poDS, bool bStart):
7726     m_poPrivate(new GDALDataset::Features::Iterator::Private())
7727 {
7728     m_poPrivate->m_poDS = poDS;
7729     if( bStart )
7730     {
7731         poDS->ResetReading();
7732         m_poPrivate->m_oPair.feature.reset(
7733             poDS->GetNextFeature(
7734                 &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
7735         m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
7736     }
7737 }
7738 
7739 GDALDataset::Features::Iterator::~Iterator() = default;
7740 
7741 const GDALDataset::FeatureLayerPair&
operator *() const7742                 GDALDataset::Features::Iterator::operator*() const
7743 {
7744     return m_poPrivate->m_oPair;
7745 }
7746 
operator ++()7747 GDALDataset::Features::Iterator& GDALDataset::Features::Iterator::operator++()
7748 {
7749     m_poPrivate->m_oPair.feature.reset(
7750         m_poPrivate->m_poDS->GetNextFeature(
7751             &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
7752     m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
7753     return *this;
7754 }
7755 
operator !=(const Iterator & it) const7756 bool GDALDataset::Features::Iterator::operator!= (const Iterator& it) const
7757 {
7758     return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
7759 }
7760 
7761 /************************************************************************/
7762 /*                            GetFeatures()                             */
7763 /************************************************************************/
7764 
7765 /** Function that return an iterable object over features in the dataset
7766 * layer.
7767 *
7768 * This is a C++ iterator friendly version of GetNextFeature().
7769 *
7770 * Using this iterator for standard range-based loops is safe, but
7771 * due to implementation limitations, you shouldn't try to access
7772 * (dereference) more than one iterator step at a time, since the
7773 * FeatureLayerPair reference which is returned is reused.
7774 *
7775 * Typical use is:
7776 * \code{.cpp}
7777 * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
7778 * {
7779 *       std::cout << "Feature of layer " <<
7780 *               oFeatureLayerPair.layer->GetName() << std::endl;
7781 *       oFeatureLayerPair.feature->DumpReadable();
7782 * }
7783 * \endcode
7784 *
7785 * @see GetNextFeature()
7786 *
7787 * @since GDAL 2.3
7788 */
GetFeatures()7789 GDALDataset::Features GDALDataset::GetFeatures()
7790 {
7791     return Features(this);
7792 }
7793 
7794 /************************************************************************/
7795 /*                                 begin()                              */
7796 /************************************************************************/
7797 
7798 /**
7799  \brief Return beginning of feature iterator.
7800 
7801  @since GDAL 2.3
7802 */
7803 
begin() const7804 const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
7805 {
7806     return {m_poSelf, true};
7807 }
7808 
7809 /************************************************************************/
7810 /*                                  end()                               */
7811 /************************************************************************/
7812 
7813 /**
7814  \brief Return end of feature iterator.
7815 
7816  @since GDAL 2.3
7817 */
7818 
end() const7819 const GDALDataset::Features::Iterator GDALDataset::Features::end() const
7820 {
7821     return {m_poSelf, false};
7822 }
7823 
7824 /************************************************************************/
7825 /*               GDALDataset::Layers::Iterator::Private                 */
7826 /************************************************************************/
7827 
7828 struct GDALDataset::Layers::Iterator::Private
7829 {
7830     OGRLayer* m_poLayer = nullptr;
7831     int m_iCurLayer = 0;
7832     int m_nLayerCount = 0;
7833     GDALDataset* m_poDS = nullptr;
7834 };
7835 
Iterator()7836 GDALDataset::Layers::Iterator::Iterator():
7837     m_poPrivate(new Private())
7838 {}
7839 
7840 // False positive of cppcheck 1.72
7841 // cppcheck-suppress uninitMemberVar
Iterator(const Iterator & oOther)7842 GDALDataset::Layers::Iterator::Iterator(const Iterator& oOther):
7843     m_poPrivate(new Private(*(oOther.m_poPrivate)))
7844 {
7845 }
7846 
Iterator(Iterator && oOther)7847 GDALDataset::Layers::Iterator::Iterator(Iterator&& oOther) noexcept:
7848     m_poPrivate(std::move(oOther.m_poPrivate))
7849 {
7850 }
7851 
Iterator(GDALDataset * poDS,bool bStart)7852 GDALDataset::Layers::Iterator::Iterator(GDALDataset* poDS, bool bStart):
7853     m_poPrivate(new Private())
7854 {
7855     m_poPrivate->m_poDS = poDS;
7856     m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
7857     if( bStart )
7858     {
7859         if( m_poPrivate->m_nLayerCount )
7860             m_poPrivate->m_poLayer = poDS->GetLayer(0);
7861     }
7862     else
7863     {
7864         m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
7865     }
7866 }
7867 
7868 GDALDataset::Layers::Iterator::~Iterator() = default;
7869 
7870 // False positive of cppcheck 1.72
7871 // cppcheck-suppress operatorEqVarError
operator =(const Iterator & oOther)7872 GDALDataset::Layers::Iterator& GDALDataset::Layers::Iterator::operator=(
7873                                 const Iterator& oOther)
7874 {
7875     *m_poPrivate = *oOther.m_poPrivate;
7876     return *this;
7877 }
7878 
operator =(GDALDataset::Layers::Iterator && oOther)7879 GDALDataset::Layers::Iterator& GDALDataset::Layers::Iterator::operator=(
7880                                 GDALDataset::Layers::Iterator&& oOther) noexcept
7881 {
7882     m_poPrivate = std::move(oOther.m_poPrivate);
7883     return *this;
7884 }
7885 
operator *() const7886 OGRLayer* GDALDataset::Layers::Iterator::operator*() const
7887 {
7888     return m_poPrivate->m_poLayer;
7889 }
7890 
operator ++()7891 GDALDataset::Layers::Iterator& GDALDataset::Layers::Iterator::operator++()
7892 {
7893     m_poPrivate->m_iCurLayer ++;
7894     if( m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount )
7895     {
7896         m_poPrivate->m_poLayer =
7897             m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
7898     }
7899     else
7900     {
7901         m_poPrivate->m_poLayer = nullptr;
7902     }
7903     return *this;
7904 }
7905 
operator ++(int)7906 GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
7907 {
7908     GDALDataset::Layers::Iterator temp = *this;
7909     ++(*this);
7910     return temp;
7911 }
7912 
operator !=(const Iterator & it) const7913 bool GDALDataset::Layers::Iterator::operator!= (const Iterator& it) const
7914 {
7915     return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
7916 }
7917 
7918 /************************************************************************/
7919 /*                             GetLayers()                              */
7920 /************************************************************************/
7921 
7922 /** Function that returns an iterable object over layers in the dataset.
7923 *
7924 * This is a C++ iterator friendly version of GetLayer().
7925 *
7926 * Typical use is:
7927 * \code{.cpp}
7928 * for( auto&& poLayer: poDS->GetLayers() )
7929 * {
7930 *       std::cout << "Layer  << poLayer->GetName() << std::endl;
7931 * }
7932 * \endcode
7933 *
7934 * @see GetLayer()
7935 *
7936 * @since GDAL 2.3
7937 */
GetLayers()7938 GDALDataset::Layers GDALDataset::GetLayers()
7939 {
7940     return Layers(this);
7941 }
7942 
7943 /************************************************************************/
7944 /*                                 begin()                              */
7945 /************************************************************************/
7946 
7947 /**
7948  \brief Return beginning of layer iterator.
7949 
7950  @since GDAL 2.3
7951 */
7952 
begin() const7953 GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
7954 {
7955     return {m_poSelf, true};
7956 }
7957 
7958 /************************************************************************/
7959 /*                                  end()                               */
7960 /************************************************************************/
7961 
7962 /**
7963  \brief Return end of layer iterator.
7964 
7965  @since GDAL 2.3
7966 */
7967 
end() const7968 GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
7969 {
7970     return {m_poSelf, false};
7971 }
7972 
7973 /************************************************************************/
7974 /*                                  size()                             */
7975 /************************************************************************/
7976 
7977 /**
7978  \brief Get the number of layers in this dataset.
7979 
7980  @return layer count.
7981 
7982  @since GDAL 2.3
7983 */
7984 
size() const7985 size_t GDALDataset::Layers::size() const
7986 {
7987     return static_cast<size_t>(m_poSelf->GetLayerCount());
7988 }
7989 
7990 /************************************************************************/
7991 /*                                operator[]()                          */
7992 /************************************************************************/
7993 /**
7994  \brief Fetch a layer by index.
7995 
7996  The returned layer remains owned by the
7997  GDALDataset and should not be deleted by the application.
7998 
7999  @param iLayer a layer number between 0 and size()-1.
8000 
8001  @return the layer, or nullptr if iLayer is out of range or an error occurs.
8002 
8003  @since GDAL 2.3
8004 */
8005 
operator [](int iLayer)8006 OGRLayer* GDALDataset::Layers::operator[](int iLayer)
8007 {
8008     return m_poSelf->GetLayer(iLayer);
8009 }
8010 
8011 /************************************************************************/
8012 /*                                operator[]()                          */
8013 /************************************************************************/
8014 /**
8015  \brief Fetch a layer by index.
8016 
8017  The returned layer remains owned by the
8018  GDALDataset and should not be deleted by the application.
8019 
8020  @param iLayer a layer number between 0 and size()-1.
8021 
8022  @return the layer, or nullptr if iLayer is out of range or an error occurs.
8023 
8024  @since GDAL 2.3
8025 */
8026 
operator [](size_t iLayer)8027 OGRLayer* GDALDataset::Layers::operator[](size_t iLayer)
8028 {
8029     return m_poSelf->GetLayer(static_cast<int>(iLayer));
8030 }
8031 
8032 /************************************************************************/
8033 /*                                operator[]()                          */
8034 /************************************************************************/
8035 /**
8036  \brief Fetch a layer by name.
8037 
8038  The returned layer remains owned by the
8039  GDALDataset and should not be deleted by the application.
8040 
8041  @param pszLayerName layer name
8042 
8043  @return the layer, or nullptr if pszLayerName does not match with a layer
8044 
8045  @since GDAL 2.3
8046 */
8047 
operator [](const char * pszLayerName)8048 OGRLayer* GDALDataset::Layers::operator[](const char* pszLayerName)
8049 {
8050     return m_poSelf->GetLayerByName(pszLayerName);
8051 }
8052 
8053 /************************************************************************/
8054 /*               GDALDataset::Bands::Iterator::Private                 */
8055 /************************************************************************/
8056 
8057 struct GDALDataset::Bands::Iterator::Private
8058 {
8059     GDALRasterBand* m_poBand = nullptr;
8060     int m_iCurBand = 0;
8061     int m_nBandCount = 0;
8062     GDALDataset* m_poDS = nullptr;
8063 };
8064 
Iterator(GDALDataset * poDS,bool bStart)8065 GDALDataset::Bands::Iterator::Iterator(GDALDataset* poDS, bool bStart):
8066     m_poPrivate(new GDALDataset::Bands::Iterator::Private())
8067 {
8068     m_poPrivate->m_poDS = poDS;
8069     m_poPrivate->m_nBandCount = poDS->GetRasterCount();
8070     if( bStart )
8071     {
8072         if( m_poPrivate->m_nBandCount )
8073             m_poPrivate->m_poBand = poDS->GetRasterBand(1);
8074     }
8075     else
8076     {
8077         m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
8078     }
8079 }
8080 
8081 GDALDataset::Bands::Iterator::~Iterator() = default;
8082 
operator *()8083 GDALRasterBand* GDALDataset::Bands::Iterator::operator*()
8084 {
8085     return m_poPrivate->m_poBand;
8086 }
8087 
operator ++()8088 GDALDataset::Bands::Iterator& GDALDataset::Bands::Iterator::operator++()
8089 {
8090     m_poPrivate->m_iCurBand ++;
8091     if( m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount )
8092     {
8093         m_poPrivate->m_poBand =
8094             m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
8095     }
8096     else
8097     {
8098         m_poPrivate->m_poBand = nullptr;
8099     }
8100     return *this;
8101 }
8102 
operator !=(const Iterator & it) const8103 bool GDALDataset::Bands::Iterator::operator!= (const Iterator& it) const
8104 {
8105     return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
8106 }
8107 
8108 /************************************************************************/
8109 /*                            GetBands()                           */
8110 /************************************************************************/
8111 
8112 /** Function that returns an iterable object over GDALRasterBand in the dataset.
8113 *
8114 * This is a C++ iterator friendly version of GetRasterBand().
8115 *
8116 * Typical use is:
8117 * \code{.cpp}
8118 * for( auto&& poBand: poDS->GetBands() )
8119 * {
8120 *       std::cout << "Band  << poBand->GetDescription() << std::endl;
8121 * }
8122 * \endcode
8123 *
8124 * @see GetRasterBand()
8125 *
8126 * @since GDAL 2.3
8127 */
GetBands()8128 GDALDataset::Bands GDALDataset::GetBands()
8129 {
8130     return Bands(this);
8131 }
8132 
8133 /************************************************************************/
8134 /*                                 begin()                              */
8135 /************************************************************************/
8136 
8137 /**
8138  \brief Return beginning of band iterator.
8139 
8140  @since GDAL 2.3
8141 */
8142 
begin() const8143 const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
8144 {
8145     return {m_poSelf, true};
8146 }
8147 
8148 /************************************************************************/
8149 /*                                  end()                               */
8150 /************************************************************************/
8151 
8152 /**
8153  \brief Return end of band iterator.
8154 
8155  @since GDAL 2.3
8156 */
8157 
end() const8158 const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
8159 {
8160     return {m_poSelf, false};
8161 }
8162 
8163 /************************************************************************/
8164 /*                                  size()                             */
8165 /************************************************************************/
8166 
8167 /**
8168  \brief Get the number of raster bands in this dataset.
8169 
8170  @return raster band count.
8171 
8172  @since GDAL 2.3
8173 */
8174 
size() const8175 size_t GDALDataset::Bands::size() const
8176 {
8177     return static_cast<size_t>(m_poSelf->GetRasterCount());
8178 }
8179 
8180 /************************************************************************/
8181 /*                                operator[]()                          */
8182 /************************************************************************/
8183 /**
8184  \brief Fetch a raster band by index.
8185 
8186  The returned band remains owned by the
8187  GDALDataset and should not be deleted by the application.
8188 
8189  @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
8190  consistent with the conventions of C/C++, i.e. starting at 0.
8191 
8192  @param iBand a band index between 0 and size()-1.
8193 
8194  @return the band, or nullptr if iBand is out of range or an error occurs.
8195 
8196  @since GDAL 2.3
8197 */
8198 
operator [](int iBand)8199 GDALRasterBand* GDALDataset::Bands::operator[](int iBand)
8200 {
8201     return m_poSelf->GetRasterBand(1+iBand);
8202 }
8203 
8204 /************************************************************************/
8205 /*                                operator[]()                          */
8206 /************************************************************************/
8207 
8208 /**
8209  \brief Fetch a raster band by index.
8210 
8211  The returned band remains owned by the
8212  GDALDataset and should not be deleted by the application.
8213 
8214  @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
8215  consistent with the conventions of C/C++, i.e. starting at 0.
8216 
8217  @param iBand a band index between 0 and size()-1.
8218 
8219  @return the band, or nullptr if iBand is out of range or an error occurs.
8220 
8221  @since GDAL 2.3
8222 */
8223 
8224 
operator [](size_t iBand)8225 GDALRasterBand* GDALDataset::Bands::operator[](size_t iBand)
8226 {
8227     return m_poSelf->GetRasterBand(1+static_cast<int>(iBand));
8228 }
8229 
8230 /************************************************************************/
8231 /*                           GetRootGroup()                             */
8232 /************************************************************************/
8233 
8234 /**
8235  \brief Return the root GDALGroup of this dataset.
8236 
8237  Only valid for multidimensional datasets.
8238 
8239  This is the same as the C function GDALDatasetGetRootGroup().
8240 
8241  @since GDAL 3.1
8242 */
8243 
GetRootGroup() const8244 std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
8245 {
8246     return nullptr;
8247 }
8248 
8249 
8250 /************************************************************************/
8251 /*                        GetRawBinaryLayout()                          */
8252 /************************************************************************/
8253 
8254 //! @cond Doxygen_Suppress
8255 /**
8256  \brief Return the layout of a dataset that can be considered as a raw binary format.
8257 
8258  @param sLayout Structure that will be set if the dataset is a raw binary one.
8259  @return true if the dataset is a raw binary one.
8260  @since GDAL 3.1
8261 */
8262 
GetRawBinaryLayout(RawBinaryLayout & sLayout)8263 bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout& sLayout)
8264 {
8265     CPL_IGNORE_RET_VAL(sLayout);
8266     return false;
8267 }
8268 //! @endcond
8269 
8270 
8271 /************************************************************************/
8272 /*                          ClearStatistics()                           */
8273 /************************************************************************/
8274 
8275 /**
8276  \brief Clear statistics
8277 
8278  Only implemented for now in PAM supported datasets
8279 
8280  This is the same as the C function GDALDatasetClearStatistics().
8281 
8282  @since GDAL 3.2
8283 */
8284 
ClearStatistics()8285 void GDALDataset::ClearStatistics()
8286 {
8287 }
8288 
8289 /************************************************************************/
8290 /*                        GDALDatasetClearStatistics()                  */
8291 /************************************************************************/
8292 
8293 /**
8294  \brief Clear statistics
8295 
8296  This is the same as the C++ method GDALDataset::ClearStatistics().
8297 
8298  @since GDAL 3.2
8299 */
8300 
GDALDatasetClearStatistics(GDALDatasetH hDS)8301 void GDALDatasetClearStatistics(GDALDatasetH hDS)
8302 {
8303     VALIDATE_POINTER0(hDS, __func__);
8304     GDALDataset::FromHandle(hDS)->ClearStatistics();
8305 }
8306 
8307 /************************************************************************/
8308 /*                        GetFieldDomain()                              */
8309 /************************************************************************/
8310 
8311 /** Get a field domain from its name.
8312  *
8313  * @return the field domain, or nullptr if not found.
8314  * @since GDAL 3.3
8315  */
GetFieldDomain(const std::string & name) const8316 const OGRFieldDomain* GDALDataset::GetFieldDomain(const std::string& name) const
8317 {
8318     const auto iter = m_oMapFieldDomains.find(name);
8319     if( iter == m_oMapFieldDomains.end() )
8320         return nullptr;
8321     return iter->second.get();
8322 }
8323 
8324 /************************************************************************/
8325 /*                      GDALDatasetGetFieldDomain()                     */
8326 /************************************************************************/
8327 
8328 /** Get a field domain from its name.
8329  *
8330  * This is the same as the C++ method GDALDataset::GetFieldDomain().
8331  *
8332  * @param hDS Dataset handle.
8333  * @param pszName Name of field domain.
8334  * @return the field domain (ownership remains to the dataset), or nullptr if not found.
8335  * @since GDAL 3.3
8336  */
GDALDatasetGetFieldDomain(GDALDatasetH hDS,const char * pszName)8337 OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS,
8338                                           const char* pszName)
8339 {
8340     VALIDATE_POINTER1(hDS, __func__, nullptr);
8341     VALIDATE_POINTER1(pszName, __func__, nullptr);
8342     return OGRFieldDomain::ToHandle(
8343         const_cast<OGRFieldDomain*>(
8344             GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
8345 }
8346 
8347 /************************************************************************/
8348 /*                         AddFieldDomain()                             */
8349 /************************************************************************/
8350 
8351 /** Add a field domain to the dataset.
8352  *
8353  * Only a few drivers will support this operation, and some of them might only
8354  * support it only for some types of field domains.
8355  * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
8356  * support this operation. A dataset having at least some support for this
8357  * operation should report the ODsCAddFieldDomain dataset capability.
8358  *
8359  * Anticipated failures will not be emitted through the CPLError()
8360  * infrastructure, but will be reported in the failureReason output parameter.
8361  *
8362  * @param domain The domain definition.
8363  * @param failureReason      Output parameter. Will contain an error message if
8364  *                           an error occurs.
8365  * @return true in case of success.
8366  * @since GDAL 3.3
8367  */
AddFieldDomain(CPL_UNUSED std::unique_ptr<OGRFieldDomain> && domain,std::string & failureReason)8368 bool GDALDataset::AddFieldDomain(CPL_UNUSED std::unique_ptr<OGRFieldDomain>&& domain,
8369                                  std::string& failureReason)
8370 {
8371     failureReason = "AddFieldDomain not supported by this driver";
8372     return false;
8373 }
8374 
8375 /************************************************************************/
8376 /*                     GDALDatasetAddFieldDomain()                      */
8377 /************************************************************************/
8378 
8379 /** Add a field domain to the dataset.
8380  *
8381  * Only a few drivers will support this operation, and some of them might only
8382  * support it only for some types of field domains.
8383  * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
8384  * support this operation. A dataset having at least some support for this
8385  * operation should report the ODsCAddFieldDomain dataset capability.
8386  *
8387  * Anticipated failures will not be emitted through the CPLError()
8388  * infrastructure, but will be reported in the ppszFailureReason output parameter.
8389  *
8390  * @param hDS                Dataset handle.
8391  * @param hFieldDomain       The domain definition. Contrary to the C++ version,
8392  *                           the passed object is copied.
8393  * @param ppszFailureReason  Output parameter. Will contain an error message if
8394  *                           an error occurs (*ppszFailureReason to be freed
8395  *                           with CPLFree). May be NULL.
8396  * @return true in case of success.
8397  * @since GDAL 3.3
8398  */
GDALDatasetAddFieldDomain(GDALDatasetH hDS,OGRFieldDomainH hFieldDomain,char ** ppszFailureReason)8399 bool GDALDatasetAddFieldDomain(GDALDatasetH hDS,
8400                                OGRFieldDomainH hFieldDomain,
8401                                char** ppszFailureReason)
8402 {
8403     VALIDATE_POINTER1(hDS, __func__, false);
8404     VALIDATE_POINTER1(hFieldDomain, __func__, false);
8405     auto poDomain = std::unique_ptr<OGRFieldDomain>(
8406                  OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
8407     if( poDomain == nullptr )
8408         return false;
8409     std::string failureReason;
8410     const bool bRet =
8411         GDALDataset::FromHandle(hDS)->AddFieldDomain(
8412              std::move(poDomain), failureReason);
8413     if( ppszFailureReason )
8414     {
8415         *ppszFailureReason = failureReason.empty() ?
8416                                 nullptr : CPLStrdup(failureReason.c_str());
8417     }
8418     return bRet;
8419 }
8420 
8421 //! @cond Doxygen_Suppress
8422 
8423 /************************************************************************/
8424 /*                       SetEnableOverviews()                           */
8425 /************************************************************************/
8426 
SetEnableOverviews(bool bEnable)8427 void GDALDataset::SetEnableOverviews(bool bEnable)
8428 {
8429     if( m_poPrivate )
8430     {
8431         m_poPrivate->m_bOverviewsEnabled = bEnable;
8432     }
8433 }
8434 
8435 /************************************************************************/
8436 /*                      AreOverviewsEnabled()                           */
8437 /************************************************************************/
8438 
AreOverviewsEnabled() const8439 bool GDALDataset::AreOverviewsEnabled() const
8440 {
8441     return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
8442 }
8443 
8444 //! @endcond
8445