LCOV - code coverage report
Current view: top level - gcore - gdaldataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 2097 2525 83.0 %
Date: 2024-11-21 22:18:42 Functions: 228 257 88.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Base class for raster file formats.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1998, 2003, Frank Warmerdam
       9             :  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "gdal.h"
      16             : #include "gdal_priv.h"
      17             : 
      18             : #include <climits>
      19             : #include <cstdarg>
      20             : #include <cstdio>
      21             : #include <cstdlib>
      22             : #include <cstring>
      23             : #include <algorithm>
      24             : #include <map>
      25             : #include <mutex>
      26             : #include <new>
      27             : #include <set>
      28             : #include <string>
      29             : #include <utility>
      30             : 
      31             : #include "cpl_conv.h"
      32             : #include "cpl_error.h"
      33             : #include "cpl_hash_set.h"
      34             : #include "cpl_multiproc.h"
      35             : #include "cpl_progress.h"
      36             : #include "cpl_string.h"
      37             : #include "cpl_vsi.h"
      38             : #include "cpl_vsi_error.h"
      39             : #include "ogr_api.h"
      40             : #include "ogr_attrind.h"
      41             : #include "ogr_core.h"
      42             : #include "ogr_feature.h"
      43             : #include "ogr_featurestyle.h"
      44             : #include "ogr_gensql.h"
      45             : #include "ogr_geometry.h"
      46             : #include "ogr_p.h"
      47             : #include "ogr_spatialref.h"
      48             : #include "ogr_srs_api.h"
      49             : #include "ograpispy.h"
      50             : #include "ogrsf_frmts.h"
      51             : #include "ogrunionlayer.h"
      52             : #include "ogr_swq.h"
      53             : 
      54             : #include "../frmts/derived/derivedlist.h"
      55             : 
      56             : #ifdef SQLITE_ENABLED
      57             : #include "../sqlite/ogrsqliteexecutesql.h"
      58             : #endif
      59             : 
      60             : extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
      61             : 
      62             : CPL_C_START
      63             : GDALAsyncReader *GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff,
      64             :                                            int nYOff, int nXSize, int nYSize,
      65             :                                            void *pBuf, int nBufXSize,
      66             :                                            int nBufYSize, GDALDataType eBufType,
      67             :                                            int nBandCount, int *panBandMap,
      68             :                                            int nPixelSpace, int nLineSpace,
      69             :                                            int nBandSpace, char **papszOptions);
      70             : CPL_C_END
      71             : 
      72             : enum class GDALAllowReadWriteMutexState
      73             : {
      74             :     RW_MUTEX_STATE_UNKNOWN,
      75             :     RW_MUTEX_STATE_ALLOWED,
      76             :     RW_MUTEX_STATE_DISABLED
      77             : };
      78             : 
      79             : const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
      80             : const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
      81             : 
      82             : class GDALDataset::Private
      83             : {
      84             :     CPL_DISALLOW_COPY_ASSIGN(Private)
      85             : 
      86             :   public:
      87             :     CPLMutex *hMutex = nullptr;
      88             :     std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
      89             : #ifdef DEBUG_EXTRA
      90             :     std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
      91             : #endif
      92             :     GDALAllowReadWriteMutexState eStateReadWriteMutex =
      93             :         GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
      94             :     int nCurrentLayerIdx = 0;
      95             :     int nLayerCount = -1;
      96             :     GIntBig nFeatureReadInLayer = 0;
      97             :     GIntBig nFeatureReadInDataset = 0;
      98             :     GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
      99             :     GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
     100             :     OGRLayer *poCurrentLayer = nullptr;
     101             : 
     102             :     std::mutex m_oMutexWKT{};
     103             : 
     104             :     char *m_pszWKTCached = nullptr;
     105             :     OGRSpatialReference *m_poSRSCached = nullptr;
     106             :     char *m_pszWKTGCPCached = nullptr;
     107             :     OGRSpatialReference *m_poSRSGCPCached = nullptr;
     108             : 
     109             :     GDALDataset *poParentDataset = nullptr;
     110             : 
     111             :     bool m_bOverviewsEnabled = true;
     112             : 
     113             :     std::vector<int>
     114             :         m_anBandMap{};  // used by RasterIO(). Values are 1, 2, etc.
     115             : 
     116      127103 :     Private() = default;
     117             : };
     118             : 
     119             : struct SharedDatasetCtxt
     120             : {
     121             :     // PID of the thread that mark the dataset as shared
     122             :     // This may not be the actual PID, but the responsiblePID.
     123             :     GIntBig nPID;
     124             :     char *pszDescription;
     125             :     char *pszConcatenatedOpenOptions;
     126             :     int nOpenFlags;
     127             : 
     128             :     GDALDataset *poDS;
     129             : };
     130             : 
     131             : // Set of datasets opened as shared datasets (with GDALOpenShared)
     132             : // The values in the set are of type SharedDatasetCtxt.
     133             : static CPLHashSet *phSharedDatasetSet = nullptr;
     134             : 
     135             : // Set of all datasets created in the constructor of GDALDataset.
     136             : // In the case of a shared dataset, memorize the PID of the thread
     137             : // that marked the dataset as shared, so that we can remove it from
     138             : // the phSharedDatasetSet in the destructor of the dataset, even
     139             : // if GDALClose is called from a different thread.
     140             : static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
     141             : 
     142             : static CPLMutex *hDLMutex = nullptr;
     143             : 
     144             : // Static array of all datasets. Used by GDALGetOpenDatasets.
     145             : // Not thread-safe. See GDALGetOpenDatasets.
     146             : static GDALDataset **ppDatasets = nullptr;
     147             : 
     148        8295 : static unsigned long GDALSharedDatasetHashFunc(const void *elt)
     149             : {
     150        8295 :     const SharedDatasetCtxt *psStruct =
     151             :         static_cast<const SharedDatasetCtxt *>(elt);
     152             :     return static_cast<unsigned long>(
     153        8295 :         CPLHashSetHashStr(psStruct->pszDescription) ^
     154        8295 :         CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^
     155        8295 :         psStruct->nOpenFlags ^ psStruct->nPID);
     156             : }
     157             : 
     158        6932 : static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)
     159             : {
     160        6932 :     const SharedDatasetCtxt *psStruct1 =
     161             :         static_cast<const SharedDatasetCtxt *>(elt1);
     162        6932 :     const SharedDatasetCtxt *psStruct2 =
     163             :         static_cast<const SharedDatasetCtxt *>(elt2);
     164       13817 :     return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
     165        6885 :            strcmp(psStruct1->pszConcatenatedOpenOptions,
     166        6885 :                   psStruct2->pszConcatenatedOpenOptions) == 0 &&
     167       20702 :            psStruct1->nPID == psStruct2->nPID &&
     168       13817 :            psStruct1->nOpenFlags == psStruct2->nOpenFlags;
     169             : }
     170             : 
     171         390 : static void GDALSharedDatasetFreeFunc(void *elt)
     172             : {
     173         390 :     SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
     174         390 :     CPLFree(psStruct->pszDescription);
     175         390 :     CPLFree(psStruct->pszConcatenatedOpenOptions);
     176         390 :     CPLFree(psStruct);
     177         390 : }
     178             : 
     179             : static std::string
     180        7006 : GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)
     181             : {
     182        7006 :     std::string osStr;
     183        7019 :     for (const char *pszOption : cpl::Iterate(papszOpenOptions))
     184          13 :         osStr += pszOption;
     185        7006 :     return osStr;
     186             : }
     187             : 
     188             : /************************************************************************/
     189             : /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
     190             : /************************************************************************/
     191             : 
     192             : // The open-shared mutex must be used by the ProxyPool too.
     193       60981 : CPLMutex **GDALGetphDLMutex()
     194             : {
     195       60981 :     return &hDLMutex;
     196             : }
     197             : 
     198             : // The current thread will act in the behalf of the thread of PID
     199             : // responsiblePID.
     200       53728 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
     201             : {
     202             :     GIntBig *pResponsiblePID =
     203       53728 :         static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
     204       53728 :     if (pResponsiblePID == nullptr)
     205             :     {
     206         167 :         pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
     207         167 :         CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
     208             :     }
     209       53728 :     *pResponsiblePID = responsiblePID;
     210       53728 : }
     211             : 
     212             : // Get the PID of the thread that the current thread will act in the behalf of
     213             : // By default : the current thread acts in the behalf of itself.
     214      162724 : GIntBig GDALGetResponsiblePIDForCurrentThread()
     215             : {
     216             :     GIntBig *pResponsiblePID =
     217      162724 :         static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
     218      162627 :     if (pResponsiblePID == nullptr)
     219       45323 :         return CPLGetPID();
     220      117304 :     return *pResponsiblePID;
     221             : }
     222             : 
     223             : /************************************************************************/
     224             : /* ==================================================================== */
     225             : /*                             GDALDataset                              */
     226             : /* ==================================================================== */
     227             : /************************************************************************/
     228             : 
     229             : /**
     230             :  * \class GDALDataset "gdal_priv.h"
     231             :  *
     232             :  * A dataset encapsulating one or more raster bands.  Details are further
     233             :  * discussed in the <a href="https://gdal.org/user/raster_data_model.html">GDAL
     234             :  * Raster Data Model</a>.
     235             :  *
     236             :  * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
     237             :  * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
     238             :  * dataset.
     239             :  */
     240             : 
     241             : /************************************************************************/
     242             : /*                            GDALDataset()                             */
     243             : /************************************************************************/
     244             : 
     245             : //! @cond Doxygen_Suppress
     246      111211 : GDALDataset::GDALDataset()
     247      111211 :     : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
     248             : {
     249      111134 : }
     250             : 
     251      127121 : GDALDataset::GDALDataset(int bForceCachedIOIn)
     252      127021 :     : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
     253      127121 :       m_poPrivate(new(std::nothrow) GDALDataset::Private)
     254             : {
     255      127070 : }
     256             : 
     257             : //! @endcond
     258             : 
     259             : /************************************************************************/
     260             : /*                            ~GDALDataset()                            */
     261             : /************************************************************************/
     262             : 
     263             : /**
     264             :  * \brief Destroy an open GDALDataset.
     265             :  *
     266             :  * This is the accepted method of closing a GDAL dataset and deallocating
     267             :  * all resources associated with it.
     268             :  *
     269             :  * Equivalent of the C callable GDALClose().  Except that GDALClose() first
     270             :  * decrements the reference count, and then closes only if it has dropped to
     271             :  * zero.
     272             :  *
     273             :  * For Windows users, it is not recommended to use the delete operator on the
     274             :  * dataset object because of known issues when allocating and freeing memory
     275             :  * across module boundaries. Calling GDALClose() is then a better option.
     276             :  */
     277             : 
     278      127118 : GDALDataset::~GDALDataset()
     279             : 
     280             : {
     281             :     // we don't want to report destruction of datasets that
     282             :     // were never really open or meant as internal
     283      127117 :     if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))
     284             :     {
     285       59945 :         if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
     286         208 :             CPLDebug("GDAL",
     287             :                      "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
     288         208 :                      GetDescription(), this, static_cast<int>(CPLGetPID()),
     289         208 :                      static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
     290             :         else
     291       59763 :             CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
     292             :     }
     293             : 
     294      127164 :     if (IsMarkedSuppressOnClose())
     295             :     {
     296        2120 :         if (poDriver == nullptr ||
     297             :             // Someone issuing Create("foo.tif") on a
     298             :             // memory driver doesn't expect files with those names to be deleted
     299             :             // on a file system...
     300             :             // This is somewhat messy. Ideally there should be a way for the
     301             :             // driver to overload the default behavior
     302        1055 :             (!EQUAL(poDriver->GetDescription(), "MEM") &&
     303        1031 :              !EQUAL(poDriver->GetDescription(), "Memory")))
     304             :         {
     305        1041 :             VSIUnlink(GetDescription());
     306             :         }
     307             :     }
     308             : 
     309             :     /* -------------------------------------------------------------------- */
     310             :     /*      Remove dataset from the "open" dataset list.                    */
     311             :     /* -------------------------------------------------------------------- */
     312      127129 :     if (!bIsInternal)
     313             :     {
     314      121276 :         CPLMutexHolderD(&hDLMutex);
     315       60638 :         if (poAllDatasetMap)
     316             :         {
     317             :             std::map<GDALDataset *, GIntBig>::iterator oIter =
     318       60638 :                 poAllDatasetMap->find(this);
     319       60638 :             CPLAssert(oIter != poAllDatasetMap->end());
     320             : 
     321       60638 :             UnregisterFromSharedDataset();
     322             : 
     323       60638 :             poAllDatasetMap->erase(oIter);
     324             : 
     325       60638 :             if (poAllDatasetMap->empty())
     326             :             {
     327       24225 :                 delete poAllDatasetMap;
     328       24225 :                 poAllDatasetMap = nullptr;
     329       24225 :                 if (phSharedDatasetSet)
     330             :                 {
     331         270 :                     CPLHashSetDestroy(phSharedDatasetSet);
     332             :                 }
     333       24225 :                 phSharedDatasetSet = nullptr;
     334       24225 :                 CPLFree(ppDatasets);
     335       24225 :                 ppDatasets = nullptr;
     336             :             }
     337             :         }
     338             :     }
     339             : 
     340             :     /* -------------------------------------------------------------------- */
     341             :     /*      Destroy the raster bands if they exist.                         */
     342             :     /* -------------------------------------------------------------------- */
     343      941976 :     for (int i = 0; i < nBands && papoBands != nullptr; ++i)
     344             :     {
     345      814851 :         if (papoBands[i] != nullptr)
     346      814851 :             delete papoBands[i];
     347      814847 :         papoBands[i] = nullptr;
     348             :     }
     349             : 
     350      127125 :     CPLFree(papoBands);
     351             : 
     352      127120 :     if (m_poStyleTable)
     353             :     {
     354          23 :         delete m_poStyleTable;
     355          23 :         m_poStyleTable = nullptr;
     356             :     }
     357             : 
     358      127120 :     if (m_poPrivate != nullptr)
     359             :     {
     360      127121 :         if (m_poPrivate->hMutex != nullptr)
     361       14471 :             CPLDestroyMutex(m_poPrivate->hMutex);
     362             : 
     363             :         // coverity[missing_lock]
     364      127121 :         CPLFree(m_poPrivate->m_pszWKTCached);
     365      127114 :         if (m_poPrivate->m_poSRSCached)
     366             :         {
     367           0 :             m_poPrivate->m_poSRSCached->Release();
     368             :         }
     369             :         // coverity[missing_lock]
     370      127114 :         CPLFree(m_poPrivate->m_pszWKTGCPCached);
     371      127114 :         if (m_poPrivate->m_poSRSGCPCached)
     372             :         {
     373           0 :             m_poPrivate->m_poSRSGCPCached->Release();
     374             :         }
     375             :     }
     376             : 
     377      127113 :     delete m_poPrivate;
     378             : 
     379      127116 :     CSLDestroy(papszOpenOptions);
     380      127117 : }
     381             : 
     382             : /************************************************************************/
     383             : /*                             Close()                                  */
     384             : /************************************************************************/
     385             : 
     386             : /** Do final cleanup before a dataset is destroyed.
     387             :  *
     388             :  * This method is typically called by GDALClose() or the destructor of a
     389             :  * GDALDataset subclass. It might also be called by C++ users before
     390             :  * destroying a dataset. It should not be called on a shared dataset whose
     391             :  * reference count is greater than one.
     392             :  *
     393             :  * It gives a last chance to the closing process to return an error code if
     394             :  * something goes wrong, in particular in creation / update scenarios where
     395             :  * file write or network communication might occur when finalizing the dataset.
     396             :  *
     397             :  * Implementations should be robust to this method to be called several times
     398             :  * (on subsequent calls, it should do nothing and return CE_None).
     399             :  * Once it has been called, no other method than Close() or the dataset
     400             :  * destructor should be called. RasterBand or OGRLayer owned by the dataset
     401             :  * should be assumed as no longer being valid.
     402             :  *
     403             :  * If a driver implements this method, it must also call it from its
     404             :  * dataset destructor.
     405             :  *
     406             :  * A typical implementation might look as the following
     407             :  * \code{.cpp}
     408             :  *
     409             :  *  MyDataset::~MyDataset()
     410             :  *  {
     411             :  *     try
     412             :  *     {
     413             :  *         MyDataset::Close();
     414             :  *     }
     415             :  *     catch (const std::exception &exc)
     416             :  *     {
     417             :  *         // If Close() can throw exception
     418             :  *         CPLError(CE_Failure, CPLE_AppDefined,
     419             :  *                  "Exception thrown in MyDataset::Close(): %s",
     420             :  *                  exc.what());
     421             :  *     }
     422             :  *     catch (...)
     423             :  *     {
     424             :  *         // If Close() can throw exception
     425             :  *         CPLError(CE_Failure, CPLE_AppDefined,
     426             :  *                  "Exception thrown in MyDataset::Close()");
     427             :  *     }
     428             :  *  }
     429             :  *
     430             :  *  CPLErr MyDataset::Close()
     431             :  *  {
     432             :  *      CPLErr eErr = CE_None;
     433             :  *      if( nOpenFlags != OPEN_FLAGS_CLOSED )
     434             :  *      {
     435             :  *          if( MyDataset::FlushCache(true) != CE_None )
     436             :  *              eErr = CE_Failure;
     437             :  *
     438             :  *          // Do something driver specific
     439             :  *          if (m_fpImage)
     440             :  *          {
     441             :  *              if( VSIFCloseL(m_fpImage) != 0 )
     442             :  *              {
     443             :  *                  CPLError(CE_Failure, CPLE_FileIO, "VSIFCloseL() failed");
     444             :  *                  eErr = CE_Failure;
     445             :  *              }
     446             :  *          }
     447             :  *
     448             :  *          // Call parent Close() implementation.
     449             :  *          if( MyParentDatasetClass::Close() != CE_None )
     450             :  *              eErr = CE_Failure;
     451             :  *      }
     452             :  *      return eErr;
     453             :  *  }
     454             :  * \endcode
     455             :  *
     456             :  * @since GDAL 3.7
     457             :  */
     458       75154 : CPLErr GDALDataset::Close()
     459             : {
     460             :     // Call UnregisterFromSharedDataset() before altering nOpenFlags
     461       75154 :     UnregisterFromSharedDataset();
     462             : 
     463       75152 :     nOpenFlags = OPEN_FLAGS_CLOSED;
     464       75152 :     return CE_None;
     465             : }
     466             : 
     467             : /************************************************************************/
     468             : /*                UnregisterFromSharedDataset()                         */
     469             : /************************************************************************/
     470             : 
     471      135790 : void GDALDataset::UnregisterFromSharedDataset()
     472             : {
     473      135790 :     if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))
     474      135400 :         return;
     475             : 
     476         780 :     CPLMutexHolderD(&hDLMutex);
     477             : 
     478             :     std::map<GDALDataset *, GIntBig>::iterator oIter =
     479         390 :         poAllDatasetMap->find(this);
     480         390 :     CPLAssert(oIter != poAllDatasetMap->end());
     481         390 :     const GIntBig nPIDCreatorForShared = oIter->second;
     482         390 :     bShared = false;
     483             :     SharedDatasetCtxt sStruct;
     484         390 :     sStruct.nPID = nPIDCreatorForShared;
     485         390 :     sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
     486         390 :     sStruct.pszDescription = const_cast<char *>(GetDescription());
     487             :     std::string osConcatenatedOpenOptions =
     488         780 :         GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
     489         390 :     sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
     490         390 :     sStruct.poDS = nullptr;
     491             :     SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
     492         390 :         CPLHashSetLookup(phSharedDatasetSet, &sStruct));
     493         390 :     if (psStruct && psStruct->poDS == this)
     494             :     {
     495         389 :         CPLHashSetRemove(phSharedDatasetSet, psStruct);
     496             :     }
     497             :     else
     498             :     {
     499           1 :         CPLDebug("GDAL",
     500             :                  "Should not happen. Cannot find %s, "
     501             :                  "this=%p in phSharedDatasetSet",
     502           1 :                  GetDescription(), this);
     503             :     }
     504             : }
     505             : 
     506             : /************************************************************************/
     507             : /*                      AddToDatasetOpenList()                          */
     508             : /************************************************************************/
     509             : 
     510       62022 : void GDALDataset::AddToDatasetOpenList()
     511             : {
     512             :     /* -------------------------------------------------------------------- */
     513             :     /*      Add this dataset to the open dataset list.                      */
     514             :     /* -------------------------------------------------------------------- */
     515       62022 :     bIsInternal = false;
     516             : 
     517       62022 :     CPLMutexHolderD(&hDLMutex);
     518             : 
     519       62022 :     if (poAllDatasetMap == nullptr)
     520       24228 :         poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
     521       62022 :     (*poAllDatasetMap)[this] = -1;
     522       62021 : }
     523             : 
     524             : /************************************************************************/
     525             : /*                             FlushCache()                             */
     526             : /************************************************************************/
     527             : 
     528             : /**
     529             :  * \brief Flush all write cached data to disk.
     530             :  *
     531             :  * Any raster (or other GDAL) data written via GDAL calls, but buffered
     532             :  * internally will be written to disk.
     533             :  *
     534             :  * The default implementation of this method just calls the FlushCache() method
     535             :  * on each of the raster bands and the SyncToDisk() method
     536             :  * on each of the layers.  Conceptually, calling FlushCache() on a dataset
     537             :  * should include any work that might be accomplished by calling SyncToDisk()
     538             :  * on layers in that dataset.
     539             :  *
     540             :  * Using this method does not prevent use from calling GDALClose()
     541             :  * to properly close a dataset and ensure that important data not addressed
     542             :  * by FlushCache() is written in the file.
     543             :  *
     544             :  * This method is the same as the C function GDALFlushCache().
     545             :  *
     546             :  * @param bAtClosing Whether this is called from a GDALDataset destructor
     547             :  * @return CE_None in case of success (note: return value added in GDAL 3.7)
     548             :  */
     549             : 
     550       94721 : CPLErr GDALDataset::FlushCache(bool bAtClosing)
     551             : 
     552             : {
     553       94721 :     CPLErr eErr = CE_None;
     554             :     // This sometimes happens if a dataset is destroyed before completely
     555             :     // built.
     556             : 
     557       94721 :     if (papoBands)
     558             :     {
     559     1265690 :         for (int i = 0; i < nBands; ++i)
     560             :         {
     561     1178570 :             if (papoBands[i])
     562             :             {
     563     1178570 :                 if (papoBands[i]->FlushCache(bAtClosing) != CE_None)
     564           7 :                     eErr = CE_Failure;
     565             :             }
     566             :         }
     567             :     }
     568             : 
     569       94721 :     const int nLayers = GetLayerCount();
     570             :     // cppcheck-suppress knownConditionTrueFalse
     571       94721 :     if (nLayers > 0)
     572             :     {
     573        6890 :         CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
     574       11811 :         for (int i = 0; i < nLayers; ++i)
     575             :         {
     576        8366 :             OGRLayer *poLayer = GetLayer(i);
     577             : 
     578        8366 :             if (poLayer)
     579             :             {
     580        8366 :                 if (poLayer->SyncToDisk() != OGRERR_NONE)
     581           0 :                     eErr = CE_Failure;
     582             :             }
     583             :         }
     584             :     }
     585             : 
     586       94721 :     return eErr;
     587             : }
     588             : 
     589             : /************************************************************************/
     590             : /*                           GDALFlushCache()                           */
     591             : /************************************************************************/
     592             : 
     593             : /**
     594             :  * \brief Flush all write cached data to disk.
     595             :  *
     596             :  * @see GDALDataset::FlushCache().
     597             :  * @return CE_None in case of success (note: return value added in GDAL 3.7)
     598             :  */
     599             : 
     600        4198 : CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)
     601             : 
     602             : {
     603        4198 :     VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);
     604             : 
     605        4198 :     return GDALDataset::FromHandle(hDS)->FlushCache(false);
     606             : }
     607             : 
     608             : /************************************************************************/
     609             : /*                             DropCache()                              */
     610             : /************************************************************************/
     611             : 
     612             : /**
     613             : * \brief Drop all write cached data
     614             : *
     615             : * This method is the same as the C function GDALDropCache().
     616             : *
     617             : * @return CE_None in case of success
     618             : * @since 3.9
     619             : */
     620             : 
     621           1 : CPLErr GDALDataset::DropCache()
     622             : 
     623             : {
     624           1 :     CPLErr eErr = CE_None;
     625             : 
     626           1 :     if (papoBands)
     627             :     {
     628           2 :         for (int i = 0; i < nBands; ++i)
     629             :         {
     630           1 :             if (papoBands[i])
     631             :             {
     632           1 :                 if (papoBands[i]->DropCache() != CE_None)
     633           0 :                     eErr = CE_Failure;
     634             :             }
     635             :         }
     636             :     }
     637             : 
     638           1 :     return eErr;
     639             : }
     640             : 
     641             : /************************************************************************/
     642             : /*                           GDALDropCache()                           */
     643             : /************************************************************************/
     644             : 
     645             : /**
     646             : * \brief Drop all write cached data
     647             : *
     648             : * @see GDALDataset::DropCache().
     649             : * @return CE_None in case of success
     650             : * @since 3.9
     651             : */
     652             : 
     653           0 : CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS)
     654             : 
     655             : {
     656           0 :     VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure);
     657             : 
     658           0 :     return GDALDataset::FromHandle(hDS)->DropCache();
     659             : }
     660             : 
     661             : /************************************************************************/
     662             : /*                      GetEstimatedRAMUsage()                          */
     663             : /************************************************************************/
     664             : 
     665             : /**
     666             :  * \brief Return the intrinsic RAM usage of this dataset.
     667             :  *
     668             :  * The returned value should take into account caches in the underlying driver
     669             :  * and decoding library, but not the usage related to the GDAL block cache.
     670             :  *
     671             :  * At time of writing, this method is only implemented in the JP2OpenJPEG
     672             :  * driver. For single-tiled JPEG2000 images, the decoding of the image,
     673             :  * even partially, involves allocating at least
     674             :  * width * height * number_of_bands * sizeof(uint32_t) bytes inside the libopenjp2
     675             :  * library.
     676             :  *
     677             :  * This method is used by the GDALDatasetPool class, itself used by the GDAL VRT
     678             :  * driver, to determine how long a dataset in the pool must be kept open, given
     679             :  * the RAM usage of the dataset with respect to the usable total RAM.
     680             :  *
     681             :  * @since GDAL 3.7
     682             :  * @return RAM usage in bytes, or -1 if unknown (the default implementation
     683             :  * returns -1)
     684             :  */
     685             : 
     686        1072 : GIntBig GDALDataset::GetEstimatedRAMUsage()
     687             : {
     688        1072 :     return -1;
     689             : }
     690             : 
     691             : /************************************************************************/
     692             : /*                        BlockBasedFlushCache()                        */
     693             : /*                                                                      */
     694             : /*      This helper method can be called by the                         */
     695             : /*      GDALDataset::FlushCache() for particular drivers to ensure      */
     696             : /*      that buffers will be flushed in a manner suitable for pixel     */
     697             : /*      interleaved (by block) IO.  That is, if all the bands have      */
     698             : /*      the same size blocks then a given block will be flushed for     */
     699             : /*      all bands before proceeding to the next block.                  */
     700             : /************************************************************************/
     701             : 
     702             : //! @cond Doxygen_Suppress
     703         346 : CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)
     704             : 
     705             : {
     706         346 :     GDALRasterBand *poBand1 = GetRasterBand(1);
     707         346 :     if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))
     708             :     {
     709           7 :         return GDALDataset::FlushCache(bAtClosing);
     710             :     }
     711             : 
     712         339 :     int nBlockXSize = 0;
     713         339 :     int nBlockYSize = 0;
     714         339 :     poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
     715             : 
     716             :     /* -------------------------------------------------------------------- */
     717             :     /*      Verify that all bands match.                                    */
     718             :     /* -------------------------------------------------------------------- */
     719        1104 :     for (int iBand = 1; iBand < nBands; ++iBand)
     720             :     {
     721         765 :         GDALRasterBand *poBand = GetRasterBand(iBand + 1);
     722             : 
     723             :         int nThisBlockXSize, nThisBlockYSize;
     724         765 :         poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
     725         765 :         if (nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize)
     726             :         {
     727           0 :             return GDALDataset::FlushCache(bAtClosing);
     728             :         }
     729             :     }
     730             : 
     731             :     /* -------------------------------------------------------------------- */
     732             :     /*      Now flush writable data.                                        */
     733             :     /* -------------------------------------------------------------------- */
     734         790 :     for (int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY)
     735             :     {
     736         991 :         for (int iX = 0; iX < poBand1->nBlocksPerRow; ++iX)
     737             :         {
     738        1690 :             for (int iBand = 0; iBand < nBands; ++iBand)
     739             :             {
     740        1150 :                 const CPLErr eErr = papoBands[iBand]->FlushBlock(iX, iY);
     741             : 
     742        1150 :                 if (eErr != CE_None)
     743           0 :                     return CE_Failure;
     744             :             }
     745             :         }
     746             :     }
     747         339 :     return CE_None;
     748             : }
     749             : 
     750             : /************************************************************************/
     751             : /*                          RasterInitialize()                          */
     752             : /*                                                                      */
     753             : /*      Initialize raster size                                          */
     754             : /************************************************************************/
     755             : 
     756           0 : void GDALDataset::RasterInitialize(int nXSize, int nYSize)
     757             : 
     758             : {
     759           0 :     CPLAssert(nXSize > 0 && nYSize > 0);
     760             : 
     761           0 :     nRasterXSize = nXSize;
     762           0 :     nRasterYSize = nYSize;
     763           0 : }
     764             : 
     765             : //! @endcond
     766             : 
     767             : /************************************************************************/
     768             : /*                              AddBand()                               */
     769             : /************************************************************************/
     770             : 
     771             : /**
     772             :  * \fn GDALDataset::AddBand(GDALDataType, char**)
     773             :  * \brief Add a band to a dataset.
     774             :  *
     775             :  * This method will add a new band to the dataset if the underlying format
     776             :  * supports this action.  Most formats do not.
     777             :  *
     778             :  * Note that the new GDALRasterBand is not returned.  It may be fetched
     779             :  * after successful completion of the method by calling
     780             :  * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
     781             :  * band will always be the last band.
     782             :  *
     783             :  * @param eType the data type of the pixels in the new band.
     784             :  *
     785             :  * @param papszOptions a list of NAME=VALUE option strings.  The supported
     786             :  * options are format specific.  NULL may be passed by default.
     787             :  *
     788             :  * @return CE_None on success or CE_Failure on failure.
     789             :  */
     790             : 
     791           0 : CPLErr GDALDataset::AddBand(CPL_UNUSED GDALDataType eType,
     792             :                             CPL_UNUSED char **papszOptions)
     793             : 
     794             : {
     795           0 :     ReportError(CE_Failure, CPLE_NotSupported,
     796             :                 "Dataset does not support the AddBand() method.");
     797             : 
     798           0 :     return CE_Failure;
     799             : }
     800             : 
     801             : /************************************************************************/
     802             : /*                            GDALAddBand()                             */
     803             : /************************************************************************/
     804             : 
     805             : /**
     806             :  * \brief Add a band to a dataset.
     807             :  *
     808             :  * @see GDALDataset::AddBand().
     809             :  */
     810             : 
     811          61 : CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,
     812             :                                CSLConstList papszOptions)
     813             : 
     814             : {
     815          61 :     VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
     816             : 
     817         122 :     return GDALDataset::FromHandle(hDataset)->AddBand(
     818          61 :         eType, const_cast<char **>(papszOptions));
     819             : }
     820             : 
     821             : /************************************************************************/
     822             : /*                              SetBand()                               */
     823             : /************************************************************************/
     824             : 
     825             : //! @cond Doxygen_Suppress
     826             : /**  Set a band in the band array, updating the band count, and array size
     827             :  * appropriately.
     828             :  *
     829             :  * @param nNewBand new band number (indexing starts at 1)
     830             :  * @param poBand band object.
     831             :  */
     832             : 
     833     1029790 : void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)
     834             : 
     835             : {
     836             :     /* -------------------------------------------------------------------- */
     837             :     /*      Do we need to grow the bands list?                              */
     838             :     /* -------------------------------------------------------------------- */
     839     1029790 :     if (nBands < nNewBand || papoBands == nullptr)
     840             :     {
     841      529182 :         GDALRasterBand **papoNewBands = nullptr;
     842             : 
     843      529182 :         if (papoBands == nullptr)
     844       77924 :             papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
     845       77890 :                 sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
     846             :         else
     847             :             papoNewBands = static_cast<GDALRasterBand **>(
     848      451266 :                 VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
     849      451292 :                                           std::max(nNewBand, nBands)));
     850      529190 :         if (papoNewBands == nullptr)
     851             :         {
     852           0 :             ReportError(CE_Failure, CPLE_OutOfMemory,
     853             :                         "Cannot allocate band array");
     854           0 :             return;
     855             :         }
     856             : 
     857      529190 :         papoBands = papoNewBands;
     858             : 
     859     1013710 :         for (int i = nBands; i < nNewBand; ++i)
     860      484518 :             papoBands[i] = nullptr;
     861             : 
     862      529190 :         nBands = std::max(nBands, nNewBand);
     863             : 
     864      529164 :         if (m_poPrivate)
     865             :         {
     866      529282 :             for (int i = static_cast<int>(m_poPrivate->m_anBandMap.size());
     867     1558900 :                  i < nBands; ++i)
     868             :             {
     869     1029700 :                 m_poPrivate->m_anBandMap.push_back(i + 1);
     870             :             }
     871             :         }
     872             :     }
     873             : 
     874             :     /* -------------------------------------------------------------------- */
     875             :     /*      Set the band.  Resetting the band is currently not permitted.   */
     876             :     /* -------------------------------------------------------------------- */
     877     1029700 :     if (papoBands[nNewBand - 1] != nullptr)
     878             :     {
     879           0 :         ReportError(CE_Failure, CPLE_NotSupported,
     880             :                     "Cannot set band %d as it is already set", nNewBand);
     881           0 :         return;
     882             :     }
     883             : 
     884     1029700 :     papoBands[nNewBand - 1] = poBand;
     885             : 
     886             :     /* -------------------------------------------------------------------- */
     887             :     /*      Set back reference information on the raster band.  Note        */
     888             :     /*      that the GDALDataset is a friend of the GDALRasterBand          */
     889             :     /*      specifically to allow this.                                     */
     890             :     /* -------------------------------------------------------------------- */
     891     1029700 :     poBand->nBand = nNewBand;
     892     1029700 :     poBand->poDS = this;
     893     1029700 :     poBand->nRasterXSize = nRasterXSize;
     894     1029700 :     poBand->nRasterYSize = nRasterYSize;
     895     1029700 :     poBand->eAccess = eAccess;  // Default access to be same as dataset.
     896             : }
     897             : 
     898             : //! @endcond
     899             : 
     900             : /************************************************************************/
     901             : /*                              SetBand()                               */
     902             : /************************************************************************/
     903             : 
     904             : //! @cond Doxygen_Suppress
     905             : /**  Set a band in the band array, updating the band count, and array size
     906             :  * appropriately.
     907             :  *
     908             :  * @param nNewBand new band number (indexing starts at 1)
     909             :  * @param poBand band object.
     910             :  */
     911             : 
     912        4672 : void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)
     913             : {
     914        4672 :     SetBand(nNewBand, poBand.release());
     915        4672 : }
     916             : 
     917             : //! @endcond
     918             : 
     919             : /************************************************************************/
     920             : /*                           GetRasterXSize()                           */
     921             : /************************************************************************/
     922             : 
     923             : /**
     924             : 
     925             :  \brief Fetch raster width in pixels.
     926             : 
     927             :  Equivalent of the C function GDALGetRasterXSize().
     928             : 
     929             :  @return the width in pixels of raster bands in this GDALDataset.
     930             : 
     931             : */
     932             : 
     933      378420 : int GDALDataset::GetRasterXSize() const
     934             : {
     935      378420 :     return nRasterXSize;
     936             : }
     937             : 
     938             : /************************************************************************/
     939             : /*                         GDALGetRasterXSize()                         */
     940             : /************************************************************************/
     941             : 
     942             : /**
     943             :  * \brief Fetch raster width in pixels.
     944             :  *
     945             :  * @see GDALDataset::GetRasterXSize().
     946             :  */
     947             : 
     948       31814 : int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)
     949             : 
     950             : {
     951       31814 :     VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
     952             : 
     953       31814 :     return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
     954             : }
     955             : 
     956             : /************************************************************************/
     957             : /*                           GetRasterYSize()                           */
     958             : /************************************************************************/
     959             : 
     960             : /**
     961             : 
     962             :  \brief Fetch raster height in pixels.
     963             : 
     964             :  Equivalent of the C function GDALGetRasterYSize().
     965             : 
     966             :  @return the height in pixels of raster bands in this GDALDataset.
     967             : 
     968             : */
     969             : 
     970      279398 : int GDALDataset::GetRasterYSize() const
     971             : {
     972      279398 :     return nRasterYSize;
     973             : }
     974             : 
     975             : /************************************************************************/
     976             : /*                         GDALGetRasterYSize()                         */
     977             : /************************************************************************/
     978             : 
     979             : /**
     980             :  * \brief Fetch raster height in pixels.
     981             :  *
     982             :  * @see GDALDataset::GetRasterYSize().
     983             :  */
     984             : 
     985       31531 : int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)
     986             : 
     987             : {
     988       31531 :     VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
     989             : 
     990       31531 :     return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
     991             : }
     992             : 
     993             : /************************************************************************/
     994             : /*                           GetRasterBand()                            */
     995             : /************************************************************************/
     996             : 
     997             : /**
     998             : 
     999             :  \brief Fetch a band object for a dataset.
    1000             : 
    1001             :  See GetBands() for a C++ iterator version of this method.
    1002             : 
    1003             :  Equivalent of the C function GDALGetRasterBand().
    1004             : 
    1005             :  @param nBandId the index number of the band to fetch, from 1 to
    1006             :                 GetRasterCount().
    1007             : 
    1008             :  @return the nBandId th band object
    1009             : 
    1010             : */
    1011             : 
    1012     9124160 : GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)
    1013             : 
    1014             : {
    1015     9124160 :     if (papoBands)
    1016             :     {
    1017     9119080 :         if (nBandId < 1 || nBandId > nBands)
    1018             :         {
    1019        6828 :             ReportError(CE_Failure, CPLE_IllegalArg,
    1020             :                         "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
    1021             :                         nBandId);
    1022          13 :             return nullptr;
    1023             :         }
    1024             : 
    1025     9112260 :         return papoBands[nBandId - 1];
    1026             :     }
    1027        5073 :     return nullptr;
    1028             : }
    1029             : 
    1030             : /************************************************************************/
    1031             : /*                           GetRasterBand()                            */
    1032             : /************************************************************************/
    1033             : 
    1034             : /**
    1035             : 
    1036             :  \brief Fetch a band object for a dataset.
    1037             : 
    1038             :  See GetBands() for a C++ iterator version of this method.
    1039             : 
    1040             :  Equivalent of the C function GDALGetRasterBand().
    1041             : 
    1042             :  @param nBandId the index number of the band to fetch, from 1 to
    1043             :                 GetRasterCount().
    1044             : 
    1045             :  @return the nBandId th band object
    1046             : 
    1047             : */
    1048             : 
    1049           0 : const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const
    1050             : 
    1051             : {
    1052           0 :     if (papoBands)
    1053             :     {
    1054           0 :         if (nBandId < 1 || nBandId > nBands)
    1055             :         {
    1056           0 :             ReportError(CE_Failure, CPLE_IllegalArg,
    1057             :                         "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
    1058             :                         nBandId);
    1059           0 :             return nullptr;
    1060             :         }
    1061             : 
    1062           0 :         return papoBands[nBandId - 1];
    1063             :     }
    1064           0 :     return nullptr;
    1065             : }
    1066             : 
    1067             : /************************************************************************/
    1068             : /*                         GDALGetRasterBand()                          */
    1069             : /************************************************************************/
    1070             : 
    1071             : /**
    1072             :  * \brief Fetch a band object for a dataset.
    1073             :  * @see GDALDataset::GetRasterBand().
    1074             :  */
    1075             : 
    1076      282579 : GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)
    1077             : 
    1078             : {
    1079      282579 :     VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
    1080             : 
    1081      282579 :     return GDALRasterBand::ToHandle(
    1082      282580 :         GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
    1083             : }
    1084             : 
    1085             : /************************************************************************/
    1086             : /*                           GetRasterCount()                           */
    1087             : /************************************************************************/
    1088             : 
    1089             : /**
    1090             :  * \brief Fetch the number of raster bands on this dataset.
    1091             :  *
    1092             :  * Same as the C function GDALGetRasterCount().
    1093             :  *
    1094             :  * @return the number of raster bands.
    1095             :  */
    1096             : 
    1097     4139980 : int GDALDataset::GetRasterCount() const
    1098             : {
    1099     4139980 :     return papoBands ? nBands : 0;
    1100             : }
    1101             : 
    1102             : /************************************************************************/
    1103             : /*                         GDALGetRasterCount()                         */
    1104             : /************************************************************************/
    1105             : 
    1106             : /**
    1107             :  * \brief Fetch the number of raster bands on this dataset.
    1108             :  *
    1109             :  * @see GDALDataset::GetRasterCount().
    1110             :  */
    1111             : 
    1112      373401 : int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)
    1113             : 
    1114             : {
    1115      373401 :     VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
    1116             : 
    1117      373401 :     return GDALDataset::FromHandle(hDS)->GetRasterCount();
    1118             : }
    1119             : 
    1120             : /************************************************************************/
    1121             : /*                          GetProjectionRef()                          */
    1122             : /************************************************************************/
    1123             : 
    1124             : /**
    1125             :  * \brief Fetch the projection definition string for this dataset.
    1126             :  *
    1127             :  * Same as the C function GDALGetProjectionRef().
    1128             :  *
    1129             :  * The returned string defines the projection coordinate system of the
    1130             :  * image in OpenGIS WKT format.  It should be suitable for use with the
    1131             :  * OGRSpatialReference class.
    1132             :  *
    1133             :  * When a projection definition is not available an empty (but not NULL)
    1134             :  * string is returned.
    1135             :  *
    1136             :  * \note Starting with GDAL 3.0, this is a compatibility layer around
    1137             :  * GetSpatialRef()
    1138             :  *
    1139             :  * @return a pointer to an internal projection reference string.  It should
    1140             :  * not be altered, freed or expected to last for long.
    1141             :  *
    1142             :  * @see https://gdal.org/tutorials/osr_api_tut.html
    1143             :  */
    1144             : 
    1145        6037 : const char *GDALDataset::GetProjectionRef() const
    1146             : {
    1147        6037 :     const auto poSRS = GetSpatialRef();
    1148        6037 :     if (!poSRS || !m_poPrivate)
    1149             :     {
    1150        2551 :         return "";
    1151             :     }
    1152        3486 :     char *pszWKT = nullptr;
    1153        3486 :     poSRS->exportToWkt(&pszWKT);
    1154        3486 :     if (!pszWKT)
    1155             :     {
    1156           0 :         return "";
    1157             :     }
    1158             : 
    1159             :     // If called on a thread-safe dataset, we might be called by several
    1160             :     // threads, so make sure our accesses to m_pszWKTCached are protected
    1161             :     // by a mutex.
    1162        6972 :     std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
    1163        3486 :     if (m_poPrivate->m_pszWKTCached &&
    1164        1292 :         strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)
    1165             :     {
    1166        1291 :         CPLFree(pszWKT);
    1167        1291 :         return m_poPrivate->m_pszWKTCached;
    1168             :     }
    1169        2195 :     CPLFree(m_poPrivate->m_pszWKTCached);
    1170        2195 :     m_poPrivate->m_pszWKTCached = pszWKT;
    1171        2195 :     return m_poPrivate->m_pszWKTCached;
    1172             : }
    1173             : 
    1174             : /************************************************************************/
    1175             : /*                           GetSpatialRef()                            */
    1176             : /************************************************************************/
    1177             : 
    1178             : /**
    1179             :  * \brief Fetch the spatial reference for this dataset.
    1180             :  *
    1181             :  * Same as the C function GDALGetSpatialRef().
    1182             :  *
    1183             :  * When a projection definition is not available, null is returned. If used on
    1184             :  * a dataset where there are GCPs and not a geotransform, this method returns
    1185             :  * null. Use GetGCPSpatialRef() instead.
    1186             :  *
    1187             :  * @since GDAL 3.0
    1188             :  *
    1189             :  * @return a pointer to an internal object. It should not be altered or freed.
    1190             :  * Its lifetime will be the one of the dataset object, or until the next
    1191             :  * call to this method.
    1192             :  *
    1193             :  * @see https://gdal.org/tutorials/osr_api_tut.html
    1194             :  */
    1195             : 
    1196       13728 : const OGRSpatialReference *GDALDataset::GetSpatialRef() const
    1197             : {
    1198       13728 :     return nullptr;
    1199             : }
    1200             : 
    1201             : /************************************************************************/
    1202             : /*                        GDALGetSpatialRef()                           */
    1203             : /************************************************************************/
    1204             : 
    1205             : /**
    1206             :  * \brief Fetch the spatial reference for this dataset.
    1207             :  *
    1208             :  * @since GDAL 3.0
    1209             :  *
    1210             :  * @see GDALDataset::GetSpatialRef()
    1211             :  */
    1212             : 
    1213        5727 : OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)
    1214             : 
    1215             : {
    1216        5727 :     VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
    1217             : 
    1218        5727 :     return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
    1219        5727 :         GDALDataset::FromHandle(hDS)->GetSpatialRef()));
    1220             : }
    1221             : 
    1222             : /************************************************************************/
    1223             : /*                        GDALGetProjectionRef()                        */
    1224             : /************************************************************************/
    1225             : 
    1226             : /**
    1227             :  * \brief Fetch the projection definition string for this dataset.
    1228             :  *
    1229             :  * @see GDALDataset::GetProjectionRef()
    1230             :  */
    1231             : 
    1232        1372 : const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)
    1233             : 
    1234             : {
    1235        1372 :     VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
    1236             : 
    1237        1372 :     return GDALDataset::FromHandle(hDS)->GetProjectionRef();
    1238             : }
    1239             : 
    1240             : /************************************************************************/
    1241             : /*                           SetProjection()                            */
    1242             : /************************************************************************/
    1243             : 
    1244             : /**
    1245             :  * \brief Set the projection reference string for this dataset.
    1246             :  *
    1247             :  * The string should be in OGC WKT or PROJ.4 format.  An error may occur
    1248             :  * because of incorrectly specified projection strings, because the dataset
    1249             :  * is not writable, or because the dataset does not support the indicated
    1250             :  * projection.  Many formats do not support writing projections.
    1251             :  *
    1252             :  * This method is the same as the C GDALSetProjection() function.
    1253             :  *
    1254             :  * \note Startig with GDAL 3.0, this is a compatibility layer around
    1255             :  * SetSpatialRef()
    1256             : 
    1257             :  * @param pszProjection projection reference string.
    1258             :  *
    1259             :  * @return CE_Failure if an error occurs, otherwise CE_None.
    1260             :  */
    1261             : 
    1262        2432 : CPLErr GDALDataset::SetProjection(const char *pszProjection)
    1263             : {
    1264        2432 :     if (pszProjection && pszProjection[0] != '\0')
    1265             :     {
    1266        4574 :         OGRSpatialReference oSRS;
    1267        2287 :         oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
    1268        2287 :         if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)
    1269             :         {
    1270           2 :             return CE_Failure;
    1271             :         }
    1272        2285 :         return SetSpatialRef(&oSRS);
    1273             :     }
    1274             :     else
    1275             :     {
    1276         145 :         return SetSpatialRef(nullptr);
    1277             :     }
    1278             : }
    1279             : 
    1280             : /************************************************************************/
    1281             : /*                           SetSpatialRef()                            */
    1282             : /************************************************************************/
    1283             : 
    1284             : /**
    1285             :  * \brief Set the spatial reference system for this dataset.
    1286             :  *
    1287             :  * An error may occur because the dataset
    1288             :  * is not writable, or because the dataset does not support the indicated
    1289             :  * projection. Many formats do not support writing projections.
    1290             :  *
    1291             :  * This method is the same as the C GDALSetSpatialRef() function.
    1292             :  *
    1293             :  * @since GDAL 3.0
    1294             : 
    1295             :  * @param poSRS spatial reference system object. nullptr can potentially be
    1296             :  * passed for drivers that support unsetting the SRS.
    1297             :  *
    1298             :  * @return CE_Failure if an error occurs, otherwise CE_None.
    1299             :  */
    1300             : 
    1301           0 : CPLErr GDALDataset::SetSpatialRef(CPL_UNUSED const OGRSpatialReference *poSRS)
    1302             : {
    1303           0 :     if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
    1304           0 :         ReportError(CE_Failure, CPLE_NotSupported,
    1305             :                     "Dataset does not support the SetSpatialRef() method.");
    1306           0 :     return CE_Failure;
    1307             : }
    1308             : 
    1309             : /************************************************************************/
    1310             : /*                         GDALSetSpatialRef()                          */
    1311             : /************************************************************************/
    1312             : 
    1313             : /**
    1314             :  * \brief Set the spatial reference system for this dataset.
    1315             :  *
    1316             :  * @since GDAL 3.0
    1317             :  *
    1318             :  * @see GDALDataset::SetSpatialRef()
    1319             :  */
    1320             : 
    1321         967 : CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)
    1322             : 
    1323             : {
    1324         967 :     VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
    1325             : 
    1326        1934 :     return GDALDataset::FromHandle(hDS)->SetSpatialRef(
    1327         967 :         OGRSpatialReference::FromHandle(hSRS));
    1328             : }
    1329             : 
    1330             : /************************************************************************/
    1331             : /*                         GDALSetProjection()                          */
    1332             : /************************************************************************/
    1333             : 
    1334             : /**
    1335             :  * \brief Set the projection reference string for this dataset.
    1336             :  *
    1337             :  * @see GDALDataset::SetProjection()
    1338             :  */
    1339             : 
    1340        1936 : CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,
    1341             :                                      const char *pszProjection)
    1342             : 
    1343             : {
    1344        1936 :     VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
    1345             : 
    1346        1936 :     return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
    1347             : }
    1348             : 
    1349             : /************************************************************************/
    1350             : /*                          GetGeoTransform()                           */
    1351             : /************************************************************************/
    1352             : 
    1353             : /**
    1354             :  * \brief Fetch the affine transformation coefficients.
    1355             :  *
    1356             :  * Fetches the coefficients for transforming between pixel/line (P,L) raster
    1357             :  * space, and projection coordinates (Xp,Yp) space.
    1358             :  *
    1359             :  * \code
    1360             :  *   Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
    1361             :  *   Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
    1362             :  * \endcode
    1363             :  *
    1364             :  * In a north up image, padfTransform[1] is the pixel width, and
    1365             :  * padfTransform[5] is the pixel height.  The upper left corner of the
    1366             :  * upper left pixel is at position (padfTransform[0],padfTransform[3]).
    1367             :  *
    1368             :  * The default transform is (0,1,0,0,0,1) and should be returned even when
    1369             :  * a CE_Failure error is returned, such as for formats that don't support
    1370             :  * transformation to projection coordinates.
    1371             :  *
    1372             :  * This method does the same thing as the C GDALGetGeoTransform() function.
    1373             :  *
    1374             :  * @param padfTransform an existing six double buffer into which the
    1375             :  * transformation will be placed.
    1376             :  *
    1377             :  * @return CE_None on success, or CE_Failure if no transform can be fetched.
    1378             :  */
    1379             : 
    1380       12075 : CPLErr GDALDataset::GetGeoTransform(double *padfTransform)
    1381             : 
    1382             : {
    1383       12075 :     CPLAssert(padfTransform != nullptr);
    1384             : 
    1385       12075 :     padfTransform[0] = 0.0;  // X Origin (top left corner)
    1386       12075 :     padfTransform[1] = 1.0;  // X Pixel size */
    1387       12075 :     padfTransform[2] = 0.0;
    1388             : 
    1389       12075 :     padfTransform[3] = 0.0;  // Y Origin (top left corner)
    1390       12075 :     padfTransform[4] = 0.0;
    1391       12075 :     padfTransform[5] = 1.0;  // Y Pixel Size
    1392             : 
    1393       12075 :     return CE_Failure;
    1394             : }
    1395             : 
    1396             : /************************************************************************/
    1397             : /*                        GDALGetGeoTransform()                         */
    1398             : /************************************************************************/
    1399             : 
    1400             : /**
    1401             :  * \brief Fetch the affine transformation coefficients.
    1402             :  *
    1403             :  * @see GDALDataset::GetGeoTransform()
    1404             :  */
    1405             : 
    1406        7674 : CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)
    1407             : 
    1408             : {
    1409        7674 :     VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
    1410             : 
    1411        7674 :     return GDALDataset::FromHandle(hDS)->GetGeoTransform(padfTransform);
    1412             : }
    1413             : 
    1414             : /************************************************************************/
    1415             : /*                          SetGeoTransform()                           */
    1416             : /************************************************************************/
    1417             : 
    1418             : /**
    1419             :  * \fn GDALDataset::SetGeoTransform(double*)
    1420             :  * \brief Set the affine transformation coefficients.
    1421             :  *
    1422             :  * See GetGeoTransform() for details on the meaning of the padfTransform
    1423             :  * coefficients.
    1424             :  *
    1425             :  * This method does the same thing as the C GDALSetGeoTransform() function.
    1426             :  *
    1427             :  * @param padfTransform a six double buffer containing the transformation
    1428             :  * coefficients to be written with the dataset.
    1429             :  *
    1430             :  * @return CE_None on success, or CE_Failure if this transform cannot be
    1431             :  * written.
    1432             :  */
    1433             : 
    1434           0 : CPLErr GDALDataset::SetGeoTransform(CPL_UNUSED double *padfTransform)
    1435             : 
    1436             : {
    1437           0 :     if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
    1438           0 :         ReportError(CE_Failure, CPLE_NotSupported,
    1439             :                     "SetGeoTransform() not supported for this dataset.");
    1440             : 
    1441           0 :     return CE_Failure;
    1442             : }
    1443             : 
    1444             : /************************************************************************/
    1445             : /*                        GDALSetGeoTransform()                         */
    1446             : /************************************************************************/
    1447             : 
    1448             : /**
    1449             :  * \brief Set the affine transformation coefficients.
    1450             :  *
    1451             :  * @see GDALDataset::SetGeoTransform()
    1452             :  */
    1453             : 
    1454        3674 : CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS, double *padfTransform)
    1455             : 
    1456             : {
    1457        3674 :     VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
    1458             : 
    1459        3674 :     return GDALDataset::FromHandle(hDS)->SetGeoTransform(padfTransform);
    1460             : }
    1461             : 
    1462             : /************************************************************************/
    1463             : /*                         GetInternalHandle()                          */
    1464             : /************************************************************************/
    1465             : 
    1466             : /**
    1467             :  * \fn GDALDataset::GetInternalHandle(const char*)
    1468             :  * \brief Fetch a format specific internally meaningful handle.
    1469             :  *
    1470             :  * This method is the same as the C GDALGetInternalHandle() method.
    1471             :  *
    1472             :  * @param pszHandleName the handle name desired.  The meaningful names
    1473             :  * will be specific to the file format.
    1474             :  *
    1475             :  * @return the desired handle value, or NULL if not recognized/supported.
    1476             :  */
    1477             : 
    1478           0 : void *GDALDataset::GetInternalHandle(CPL_UNUSED const char *pszHandleName)
    1479             : 
    1480             : {
    1481           0 :     return nullptr;
    1482             : }
    1483             : 
    1484             : /************************************************************************/
    1485             : /*                       GDALGetInternalHandle()                        */
    1486             : /************************************************************************/
    1487             : 
    1488             : /**
    1489             :  * \brief Fetch a format specific internally meaningful handle.
    1490             :  *
    1491             :  * @see GDALDataset::GetInternalHandle()
    1492             :  */
    1493             : 
    1494          58 : void *CPL_STDCALL GDALGetInternalHandle(GDALDatasetH hDS,
    1495             :                                         const char *pszRequest)
    1496             : 
    1497             : {
    1498          58 :     VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
    1499             : 
    1500          58 :     return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
    1501             : }
    1502             : 
    1503             : /************************************************************************/
    1504             : /*                             GetDriver()                              */
    1505             : /************************************************************************/
    1506             : 
    1507             : /**
    1508             :  * \brief Fetch the driver to which this dataset relates.
    1509             :  *
    1510             :  * This method is the same as the C GDALGetDatasetDriver() function.
    1511             :  *
    1512             :  * @return the driver on which the dataset was created with GDALOpen() or
    1513             :  * GDALCreate().
    1514             :  */
    1515             : 
    1516       26628 : GDALDriver *GDALDataset::GetDriver()
    1517             : {
    1518       26628 :     return poDriver;
    1519             : }
    1520             : 
    1521             : /************************************************************************/
    1522             : /*                        GDALGetDatasetDriver()                        */
    1523             : /************************************************************************/
    1524             : 
    1525             : /**
    1526             :  * \brief Fetch the driver to which this dataset relates.
    1527             :  *
    1528             :  * @see GDALDataset::GetDriver()
    1529             :  */
    1530             : 
    1531        2659 : GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)
    1532             : 
    1533             : {
    1534        2659 :     VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
    1535             : 
    1536             :     return static_cast<GDALDriverH>(
    1537        2659 :         GDALDataset::FromHandle(hDataset)->GetDriver());
    1538             : }
    1539             : 
    1540             : /************************************************************************/
    1541             : /*                             Reference()                              */
    1542             : /************************************************************************/
    1543             : 
    1544             : /**
    1545             :  * \brief Add one to dataset reference count.
    1546             :  *
    1547             :  * The reference is one after instantiation.
    1548             :  *
    1549             :  * This method is the same as the C GDALReferenceDataset() function.
    1550             :  *
    1551             :  * @return the post-increment reference count.
    1552             :  */
    1553             : 
    1554       18428 : int GDALDataset::Reference()
    1555             : {
    1556       18428 :     return ++nRefCount;
    1557             : }
    1558             : 
    1559             : /************************************************************************/
    1560             : /*                        GDALReferenceDataset()                        */
    1561             : /************************************************************************/
    1562             : 
    1563             : /**
    1564             :  * \brief Add one to dataset reference count.
    1565             :  *
    1566             :  * @see GDALDataset::Reference()
    1567             :  */
    1568             : 
    1569        1065 : int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)
    1570             : 
    1571             : {
    1572        1065 :     VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
    1573             : 
    1574        1065 :     return GDALDataset::FromHandle(hDataset)->Reference();
    1575             : }
    1576             : 
    1577             : /************************************************************************/
    1578             : /*                            Dereference()                             */
    1579             : /************************************************************************/
    1580             : 
    1581             : /**
    1582             :  * \brief Subtract one from dataset reference count.
    1583             :  *
    1584             :  * The reference is one after instantiation.  Generally when the reference
    1585             :  * count has dropped to zero the dataset may be safely deleted (closed).
    1586             :  *
    1587             :  * This method is the same as the C GDALDereferenceDataset() function.
    1588             :  *
    1589             :  * @return the post-decrement reference count.
    1590             :  */
    1591             : 
    1592       66956 : int GDALDataset::Dereference()
    1593             : {
    1594       66956 :     return --nRefCount;
    1595             : }
    1596             : 
    1597             : /************************************************************************/
    1598             : /*                       GDALDereferenceDataset()                       */
    1599             : /************************************************************************/
    1600             : 
    1601             : /**
    1602             :  * \brief Subtract one from dataset reference count.
    1603             :  *
    1604             :  * @see GDALDataset::Dereference()
    1605             :  */
    1606             : 
    1607       52386 : int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)
    1608             : 
    1609             : {
    1610       52386 :     VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
    1611             : 
    1612       52386 :     return GDALDataset::FromHandle(hDataset)->Dereference();
    1613             : }
    1614             : 
    1615             : /************************************************************************/
    1616             : /*                            ReleaseRef()                              */
    1617             : /************************************************************************/
    1618             : 
    1619             : /**
    1620             :  * \brief Drop a reference to this object, and destroy if no longer referenced.
    1621             :  * @return TRUE if the object has been destroyed.
    1622             :  * @since GDAL 2.2
    1623             :  */
    1624             : 
    1625       13961 : int GDALDataset::ReleaseRef()
    1626             : 
    1627             : {
    1628       13961 :     if (Dereference() <= 0)
    1629             :     {
    1630        3281 :         nRefCount = 1;
    1631        3281 :         delete this;
    1632        3281 :         return TRUE;
    1633             :     }
    1634       10680 :     return FALSE;
    1635             : }
    1636             : 
    1637             : /************************************************************************/
    1638             : /*                        GDALReleaseDataset()                          */
    1639             : /************************************************************************/
    1640             : 
    1641             : /**
    1642             :  * \brief Drop a reference to this object, and destroy if no longer referenced.
    1643             :  *
    1644             :  * @see GDALDataset::ReleaseRef()
    1645             :  * @since GDAL 2.2
    1646             :  */
    1647             : 
    1648        1293 : int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)
    1649             : 
    1650             : {
    1651        1293 :     VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
    1652             : 
    1653        1293 :     return GDALDataset::FromHandle(hDataset)->ReleaseRef();
    1654             : }
    1655             : 
    1656             : /************************************************************************/
    1657             : /*                             GetShared()                              */
    1658             : /************************************************************************/
    1659             : 
    1660             : /**
    1661             :  * \brief Returns shared flag.
    1662             :  *
    1663             :  * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
    1664             :  */
    1665             : 
    1666       91186 : int GDALDataset::GetShared() const
    1667             : {
    1668       91186 :     return bShared;
    1669             : }
    1670             : 
    1671             : /************************************************************************/
    1672             : /*                            MarkAsShared()                            */
    1673             : /************************************************************************/
    1674             : 
    1675             : /**
    1676             :  * \brief Mark this dataset as available for sharing.
    1677             :  */
    1678             : 
    1679         404 : void GDALDataset::MarkAsShared()
    1680             : 
    1681             : {
    1682         404 :     CPLAssert(!bShared);
    1683             : 
    1684         404 :     bShared = true;
    1685         404 :     if (bIsInternal)
    1686          13 :         return;
    1687             : 
    1688         391 :     GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
    1689             : 
    1690             :     // Insert the dataset in the set of shared opened datasets.
    1691         782 :     CPLMutexHolderD(&hDLMutex);
    1692         391 :     if (phSharedDatasetSet == nullptr)
    1693         271 :         phSharedDatasetSet =
    1694         271 :             CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
    1695             :                           GDALSharedDatasetFreeFunc);
    1696             : 
    1697             :     SharedDatasetCtxt *psStruct =
    1698         391 :         static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
    1699         391 :     psStruct->poDS = this;
    1700         391 :     psStruct->nPID = nPID;
    1701         391 :     psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
    1702         391 :     psStruct->pszDescription = CPLStrdup(GetDescription());
    1703             :     std::string osConcatenatedOpenOptions =
    1704         782 :         GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
    1705         391 :     psStruct->pszConcatenatedOpenOptions =
    1706         391 :         CPLStrdup(osConcatenatedOpenOptions.c_str());
    1707         391 :     if (CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
    1708             :     {
    1709           1 :         GDALSharedDatasetFreeFunc(psStruct);
    1710           1 :         ReportError(CE_Failure, CPLE_AppDefined,
    1711             :                     "An existing shared dataset already has this description. "
    1712             :                     "This should not happen.");
    1713             :     }
    1714             :     else
    1715             :     {
    1716         390 :         CPLHashSetInsert(phSharedDatasetSet, psStruct);
    1717             : 
    1718         390 :         (*poAllDatasetMap)[this] = nPID;
    1719             :     }
    1720             : }
    1721             : 
    1722             : /************************************************************************/
    1723             : /*                        MarkSuppressOnClose()                         */
    1724             : /************************************************************************/
    1725             : 
    1726             : /** Set that the dataset must be deleted on close. */
    1727        1066 : void GDALDataset::MarkSuppressOnClose()
    1728             : {
    1729        1066 :     bSuppressOnClose = true;
    1730        1066 : }
    1731             : 
    1732             : /************************************************************************/
    1733             : /*                       UnMarkSuppressOnClose()                        */
    1734             : /************************************************************************/
    1735             : 
    1736             : /** Remove the flag requesting the dataset to be deleted on close. */
    1737           1 : void GDALDataset::UnMarkSuppressOnClose()
    1738             : {
    1739           1 :     bSuppressOnClose = false;
    1740           1 : }
    1741             : 
    1742             : /************************************************************************/
    1743             : /*                        CleanupPostFileClosing()                      */
    1744             : /************************************************************************/
    1745             : 
    1746             : /** This method should be called by driver implementations in their destructor,
    1747             :  * after having closed all files, but before having freed resources that
    1748             :  * are needed for their GetFileList() implementation.
    1749             :  * This is used to implement MarkSuppressOnClose behavior.
    1750             :  */
    1751         251 : void GDALDataset::CleanupPostFileClosing()
    1752             : {
    1753         251 :     if (IsMarkedSuppressOnClose())
    1754             :     {
    1755           1 :         char **papszFileList = GetFileList();
    1756           3 :         for (int i = 0; papszFileList && papszFileList[i]; ++i)
    1757           2 :             VSIUnlink(papszFileList[i]);
    1758           1 :         CSLDestroy(papszFileList);
    1759             :     }
    1760         251 : }
    1761             : 
    1762             : /************************************************************************/
    1763             : /*                            GetGCPCount()                             */
    1764             : /************************************************************************/
    1765             : 
    1766             : /**
    1767             :  * \brief Get number of GCPs.
    1768             :  *
    1769             :  * This method is the same as the C function GDALGetGCPCount().
    1770             :  *
    1771             :  * @return number of GCPs for this dataset.  Zero if there are none.
    1772             :  */
    1773             : 
    1774       12492 : int GDALDataset::GetGCPCount()
    1775             : {
    1776       12492 :     return 0;
    1777             : }
    1778             : 
    1779             : /************************************************************************/
    1780             : /*                          GDALGetGCPCount()                           */
    1781             : /************************************************************************/
    1782             : 
    1783             : /**
    1784             :  * \brief Get number of GCPs.
    1785             :  *
    1786             :  * @see GDALDataset::GetGCPCount()
    1787             :  */
    1788             : 
    1789        1017 : int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)
    1790             : 
    1791             : {
    1792        1017 :     VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
    1793             : 
    1794        1017 :     return GDALDataset::FromHandle(hDS)->GetGCPCount();
    1795             : }
    1796             : 
    1797             : /************************************************************************/
    1798             : /*                          GetGCPProjection()                          */
    1799             : /************************************************************************/
    1800             : 
    1801             : /**
    1802             :  * \brief Get output projection for GCPs.
    1803             :  *
    1804             :  * This method is the same as the C function GDALGetGCPProjection().
    1805             :  *
    1806             :  * The projection string follows the normal rules from GetProjectionRef().
    1807             :  *
    1808             :  * \note Starting with GDAL 3.0, this is a compatibility layer around
    1809             :  * GetGCPSpatialRef()
    1810             :  *
    1811             :  * @return internal projection string or "" if there are no GCPs.
    1812             :  *  It should not be altered, freed or expected to last for long.
    1813             :  */
    1814             : 
    1815         786 : const char *GDALDataset::GetGCPProjection()
    1816             : {
    1817         786 :     const auto poSRS = GetGCPSpatialRef();
    1818         786 :     if (!poSRS || !m_poPrivate)
    1819             :     {
    1820         443 :         return "";
    1821             :     }
    1822         343 :     char *pszWKT = nullptr;
    1823         343 :     poSRS->exportToWkt(&pszWKT);
    1824         343 :     if (!pszWKT)
    1825             :     {
    1826           0 :         return "";
    1827             :     }
    1828             : 
    1829             :     // If called on a thread-safe dataset, we might be called by several
    1830             :     // threads, so make sure our accesses to m_pszWKTCached are protected
    1831             :     // by a mutex.
    1832         686 :     std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
    1833         343 :     if (m_poPrivate->m_pszWKTGCPCached &&
    1834         256 :         strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0)
    1835             :     {
    1836         256 :         CPLFree(pszWKT);
    1837         256 :         return m_poPrivate->m_pszWKTGCPCached;
    1838             :     }
    1839          87 :     CPLFree(m_poPrivate->m_pszWKTGCPCached);
    1840          87 :     m_poPrivate->m_pszWKTGCPCached = pszWKT;
    1841          87 :     return m_poPrivate->m_pszWKTGCPCached;
    1842             : }
    1843             : 
    1844             : /************************************************************************/
    1845             : /*                          GetGCPSpatialRef()                          */
    1846             : /************************************************************************/
    1847             : 
    1848             : /**
    1849             :  * \brief Get output spatial reference system for GCPs.
    1850             :  *
    1851             :  * Same as the C function GDALGetGCPSpatialRef().
    1852             :  *
    1853             :  * When a SRS is not available, null is returned. If used on
    1854             :  * a dataset where there is a geotransform, and not GCPs, this method returns
    1855             :  * null. Use GetSpatialRef() instead.
    1856             :  *
    1857             :  * @since GDAL 3.0
    1858             :  *
    1859             :  * @return a pointer to an internal object. It should not be altered or freed.
    1860             :  * Its lifetime will be the one of the dataset object, or until the next
    1861             :  * call to this method.
    1862             :  */
    1863             : 
    1864          39 : const OGRSpatialReference *GDALDataset::GetGCPSpatialRef() const
    1865             : {
    1866          39 :     return nullptr;
    1867             : }
    1868             : 
    1869             : /************************************************************************/
    1870             : /*                       GDALGetGCPSpatialRef()                         */
    1871             : /************************************************************************/
    1872             : 
    1873             : /**
    1874             :  * \brief Get output spatial reference system for GCPs.
    1875             :  *
    1876             :  * @since GDAL 3.0
    1877             :  *
    1878             :  * @see GDALDataset::GetGCPSpatialRef()
    1879             :  */
    1880             : 
    1881         462 : OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)
    1882             : 
    1883             : {
    1884         462 :     VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
    1885             : 
    1886         462 :     return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
    1887         462 :         GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
    1888             : }
    1889             : 
    1890             : /************************************************************************/
    1891             : /*                        GDALGetGCPProjection()                        */
    1892             : /************************************************************************/
    1893             : 
    1894             : /**
    1895             :  * \brief Get output projection for GCPs.
    1896             :  *
    1897             :  * @see GDALDataset::GetGCPProjection()
    1898             :  */
    1899             : 
    1900         711 : const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)
    1901             : 
    1902             : {
    1903         711 :     VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
    1904             : 
    1905         711 :     return GDALDataset::FromHandle(hDS)->GetGCPProjection();
    1906             : }
    1907             : 
    1908             : /************************************************************************/
    1909             : /*                               GetGCPs()                              */
    1910             : /************************************************************************/
    1911             : 
    1912             : /**
    1913             :  * \brief Fetch GCPs.
    1914             :  *
    1915             :  * This method is the same as the C function GDALGetGCPs().
    1916             :  *
    1917             :  * @return pointer to internal GCP structure list.  It should not be modified,
    1918             :  * and may change on the next GDAL call.
    1919             :  */
    1920             : 
    1921          10 : const GDAL_GCP *GDALDataset::GetGCPs()
    1922             : {
    1923          10 :     return nullptr;
    1924             : }
    1925             : 
    1926             : /************************************************************************/
    1927             : /*                            GDALGetGCPs()                             */
    1928             : /************************************************************************/
    1929             : 
    1930             : /**
    1931             :  * \brief Fetch GCPs.
    1932             :  *
    1933             :  * @see GDALDataset::GetGCPs()
    1934             :  */
    1935             : 
    1936         559 : const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)
    1937             : 
    1938             : {
    1939         559 :     VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
    1940             : 
    1941         559 :     return GDALDataset::FromHandle(hDS)->GetGCPs();
    1942             : }
    1943             : 
    1944             : /************************************************************************/
    1945             : /*                              SetGCPs()                               */
    1946             : /************************************************************************/
    1947             : 
    1948             : /**
    1949             :  * \brief Assign GCPs.
    1950             :  *
    1951             :  * This method is the same as the C function GDALSetGCPs().
    1952             :  *
    1953             :  * This method assigns the passed set of GCPs to this dataset, as well as
    1954             :  * setting their coordinate system.  Internally copies are made of the
    1955             :  * coordinate system and list of points, so the caller remains responsible for
    1956             :  * deallocating these arguments if appropriate.
    1957             :  *
    1958             :  * Most formats do not support setting of GCPs, even formats that can
    1959             :  * handle GCPs.  These formats will return CE_Failure.
    1960             :  *
    1961             :  * \note Startig with GDAL 3.0, this is a compatibility layer around
    1962             :  * SetGCPs(int, const GDAL_GCP*, const char*)
    1963             :  *
    1964             :  * @param nGCPCount number of GCPs being assigned.
    1965             :  *
    1966             :  * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
    1967             :  *
    1968             :  * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
    1969             :  * GCP output coordinates.  This parameter should be "" if no output coordinate
    1970             :  * system is known.
    1971             :  *
    1972             :  * @return CE_None on success, CE_Failure on failure (including if action is
    1973             :  * not supported for this format).
    1974             :  */
    1975             : 
    1976          53 : CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,
    1977             :                             const char *pszGCPProjection)
    1978             : 
    1979             : {
    1980          53 :     if (pszGCPProjection && pszGCPProjection[0] != '\0')
    1981             :     {
    1982          70 :         OGRSpatialReference oSRS;
    1983          35 :         oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
    1984          35 :         if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)
    1985             :         {
    1986           0 :             return CE_Failure;
    1987             :         }
    1988          35 :         return SetGCPs(nGCPCount, pasGCPList, &oSRS);
    1989             :     }
    1990             :     else
    1991             :     {
    1992          18 :         return SetGCPs(nGCPCount, pasGCPList,
    1993          18 :                        static_cast<const OGRSpatialReference *>(nullptr));
    1994             :     }
    1995             : }
    1996             : 
    1997             : /************************************************************************/
    1998             : /*                              SetGCPs()                               */
    1999             : /************************************************************************/
    2000             : 
    2001             : /**
    2002             :  * \brief Assign GCPs.
    2003             :  *
    2004             :  * This method is the same as the C function GDALSetGCPs().
    2005             :  *
    2006             :  * This method assigns the passed set of GCPs to this dataset, as well as
    2007             :  * setting their coordinate system.  Internally copies are made of the
    2008             :  * coordinate system and list of points, so the caller remains responsible for
    2009             :  * deallocating these arguments if appropriate.
    2010             :  *
    2011             :  * Most formats do not support setting of GCPs, even formats that can
    2012             :  * handle GCPs.  These formats will return CE_Failure.
    2013             :  *
    2014             :  * @since GDAL 3.0
    2015             :  *
    2016             :  * @param nGCPCount number of GCPs being assigned.
    2017             :  *
    2018             :  * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
    2019             :  *
    2020             :  * @param poGCP_SRS the new coordinate reference system to assign for the
    2021             :  * GCP output coordinates.  This parameter should be null if no output
    2022             :  * coordinate system is known.
    2023             :  *
    2024             :  * @return CE_None on success, CE_Failure on failure (including if action is
    2025             :  * not supported for this format).
    2026             :  */
    2027             : 
    2028           0 : CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,
    2029             :                             CPL_UNUSED const GDAL_GCP *pasGCPList,
    2030             :                             CPL_UNUSED const OGRSpatialReference *poGCP_SRS)
    2031             : 
    2032             : {
    2033           0 :     if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
    2034           0 :         ReportError(CE_Failure, CPLE_NotSupported,
    2035             :                     "Dataset does not support the SetGCPs() method.");
    2036             : 
    2037           0 :     return CE_Failure;
    2038             : }
    2039             : 
    2040             : /************************************************************************/
    2041             : /*                            GDALSetGCPs()                             */
    2042             : /************************************************************************/
    2043             : 
    2044             : /**
    2045             :  * \brief Assign GCPs.
    2046             :  *
    2047             :  * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
    2048             :  */
    2049             : 
    2050          30 : CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,
    2051             :                                const GDAL_GCP *pasGCPList,
    2052             :                                const char *pszGCPProjection)
    2053             : 
    2054             : {
    2055          30 :     VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
    2056             : 
    2057          30 :     return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,
    2058          30 :                                                  pszGCPProjection);
    2059             : }
    2060             : 
    2061             : /************************************************************************/
    2062             : /*                           GDALSetGCPs2()                             */
    2063             : /************************************************************************/
    2064             : 
    2065             : /**
    2066             :  * \brief Assign GCPs.
    2067             :  *
    2068             :  * @since GDAL 3.0
    2069             :  * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
    2070             :  */
    2071             : 
    2072           9 : CPLErr GDALSetGCPs2(GDALDatasetH hDS, int nGCPCount, const GDAL_GCP *pasGCPList,
    2073             :                     OGRSpatialReferenceH hSRS)
    2074             : 
    2075             : {
    2076           9 :     VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
    2077             : 
    2078          18 :     return GDALDataset::FromHandle(hDS)->SetGCPs(
    2079           9 :         nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
    2080             : }
    2081             : 
    2082             : /************************************************************************/
    2083             : /*                           BuildOverviews()                           */
    2084             : /************************************************************************/
    2085             : 
    2086             : /**
    2087             :  * \brief Build raster overview(s)
    2088             :  *
    2089             :  * If the operation is unsupported for the indicated dataset, then
    2090             :  * CE_Failure is returned, and CPLGetLastErrorNo() will return
    2091             :  * CPLE_NotSupported.
    2092             :  *
    2093             :  * Depending on the actual file format, all overviews level can be also
    2094             :  * deleted by specifying nOverviews == 0. This works at least for external
    2095             :  * overviews (.ovr), TIFF internal overviews, etc.
    2096             :  *
    2097             :  * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
    2098             :  * to "ALL_CPUS" or a integer value to specify the number of threads to use for
    2099             :  * overview computation.
    2100             :  *
    2101             :  * This method is the same as the C function GDALBuildOverviewsEx().
    2102             :  *
    2103             :  * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
    2104             :  * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
    2105             :  * or "NONE" controlling the downsampling method applied.
    2106             :  * @param nOverviews number of overviews to build, or 0 to clean overviews.
    2107             :  * @param panOverviewList the list of overview decimation factors to build, or
    2108             :  *                        NULL if nOverviews == 0.
    2109             :  * @param nListBands number of bands to build overviews for in panBandList.
    2110             :  * Build for all bands if this is 0.
    2111             :  * @param panBandList list of band numbers.
    2112             :  * @param pfnProgress a function to call to report progress, or NULL.
    2113             :  * @param pProgressData application data to pass to the progress function.
    2114             :  * @param papszOptions (GDAL >= 3.6) NULL terminated list of options as
    2115             :  *                     key=value pairs, or NULL
    2116             :  *
    2117             :  * @return CE_None on success or CE_Failure if the operation doesn't work.
    2118             :  *
    2119             :  * For example, to build overview level 2, 4 and 8 on all bands the following
    2120             :  * call could be made:
    2121             :  * \code{.cpp}
    2122             :  *   int       anOverviewList[3] = { 2, 4, 8 };
    2123             :  *
    2124             :  *   poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
    2125             :  *                              GDALDummyProgress, nullptr );
    2126             :  * \endcode
    2127             :  *
    2128             :  * @see GDALRegenerateOverviewsEx()
    2129             :  */
    2130             : 
    2131         654 : CPLErr GDALDataset::BuildOverviews(const char *pszResampling, int nOverviews,
    2132             :                                    const int *panOverviewList, int nListBands,
    2133             :                                    const int *panBandList,
    2134             :                                    GDALProgressFunc pfnProgress,
    2135             :                                    void *pProgressData,
    2136             :                                    CSLConstList papszOptions)
    2137             : {
    2138         654 :     int *panAllBandList = nullptr;
    2139             : 
    2140         654 :     if (nListBands == 0)
    2141             :     {
    2142         643 :         nListBands = GetRasterCount();
    2143             :         panAllBandList =
    2144         643 :             static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
    2145        1708 :         for (int i = 0; i < nListBands; ++i)
    2146        1065 :             panAllBandList[i] = i + 1;
    2147             : 
    2148         643 :         panBandList = panAllBandList;
    2149             :     }
    2150             : 
    2151         654 :     if (pfnProgress == nullptr)
    2152         623 :         pfnProgress = GDALDummyProgress;
    2153             : 
    2154             :     // At time of writing, all overview generation options are actually
    2155             :     // expected to be passed as configuration options.
    2156         654 :     std::vector<std::unique_ptr<CPLConfigOptionSetter>> apoConfigOptionSetter;
    2157         688 :     for (const auto &[pszKey, pszValue] : cpl::IterateNameValue(papszOptions))
    2158             :     {
    2159             :         apoConfigOptionSetter.emplace_back(
    2160          34 :             std::make_unique<CPLConfigOptionSetter>(pszKey, pszValue, false));
    2161             :     }
    2162             : 
    2163             :     const CPLErr eErr =
    2164        1308 :         IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
    2165         654 :                         panBandList, pfnProgress, pProgressData, papszOptions);
    2166             : 
    2167         654 :     if (panAllBandList != nullptr)
    2168         642 :         CPLFree(panAllBandList);
    2169             : 
    2170        1308 :     return eErr;
    2171             : }
    2172             : 
    2173             : /************************************************************************/
    2174             : /*                         GDALBuildOverviews()                         */
    2175             : /************************************************************************/
    2176             : 
    2177             : /**
    2178             :  * \brief Build raster overview(s)
    2179             :  *
    2180             :  * @see GDALDataset::BuildOverviews() and GDALBuildOverviews()
    2181             :  */
    2182             : 
    2183          21 : CPLErr CPL_STDCALL GDALBuildOverviews(GDALDatasetH hDataset,
    2184             :                                       const char *pszResampling, int nOverviews,
    2185             :                                       const int *panOverviewList,
    2186             :                                       int nListBands, const int *panBandList,
    2187             :                                       GDALProgressFunc pfnProgress,
    2188             :                                       void *pProgressData)
    2189             : 
    2190             : {
    2191          21 :     VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
    2192             : 
    2193          21 :     return GDALDataset::FromHandle(hDataset)->BuildOverviews(
    2194             :         pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
    2195          21 :         pfnProgress, pProgressData, nullptr);
    2196             : }
    2197             : 
    2198             : /************************************************************************/
    2199             : /*                         GDALBuildOverviews()                         */
    2200             : /************************************************************************/
    2201             : 
    2202             : /**
    2203             :  * \brief Build raster overview(s)
    2204             :  *
    2205             :  * @see GDALDataset::BuildOverviews()
    2206             :  * @since GDAL 3.6
    2207             :  */
    2208             : 
    2209             : CPLErr CPL_STDCALL
    2210         614 : GDALBuildOverviewsEx(GDALDatasetH hDataset, const char *pszResampling,
    2211             :                      int nOverviews, const int *panOverviewList, int nListBands,
    2212             :                      const int *panBandList, GDALProgressFunc pfnProgress,
    2213             :                      void *pProgressData, CSLConstList papszOptions)
    2214             : 
    2215             : {
    2216         614 :     VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
    2217             : 
    2218         614 :     return GDALDataset::FromHandle(hDataset)->BuildOverviews(
    2219             :         pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
    2220         614 :         pfnProgress, pProgressData, papszOptions);
    2221             : }
    2222             : 
    2223             : /************************************************************************/
    2224             : /*                          IBuildOverviews()                           */
    2225             : /*                                                                      */
    2226             : /*      Default implementation.                                         */
    2227             : /************************************************************************/
    2228             : 
    2229             : //! @cond Doxygen_Suppress
    2230         186 : CPLErr GDALDataset::IBuildOverviews(const char *pszResampling, int nOverviews,
    2231             :                                     const int *panOverviewList, int nListBands,
    2232             :                                     const int *panBandList,
    2233             :                                     GDALProgressFunc pfnProgress,
    2234             :                                     void *pProgressData,
    2235             :                                     CSLConstList papszOptions)
    2236             : 
    2237             : {
    2238         186 :     if (oOvManager.IsInitialized())
    2239         185 :         return oOvManager.BuildOverviews(
    2240             :             nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
    2241         185 :             panBandList, pfnProgress, pProgressData, papszOptions);
    2242             :     else
    2243             :     {
    2244           1 :         ReportError(CE_Failure, CPLE_NotSupported,
    2245             :                     "BuildOverviews() not supported for this dataset.");
    2246             : 
    2247           1 :         return CE_Failure;
    2248             :     }
    2249             : }
    2250             : 
    2251             : //! @endcond
    2252             : 
    2253             : /************************************************************************/
    2254             : /*                             IRasterIO()                              */
    2255             : /*                                                                      */
    2256             : /*      The default implementation of IRasterIO() is, in the general    */
    2257             : /*      case to pass the request off to each band objects rasterio      */
    2258             : /*      methods with appropriate arguments. In some cases, it might     */
    2259             : /*      choose instead the BlockBasedRasterIO() implementation.         */
    2260             : /************************************************************************/
    2261             : 
    2262             : //! @cond Doxygen_Suppress
    2263      438741 : CPLErr GDALDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
    2264             :                               int nXSize, int nYSize, void *pData,
    2265             :                               int nBufXSize, int nBufYSize,
    2266             :                               GDALDataType eBufType, int nBandCount,
    2267             :                               BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,
    2268             :                               GSpacing nLineSpace, GSpacing nBandSpace,
    2269             :                               GDALRasterIOExtraArg *psExtraArg)
    2270             : 
    2271             : {
    2272      438741 :     const char *pszInterleave = nullptr;
    2273             : 
    2274      438741 :     CPLAssert(nullptr != pData);
    2275             : 
    2276      438741 :     const bool bHasSubpixelShift =
    2277      439833 :         psExtraArg->bFloatingPointWindowValidity &&
    2278      438919 :         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
    2279         178 :         (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
    2280             : 
    2281      438644 :     if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&
    2282       69630 :         nBandCount > 1 &&
    2283       69631 :         (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
    2284      877384 :             nullptr &&
    2285       65671 :         EQUAL(pszInterleave, "PIXEL"))
    2286             :     {
    2287       63502 :         return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
    2288             :                                   nBufXSize, nBufYSize, eBufType, nBandCount,
    2289             :                                   panBandMap, nPixelSpace, nLineSpace,
    2290       63501 :                                   nBandSpace, psExtraArg);
    2291             :     }
    2292             : 
    2293      375239 :     if (eRWFlag == GF_Read &&
    2294      199553 :         (psExtraArg->eResampleAlg == GRIORA_Cubic ||
    2295      199379 :          psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
    2296      199378 :          psExtraArg->eResampleAlg == GRIORA_Bilinear ||
    2297      199553 :          psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
    2298         331 :         !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)
    2299             :     {
    2300         312 :         if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())
    2301             :         {
    2302         153 :             int bTried = FALSE;
    2303         153 :             const CPLErr eErr = TryOverviewRasterIO(
    2304             :                 eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
    2305             :                 nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
    2306             :                 nLineSpace, nBandSpace, psExtraArg, &bTried);
    2307         153 :             if (bTried)
    2308           1 :                 return eErr;
    2309             :         }
    2310             : 
    2311         311 :         GDALDataType eFirstBandDT = GDT_Unknown;
    2312         311 :         int nFirstMaskFlags = 0;
    2313         311 :         GDALRasterBand *poFirstMaskBand = nullptr;
    2314         311 :         int nOKBands = 0;
    2315             : 
    2316             :         // Check if bands share the same mask band
    2317        1271 :         for (int i = 0; i < nBandCount; ++i)
    2318             :         {
    2319        1042 :             GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
    2320        1534 :             if ((nBufXSize < nXSize || nBufYSize < nYSize) &&
    2321         485 :                 poBand->GetOverviewCount())
    2322             :             {
    2323             :                 // Could be improved to select the appropriate overview.
    2324           3 :                 break;
    2325             :             }
    2326        1046 :             if (poBand->GetColorTable() != nullptr)
    2327             :             {
    2328           0 :                 break;
    2329             :             }
    2330        1048 :             const GDALDataType eDT = poBand->GetRasterDataType();
    2331        1045 :             if (GDALDataTypeIsComplex(eDT))
    2332             :             {
    2333          30 :                 break;
    2334             :             }
    2335        1014 :             if (i == 0)
    2336             :             {
    2337         280 :                 eFirstBandDT = eDT;
    2338         280 :                 nFirstMaskFlags = poBand->GetMaskFlags();
    2339         283 :                 if (nFirstMaskFlags == GMF_NODATA)
    2340             :                 {
    2341             :                     // The dataset-level resampling code is not ready for nodata
    2342             :                     // Fallback to band-level resampling
    2343           6 :                     break;
    2344             :                 }
    2345         277 :                 poFirstMaskBand = poBand->GetMaskBand();
    2346             :             }
    2347             :             else
    2348             :             {
    2349         734 :                 if (eDT != eFirstBandDT)
    2350             :                 {
    2351           0 :                     break;
    2352             :                 }
    2353         734 :                 int nMaskFlags = poBand->GetMaskFlags();
    2354         734 :                 if (nMaskFlags == GMF_NODATA)
    2355             :                 {
    2356             :                     // The dataset-level resampling code is not ready for nodata
    2357             :                     // Fallback to band-level resampling
    2358           0 :                     break;
    2359             :                 }
    2360         734 :                 GDALRasterBand *poMaskBand = poBand->GetMaskBand();
    2361         737 :                 if (nFirstMaskFlags == GMF_ALL_VALID &&
    2362             :                     nMaskFlags == GMF_ALL_VALID)
    2363             :                 {
    2364             :                     // Ok.
    2365             :                 }
    2366         168 :                 else if (poFirstMaskBand == poMaskBand)
    2367             :                 {
    2368             :                     // Ok.
    2369             :                 }
    2370             :                 else
    2371             :                 {
    2372          55 :                     break;
    2373             :                 }
    2374             :             }
    2375             : 
    2376         960 :             ++nOKBands;
    2377             :         }
    2378             : 
    2379         323 :         GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
    2380         323 :         void *pProgressDataGlobal = psExtraArg->pProgressData;
    2381             : 
    2382         323 :         CPLErr eErr = CE_None;
    2383         323 :         if (nOKBands > 0)
    2384             :         {
    2385         280 :             if (nOKBands < nBandCount)
    2386             :             {
    2387          55 :                 psExtraArg->pfnProgress = GDALScaledProgress;
    2388         110 :                 psExtraArg->pProgressData = GDALCreateScaledProgress(
    2389          55 :                     0.0, static_cast<double>(nOKBands) / nBandCount,
    2390             :                     pfnProgressGlobal, pProgressDataGlobal);
    2391          55 :                 if (psExtraArg->pProgressData == nullptr)
    2392          53 :                     psExtraArg->pfnProgress = nullptr;
    2393             :             }
    2394             : 
    2395         280 :             eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
    2396             :                                      pData, nBufXSize, nBufYSize, eBufType,
    2397             :                                      nOKBands, panBandMap, nPixelSpace,
    2398             :                                      nLineSpace, nBandSpace, psExtraArg);
    2399             : 
    2400         280 :             if (nOKBands < nBandCount)
    2401             :             {
    2402          55 :                 GDALDestroyScaledProgress(psExtraArg->pProgressData);
    2403             :             }
    2404             :         }
    2405         323 :         if (eErr == CE_None && nOKBands < nBandCount)
    2406             :         {
    2407          92 :             if (nOKBands > 0)
    2408             :             {
    2409          53 :                 psExtraArg->pfnProgress = GDALScaledProgress;
    2410         106 :                 psExtraArg->pProgressData = GDALCreateScaledProgress(
    2411          53 :                     static_cast<double>(nOKBands) / nBandCount, 1.0,
    2412             :                     pfnProgressGlobal, pProgressDataGlobal);
    2413          53 :                 if (psExtraArg->pProgressData == nullptr)
    2414          51 :                     psExtraArg->pfnProgress = nullptr;
    2415             :             }
    2416         184 :             eErr = BandBasedRasterIO(
    2417             :                 eRWFlag, nXOff, nYOff, nXSize, nYSize,
    2418          92 :                 static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,
    2419             :                 nBufYSize, eBufType, nBandCount - nOKBands,
    2420          92 :                 panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,
    2421             :                 psExtraArg);
    2422          92 :             if (nOKBands > 0)
    2423             :             {
    2424          53 :                 GDALDestroyScaledProgress(psExtraArg->pProgressData);
    2425             :             }
    2426             :         }
    2427             : 
    2428         319 :         psExtraArg->pfnProgress = pfnProgressGlobal;
    2429         319 :         psExtraArg->pProgressData = pProgressDataGlobal;
    2430             : 
    2431         319 :         return eErr;
    2432             :     }
    2433             : 
    2434      374927 :     return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
    2435             :                              nBufXSize, nBufYSize, eBufType, nBandCount,
    2436             :                              panBandMap, nPixelSpace, nLineSpace, nBandSpace,
    2437      374919 :                              psExtraArg);
    2438             : }
    2439             : 
    2440             : //! @endcond
    2441             : 
    2442             : /************************************************************************/
    2443             : /*                         BandBasedRasterIO()                          */
    2444             : /*                                                                      */
    2445             : /*      Pass the request off to each band objects rasterio methods with */
    2446             : /*      appropriate arguments.                                          */
    2447             : /************************************************************************/
    2448             : 
    2449             : //! @cond Doxygen_Suppress
    2450      637605 : CPLErr GDALDataset::BandBasedRasterIO(
    2451             :     GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
    2452             :     void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
    2453             :     int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
    2454             :     GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
    2455             : 
    2456             : {
    2457             :     int iBandIndex;
    2458      637605 :     CPLErr eErr = CE_None;
    2459             : 
    2460      637605 :     GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
    2461      637605 :     void *pProgressDataGlobal = psExtraArg->pProgressData;
    2462             : 
    2463     1567450 :     for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
    2464             :          ++iBandIndex)
    2465             :     {
    2466      929821 :         GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
    2467             : 
    2468      929827 :         if (poBand == nullptr)
    2469             :         {
    2470           0 :             eErr = CE_Failure;
    2471           0 :             break;
    2472             :         }
    2473             : 
    2474      929827 :         GByte *pabyBandData =
    2475      929827 :             static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
    2476             : 
    2477      929827 :         if (nBandCount > 1)
    2478             :         {
    2479      428653 :             psExtraArg->pfnProgress = GDALScaledProgress;
    2480      857310 :             psExtraArg->pProgressData = GDALCreateScaledProgress(
    2481             :                 1.0 * iBandIndex / nBandCount,
    2482      428653 :                 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
    2483             :                 pProgressDataGlobal);
    2484      428657 :             if (psExtraArg->pProgressData == nullptr)
    2485      425086 :                 psExtraArg->pfnProgress = nullptr;
    2486             :         }
    2487             : 
    2488     1859680 :         eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
    2489             :                                  pabyBandData, nBufXSize, nBufYSize, eBufType,
    2490      929831 :                                  nPixelSpace, nLineSpace, psExtraArg);
    2491             : 
    2492      929852 :         if (nBandCount > 1)
    2493      428677 :             GDALDestroyScaledProgress(psExtraArg->pProgressData);
    2494             :     }
    2495             : 
    2496      637628 :     psExtraArg->pfnProgress = pfnProgressGlobal;
    2497      637628 :     psExtraArg->pProgressData = pProgressDataGlobal;
    2498             : 
    2499      637628 :     return eErr;
    2500             : }
    2501             : 
    2502             : //! @endcond
    2503             : 
    2504             : /************************************************************************/
    2505             : /*               ValidateRasterIOOrAdviseReadParameters()               */
    2506             : /************************************************************************/
    2507             : 
    2508             : //! @cond Doxygen_Suppress
    2509      726890 : CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
    2510             :     const char *pszCallingFunc, int *pbStopProcessingOnCENone, int nXOff,
    2511             :     int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize,
    2512             :     int nBandCount, const int *panBandMap)
    2513             : {
    2514             : 
    2515             :     /* -------------------------------------------------------------------- */
    2516             :     /*      Some size values are "noop".  Lets just return to avoid         */
    2517             :     /*      stressing lower level functions.                                */
    2518             :     /* -------------------------------------------------------------------- */
    2519      726890 :     if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)
    2520             :     {
    2521          19 :         CPLDebug("GDAL",
    2522             :                  "%s skipped for odd window or buffer size.\n"
    2523             :                  "  Window = (%d,%d)x%dx%d\n"
    2524             :                  "  Buffer = %dx%d",
    2525             :                  pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nBufXSize,
    2526             :                  nBufYSize);
    2527             : 
    2528           4 :         *pbStopProcessingOnCENone = TRUE;
    2529           4 :         return CE_None;
    2530             :     }
    2531             : 
    2532      726871 :     CPLErr eErr = CE_None;
    2533      726871 :     *pbStopProcessingOnCENone = FALSE;
    2534             : 
    2535      726871 :     if (nXOff < 0 || nXOff > INT_MAX - nXSize ||
    2536      726872 :         nXOff + nXSize > nRasterXSize || nYOff < 0 ||
    2537      726877 :         nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)
    2538             :     {
    2539           0 :         ReportError(CE_Failure, CPLE_IllegalArg,
    2540             :                     "Access window out of range in %s.  Requested "
    2541             :                     "(%d,%d) of size %dx%d on raster of %dx%d.",
    2542             :                     pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
    2543             :                     nRasterYSize);
    2544           2 :         eErr = CE_Failure;
    2545             :     }
    2546             : 
    2547      726873 :     if (panBandMap == nullptr && nBandCount > GetRasterCount())
    2548             :     {
    2549           0 :         ReportError(CE_Failure, CPLE_IllegalArg,
    2550             :                     "%s: nBandCount cannot be greater than %d", pszCallingFunc,
    2551             :                     GetRasterCount());
    2552           0 :         eErr = CE_Failure;
    2553             :     }
    2554             : 
    2555     1967380 :     for (int i = 0; i < nBandCount && eErr == CE_None; ++i)
    2556             :     {
    2557     1240510 :         int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
    2558     1240510 :         if (iBand < 1 || iBand > GetRasterCount())
    2559             :         {
    2560           3 :             ReportError(
    2561             :                 CE_Failure, CPLE_IllegalArg,
    2562             :                 "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
    2563             :                 pszCallingFunc, i, iBand);
    2564           3 :             eErr = CE_Failure;
    2565             :         }
    2566             : 
    2567     1240500 :         if (eErr == CE_None && GetRasterBand(iBand) == nullptr)
    2568             :         {
    2569           0 :             ReportError(
    2570             :                 CE_Failure, CPLE_IllegalArg,
    2571             :                 "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
    2572             :                 pszCallingFunc, i, iBand);
    2573           0 :             eErr = CE_Failure;
    2574             :         }
    2575             :     }
    2576             : 
    2577      726864 :     return eErr;
    2578             : }
    2579             : 
    2580             : //! @endcond
    2581             : 
    2582             : /************************************************************************/
    2583             : /*                              RasterIO()                              */
    2584             : /************************************************************************/
    2585             : 
    2586             : /**
    2587             :  * \brief Read/write a region of image data from multiple bands.
    2588             :  *
    2589             :  * This method allows reading a region of one or more GDALRasterBands from
    2590             :  * this dataset into a buffer,  or writing data from a buffer into a region
    2591             :  * of the GDALRasterBands.  It automatically takes care of data type
    2592             :  * translation if the data type (eBufType) of the buffer is different than
    2593             :  * that of the GDALRasterBand.
    2594             :  * The method also takes care of image decimation / replication if the
    2595             :  * buffer size (nBufXSize x nBufYSize) is different than the size of the
    2596             :  * region being accessed (nXSize x nYSize).
    2597             :  *
    2598             :  * The window of interest expressed by (nXOff, nYOff, nXSize, nYSize) should be
    2599             :  * fully within the raster space, that is nXOff >= 0, nYOff >= 0,
    2600             :  * nXOff + nXSize <= GetRasterXSize() and nYOff + nYSize <= GetRasterYSize().
    2601             :  * If reads larger than the raster space are wished, GDALTranslate() might be used.
    2602             :  * Or use nLineSpace and a possibly shifted pData value.
    2603             :  *
    2604             :  * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
    2605             :  * writing from various organization of buffers.
    2606             :  *
    2607             :  * Some formats may efficiently implement decimation into a buffer by
    2608             :  * reading from lower resolution overview images. The logic of the default
    2609             :  * implementation in the base class GDALRasterBand is the following one. It
    2610             :  * computes a target_downscaling_factor from the window of interest and buffer
    2611             :  * size which is min(nXSize/nBufXSize, nYSize/nBufYSize).
    2612             :  * It then walks through overviews and will select the first one whose
    2613             :  * downscaling factor is greater than target_downscaling_factor / 1.2.
    2614             :  *
    2615             :  * Let's assume we have overviews at downscaling factors 2, 4 and 8.
    2616             :  * The relationship between target_downscaling_factor and the select overview
    2617             :  * level is the following one:
    2618             :  *
    2619             :  * target_downscaling_factor  | selected_overview
    2620             :  * -------------------------  | -----------------
    2621             :  * ]0,       2 / 1.2]         | full resolution band
    2622             :  * ]2 / 1.2, 4 / 1.2]         | 2x downsampled band
    2623             :  * ]4 / 1.2, 8 / 1.2]         | 4x downsampled band
    2624             :  * ]8 / 1.2, infinity[        | 8x downsampled band
    2625             :  *
    2626             :  * Note that starting with GDAL 3.9, this 1.2 oversampling factor can be
    2627             :  * modified by setting the GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD configuration
    2628             :  * option. Also note that starting with GDAL 3.9, when the resampling algorithm
    2629             :  * specified in psExtraArg->eResampleAlg is different from GRIORA_NearestNeighbour,
    2630             :  * this oversampling threshold defaults to 1. Consequently if there are overviews
    2631             :  * of downscaling factor 2, 4 and 8, and the desired downscaling factor is
    2632             :  * 7.99, the overview of factor 4 will be selected for a non nearest resampling.
    2633             :  *
    2634             :  * For highest performance full resolution data access, read and write
    2635             :  * on "block boundaries" as returned by GetBlockSize(), or use the
    2636             :  * ReadBlock() and WriteBlock() methods.
    2637             :  *
    2638             :  * This method is the same as the C GDALDatasetRasterIO() or
    2639             :  * GDALDatasetRasterIOEx() functions.
    2640             :  *
    2641             :  * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
    2642             :  * write a region of data.
    2643             :  *
    2644             :  * @param nXOff The pixel offset to the top left corner of the region
    2645             :  * of the band to be accessed.  This would be zero to start from the left side.
    2646             :  *
    2647             :  * @param nYOff The line offset to the top left corner of the region
    2648             :  * of the band to be accessed.  This would be zero to start from the top.
    2649             :  *
    2650             :  * @param nXSize The width of the region of the band to be accessed in pixels.
    2651             :  *
    2652             :  * @param nYSize The height of the region of the band to be accessed in lines.
    2653             :  *
    2654             :  * @param pData The buffer into which the data should be read, or from which
    2655             :  * it should be written.  This buffer must contain at least
    2656             :  * nBufXSize * nBufYSize * nBandCount words of type eBufType.  It is organized
    2657             :  * in left to right,top to bottom pixel order.  Spacing is controlled by the
    2658             :  * nPixelSpace, and nLineSpace parameters.
    2659             :  * Note that even with eRWFlag==GF_Write, the content of the buffer might be
    2660             :  * temporarily modified during the execution of this method (and eventually
    2661             :  * restored back to its original content), so it is not safe to use a buffer
    2662             :  * stored in a read-only section of the calling program.
    2663             :  *
    2664             :  * @param nBufXSize the width of the buffer image into which the desired region
    2665             :  * is to be read, or from which it is to be written.
    2666             :  *
    2667             :  * @param nBufYSize the height of the buffer image into which the desired
    2668             :  * region is to be read, or from which it is to be written.
    2669             :  *
    2670             :  * @param eBufType the type of the pixel values in the pData data buffer. The
    2671             :  * pixel values will automatically be translated to/from the GDALRasterBand
    2672             :  * data type as needed. Most driver implementations will use GDALCopyWords64()
    2673             :  * to perform data type translation.
    2674             :  *
    2675             :  * @param nBandCount the number of bands being read or written.
    2676             :  *
    2677             :  * @param panBandMap the list of nBandCount band numbers being read/written.
    2678             :  * Note band numbers are 1 based. This may be NULL to select the first
    2679             :  * nBandCount bands. (Note: before GDAL 3.10, argument type was "int*", and
    2680             :  * not "const int*")
    2681             :  *
    2682             :  * @param nPixelSpace The byte offset from the start of one pixel value in
    2683             :  * pData to the start of the next pixel value within a scanline. If defaulted
    2684             :  * (0) the size of the datatype eBufType is used.
    2685             :  *
    2686             :  * @param nLineSpace The byte offset from the start of one scanline in
    2687             :  * pData to the start of the next. If defaulted (0) the size of the datatype
    2688             :  * eBufType * nBufXSize is used.
    2689             :  *
    2690             :  * @param nBandSpace the byte offset from the start of one bands data to the
    2691             :  * start of the next. If defaulted (0) the value will be
    2692             :  * nLineSpace * nBufYSize implying band sequential organization
    2693             :  * of the data buffer.
    2694             :  *
    2695             :  * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
    2696             :  * structure with additional arguments to specify resampling and progress
    2697             :  * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
    2698             :  * configuration option can also be defined to override the default resampling
    2699             :  * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
    2700             :  *
    2701             :  * @return CE_Failure if the access fails, otherwise CE_None.
    2702             :  */
    2703             : 
    2704      714327 : CPLErr GDALDataset::RasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
    2705             :                              int nXSize, int nYSize, void *pData, int nBufXSize,
    2706             :                              int nBufYSize, GDALDataType eBufType,
    2707             :                              int nBandCount, const int *panBandMap,
    2708             :                              GSpacing nPixelSpace, GSpacing nLineSpace,
    2709             :                              GSpacing nBandSpace,
    2710             :                              GDALRasterIOExtraArg *psExtraArg)
    2711             : 
    2712             : {
    2713             :     GDALRasterIOExtraArg sExtraArg;
    2714      714327 :     if (psExtraArg == nullptr)
    2715             :     {
    2716      530131 :         INIT_RASTERIO_EXTRA_ARG(sExtraArg);
    2717             : 
    2718             :         // 4 below inits are not strictly needed but make Coverity Scan
    2719             :         // happy
    2720      530131 :         sExtraArg.dfXOff = nXOff;
    2721      530131 :         sExtraArg.dfYOff = nYOff;
    2722      530131 :         sExtraArg.dfXSize = nXSize;
    2723      530131 :         sExtraArg.dfYSize = nYSize;
    2724             : 
    2725      530131 :         psExtraArg = &sExtraArg;
    2726             :     }
    2727      184196 :     else if (CPL_UNLIKELY(psExtraArg->nVersion !=
    2728             :                           RASTERIO_EXTRA_ARG_CURRENT_VERSION))
    2729             :     {
    2730           0 :         ReportError(CE_Failure, CPLE_AppDefined,
    2731             :                     "Unhandled version of GDALRasterIOExtraArg");
    2732           0 :         return CE_Failure;
    2733             :     }
    2734             : 
    2735      714327 :     GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
    2736             :                                        nBufYSize);
    2737             : 
    2738      714309 :     if (CPL_UNLIKELY(nullptr == pData))
    2739             :     {
    2740           0 :         ReportError(CE_Failure, CPLE_AppDefined,
    2741             :                     "The buffer into which the data should be read is null");
    2742           0 :         return CE_Failure;
    2743             :     }
    2744             : 
    2745             :     /* -------------------------------------------------------------------- */
    2746             :     /*      Do some validation of parameters.                               */
    2747             :     /* -------------------------------------------------------------------- */
    2748             : 
    2749      714309 :     if (CPL_UNLIKELY(eRWFlag != GF_Read && eRWFlag != GF_Write))
    2750             :     {
    2751           0 :         ReportError(
    2752             :             CE_Failure, CPLE_IllegalArg,
    2753             :             "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
    2754             :             eRWFlag);
    2755           0 :         return CE_Failure;
    2756             :     }
    2757             : 
    2758      714309 :     if (eRWFlag == GF_Write)
    2759             :     {
    2760      212502 :         if (CPL_UNLIKELY(eAccess != GA_Update))
    2761             :         {
    2762           2 :             ReportError(CE_Failure, CPLE_AppDefined,
    2763             :                         "Write operation not permitted on dataset opened "
    2764             :                         "in read-only mode");
    2765           2 :             return CE_Failure;
    2766             :         }
    2767             :     }
    2768             : 
    2769      714307 :     int bStopProcessing = FALSE;
    2770      714307 :     CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
    2771             :         "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
    2772             :         nBufYSize, nBandCount, panBandMap);
    2773      714327 :     if (eErr != CE_None || bStopProcessing)
    2774          20 :         return eErr;
    2775      714307 :     if (CPL_UNLIKELY(eBufType == GDT_Unknown || eBufType == GDT_TypeCount))
    2776             :     {
    2777           2 :         ReportError(CE_Failure, CPLE_AppDefined,
    2778             :                     "Illegal GDT_Unknown/GDT_TypeCount argument");
    2779           2 :         return CE_Failure;
    2780             :     }
    2781             : 
    2782             :     /* -------------------------------------------------------------------- */
    2783             :     /*      If pixel and line spacing are defaulted assign reasonable      */
    2784             :     /*      value assuming a packed buffer.                                 */
    2785             :     /* -------------------------------------------------------------------- */
    2786      714305 :     if (nPixelSpace == 0)
    2787      415454 :         nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
    2788             : 
    2789      714297 :     if (nLineSpace == 0)
    2790             :     {
    2791      518620 :         nLineSpace = nPixelSpace * nBufXSize;
    2792             :     }
    2793             : 
    2794      714297 :     if (nBandSpace == 0 && nBandCount > 1)
    2795             :     {
    2796       67349 :         nBandSpace = nLineSpace * nBufYSize;
    2797             :     }
    2798             : 
    2799      714297 :     if (panBandMap == nullptr)
    2800             :     {
    2801      352163 :         if (!m_poPrivate)
    2802           0 :             return CE_Failure;
    2803      352163 :         CPLAssert(static_cast<int>(m_poPrivate->m_anBandMap.size()) == nBands);
    2804      352163 :         panBandMap = m_poPrivate->m_anBandMap.data();
    2805             :     }
    2806             : 
    2807      714296 :     int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
    2808             : 
    2809             :     /* -------------------------------------------------------------------- */
    2810             :     /*      We are being forced to use cached IO instead of a driver        */
    2811             :     /*      specific implementation.                                        */
    2812             :     /* -------------------------------------------------------------------- */
    2813      714313 :     if (bForceCachedIO)
    2814             :     {
    2815           7 :         eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
    2816             :                                   nBufXSize, nBufYSize, eBufType, nBandCount,
    2817             :                                   panBandMap, nPixelSpace, nLineSpace,
    2818           7 :                                   nBandSpace, psExtraArg);
    2819             :     }
    2820             : 
    2821             :     /* -------------------------------------------------------------------- */
    2822             :     /*      Call the format specific function.                              */
    2823             :     /* -------------------------------------------------------------------- */
    2824             :     else
    2825             :     {
    2826      714314 :         eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
    2827             :                          nBufXSize, nBufYSize, eBufType, nBandCount,
    2828             :                          // TODO: remove this const_cast once IRasterIO()
    2829             :                          // takes a const int*
    2830             :                          const_cast<int *>(panBandMap), nPixelSpace, nLineSpace,
    2831      714306 :                          nBandSpace, psExtraArg);
    2832             :     }
    2833             : 
    2834      714321 :     if (bCallLeaveReadWrite)
    2835      400467 :         LeaveReadWrite();
    2836             : 
    2837      714321 :     return eErr;
    2838             : }
    2839             : 
    2840             : /************************************************************************/
    2841             : /*                        GDALDatasetRasterIO()                         */
    2842             : /************************************************************************/
    2843             : 
    2844             : /**
    2845             :  * \brief Read/write a region of image data from multiple bands.
    2846             :  *
    2847             :  * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
    2848             :  * resolution, progress callback, etc. are needed)
    2849             :  *
    2850             :  * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
    2851             :  *
    2852             :  * @see GDALDataset::RasterIO()
    2853             :  */
    2854             : 
    2855        4395 : CPLErr CPL_STDCALL GDALDatasetRasterIO(GDALDatasetH hDS, GDALRWFlag eRWFlag,
    2856             :                                        int nXOff, int nYOff, int nXSize,
    2857             :                                        int nYSize, void *pData, int nBufXSize,
    2858             :                                        int nBufYSize, GDALDataType eBufType,
    2859             :                                        int nBandCount, const int *panBandMap,
    2860             :                                        int nPixelSpace, int nLineSpace,
    2861             :                                        int nBandSpace)
    2862             : 
    2863             : {
    2864        4395 :     VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
    2865             : 
    2866        4395 :     GDALDataset *poDS = GDALDataset::FromHandle(hDS);
    2867             : 
    2868        4395 :     return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
    2869             :                           nBufXSize, nBufYSize, eBufType, nBandCount,
    2870             :                           panBandMap, nPixelSpace, nLineSpace, nBandSpace,
    2871        4395 :                           nullptr);
    2872             : }
    2873             : 
    2874             : /************************************************************************/
    2875             : /*                       GDALDatasetRasterIOEx()                        */
    2876             : /************************************************************************/
    2877             : 
    2878             : /**
    2879             :  * \brief Read/write a region of image data from multiple bands.
    2880             :  *
    2881             :  * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
    2882             :  *
    2883             :  * @see GDALDataset::RasterIO()
    2884             :  * @since GDAL 2.0
    2885             :  */
    2886             : 
    2887      350457 : CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
    2888             :     GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
    2889             :     int nYSize, void *pData, int nBufXSize, int nBufYSize,
    2890             :     GDALDataType eBufType, int nBandCount, const int *panBandMap,
    2891             :     GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
    2892             :     GDALRasterIOExtraArg *psExtraArg)
    2893             : 
    2894             : {
    2895      350457 :     VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
    2896             : 
    2897      350457 :     GDALDataset *poDS = GDALDataset::FromHandle(hDS);
    2898             : 
    2899      350457 :     return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
    2900             :                           nBufXSize, nBufYSize, eBufType, nBandCount,
    2901             :                           panBandMap, nPixelSpace, nLineSpace, nBandSpace,
    2902      350457 :                           psExtraArg);
    2903             : }
    2904             : 
    2905             : /************************************************************************/
    2906             : /*                          GetOpenDatasets()                           */
    2907             : /************************************************************************/
    2908             : 
    2909             : /**
    2910             :  * \brief Fetch all open GDAL dataset handles.
    2911             :  *
    2912             :  * This method is the same as the C function GDALGetOpenDatasets().
    2913             :  *
    2914             :  * NOTE: This method is not thread safe.  The returned list may change
    2915             :  * at any time and it should not be freed.
    2916             :  *
    2917             :  * @param pnCount integer into which to place the count of dataset pointers
    2918             :  * being returned.
    2919             :  *
    2920             :  * @return a pointer to an array of dataset handles.
    2921             :  */
    2922             : 
    2923        1884 : GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)
    2924             : 
    2925             : {
    2926        3768 :     CPLMutexHolderD(&hDLMutex);
    2927             : 
    2928        1884 :     if (poAllDatasetMap == nullptr)
    2929             :     {
    2930        1858 :         *pnCount = 0;
    2931        1858 :         return nullptr;
    2932             :     }
    2933             : 
    2934          26 :     *pnCount = static_cast<int>(poAllDatasetMap->size());
    2935          26 :     ppDatasets = static_cast<GDALDataset **>(
    2936          26 :         CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
    2937          26 :     std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();
    2938         715 :     for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)
    2939         689 :         ppDatasets[i] = oIter->first;
    2940          26 :     return ppDatasets;
    2941             : }
    2942             : 
    2943             : /************************************************************************/
    2944             : /*                        GDALGetOpenDatasets()                         */
    2945             : /************************************************************************/
    2946             : 
    2947             : /**
    2948             :  * \brief Fetch all open GDAL dataset handles.
    2949             :  *
    2950             :  * @see GDALDataset::GetOpenDatasets()
    2951             :  */
    2952             : 
    2953           0 : void CPL_STDCALL GDALGetOpenDatasets(GDALDatasetH **ppahDSList, int *pnCount)
    2954             : 
    2955             : {
    2956           0 :     VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
    2957           0 :     VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
    2958             : 
    2959           0 :     *ppahDSList =
    2960           0 :         reinterpret_cast<GDALDatasetH *>(GDALDataset::GetOpenDatasets(pnCount));
    2961             : }
    2962             : 
    2963             : /************************************************************************/
    2964             : /*                        GDALCleanOpenDatasetsList()                   */
    2965             : /************************************************************************/
    2966             : 
    2967             : // Useful when called from the child of a fork(), to avoid closing
    2968             : // the datasets of the parent at the child termination.
    2969           0 : void GDALNullifyOpenDatasetsList()
    2970             : {
    2971           0 :     poAllDatasetMap = nullptr;
    2972           0 :     phSharedDatasetSet = nullptr;
    2973           0 :     ppDatasets = nullptr;
    2974           0 :     hDLMutex = nullptr;
    2975           0 : }
    2976             : 
    2977             : /************************************************************************/
    2978             : /*                             GDALGetAccess()                          */
    2979             : /************************************************************************/
    2980             : 
    2981             : /**
    2982             :  * \brief Return access flag
    2983             :  *
    2984             :  * @see GDALDataset::GetAccess()
    2985             :  */
    2986             : 
    2987           0 : int CPL_STDCALL GDALGetAccess(GDALDatasetH hDS)
    2988             : {
    2989           0 :     VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
    2990             : 
    2991           0 :     return GDALDataset::FromHandle(hDS)->GetAccess();
    2992             : }
    2993             : 
    2994             : /************************************************************************/
    2995             : /*                             AdviseRead()                             */
    2996             : /************************************************************************/
    2997             : 
    2998             : /**
    2999             :  * \brief Advise driver of upcoming read requests.
    3000             :  *
    3001             :  * Some GDAL drivers operate more efficiently if they know in advance what
    3002             :  * set of upcoming read requests will be made.  The AdviseRead() method allows
    3003             :  * an application to notify the driver of the region and bands of interest,
    3004             :  * and at what resolution the region will be read.
    3005             :  *
    3006             :  * Many drivers just ignore the AdviseRead() call, but it can dramatically
    3007             :  * accelerate access via some drivers.
    3008             :  *
    3009             :  * Depending on call paths, drivers might receive several calls to
    3010             :  * AdviseRead() with the same parameters.
    3011             :  *
    3012             :  * @param nXOff The pixel offset to the top left corner of the region
    3013             :  * of the band to be accessed.  This would be zero to start from the left side.
    3014             :  *
    3015             :  * @param nYOff The line offset to the top left corner of the region
    3016             :  * of the band to be accessed.  This would be zero to start from the top.
    3017             :  *
    3018             :  * @param nXSize The width of the region of the band to be accessed in pixels.
    3019             :  *
    3020             :  * @param nYSize The height of the region of the band to be accessed in lines.
    3021             :  *
    3022             :  * @param nBufXSize the width of the buffer image into which the desired region
    3023             :  * is to be read, or from which it is to be written.
    3024             :  *
    3025             :  * @param nBufYSize the height of the buffer image into which the desired
    3026             :  * region is to be read, or from which it is to be written.
    3027             :  *
    3028             :  * @param eBufType the type of the pixel values in the pData data buffer.  The
    3029             :  * pixel values will automatically be translated to/from the GDALRasterBand
    3030             :  * data type as needed.
    3031             :  *
    3032             :  * @param nBandCount the number of bands being read or written.
    3033             :  *
    3034             :  * @param panBandMap the list of nBandCount band numbers being read/written.
    3035             :  * Note band numbers are 1 based.   This may be NULL to select the first
    3036             :  * nBandCount bands.
    3037             :  *
    3038             :  * @param papszOptions a list of name=value strings with special control
    3039             :  * options.  Normally this is NULL.
    3040             :  *
    3041             :  * @return CE_Failure if the request is invalid and CE_None if it works or
    3042             :  * is ignored.
    3043             :  */
    3044             : 
    3045       12313 : CPLErr GDALDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
    3046             :                                int nBufXSize, int nBufYSize,
    3047             :                                GDALDataType eBufType, int nBandCount,
    3048             :                                int *panBandMap, char **papszOptions)
    3049             : 
    3050             : {
    3051             :     /* -------------------------------------------------------------------- */
    3052             :     /*      Do some validation of parameters.                               */
    3053             :     /* -------------------------------------------------------------------- */
    3054       12313 :     int bStopProcessing = FALSE;
    3055       12313 :     CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
    3056             :         "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
    3057             :         nBufXSize, nBufYSize, nBandCount, panBandMap);
    3058       12313 :     if (eErr != CE_None || bStopProcessing)
    3059           0 :         return eErr;
    3060             : 
    3061       54272 :     for (int iBand = 0; iBand < nBandCount; ++iBand)
    3062             :     {
    3063       41959 :         GDALRasterBand *poBand = nullptr;
    3064             : 
    3065       41959 :         if (panBandMap == nullptr)
    3066       40694 :             poBand = GetRasterBand(iBand + 1);
    3067             :         else
    3068        1265 :             poBand = GetRasterBand(panBandMap[iBand]);
    3069             : 
    3070       41959 :         if (poBand == nullptr)
    3071           0 :             return CE_Failure;
    3072             : 
    3073       83918 :         eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
    3074       41959 :                                   nBufYSize, eBufType, papszOptions);
    3075             : 
    3076       41959 :         if (eErr != CE_None)
    3077           0 :             return eErr;
    3078             :     }
    3079             : 
    3080       12313 :     return CE_None;
    3081             : }
    3082             : 
    3083             : /************************************************************************/
    3084             : /*                       GDALDatasetAdviseRead()                        */
    3085             : /************************************************************************/
    3086             : 
    3087             : /**
    3088             :  * \brief Advise driver of upcoming read requests.
    3089             :  *
    3090             :  * @see GDALDataset::AdviseRead()
    3091             :  */
    3092           1 : CPLErr CPL_STDCALL GDALDatasetAdviseRead(GDALDatasetH hDS, int nXOff, int nYOff,
    3093             :                                          int nXSize, int nYSize, int nBufXSize,
    3094             :                                          int nBufYSize, GDALDataType eDT,
    3095             :                                          int nBandCount, int *panBandMap,
    3096             :                                          CSLConstList papszOptions)
    3097             : 
    3098             : {
    3099           1 :     VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
    3100             : 
    3101           2 :     return GDALDataset::FromHandle(hDS)->AdviseRead(
    3102             :         nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount,
    3103           1 :         panBandMap, const_cast<char **>(papszOptions));
    3104             : }
    3105             : 
    3106             : /************************************************************************/
    3107             : /*                         GDALAntiRecursionStruct                      */
    3108             : /************************************************************************/
    3109             : 
    3110             : // Prevent infinite recursion.
    3111             : struct GDALAntiRecursionStruct
    3112             : {
    3113             :     struct DatasetContext
    3114             :     {
    3115             :         std::string osFilename;
    3116             :         int nOpenFlags;
    3117             :         std::string osAllowedDrivers;
    3118             : 
    3119       72075 :         DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,
    3120             :                        const std::string &osAllowedDriversIn)
    3121       72075 :             : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),
    3122       72075 :               osAllowedDrivers(osAllowedDriversIn)
    3123             :         {
    3124       72075 :         }
    3125             :     };
    3126             : 
    3127             :     struct DatasetContextCompare
    3128             :     {
    3129     1121580 :         bool operator()(const DatasetContext &lhs,
    3130             :                         const DatasetContext &rhs) const
    3131             :         {
    3132     3278510 :             return lhs.osFilename < rhs.osFilename ||
    3133     1086050 :                    (lhs.osFilename == rhs.osFilename &&
    3134     1071090 :                     (lhs.nOpenFlags < rhs.nOpenFlags ||
    3135     2140580 :                      (lhs.nOpenFlags == rhs.nOpenFlags &&
    3136     2191930 :                       lhs.osAllowedDrivers < rhs.osAllowedDrivers)));
    3137             :         }
    3138             :     };
    3139             : 
    3140             :     std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
    3141             :     int nRecLevel = 0;
    3142             :     std::map<std::string, int> m_oMapDepth{};
    3143             : };
    3144             : 
    3145             : #ifdef _WIN32
    3146             : // Currently thread_local and C++ objects don't work well with DLL on Windows
    3147             : static void FreeAntiRecursionOpen(void *pData)
    3148             : {
    3149             :     delete static_cast<GDALAntiRecursionStruct *>(pData);
    3150             : }
    3151             : 
    3152             : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
    3153             : {
    3154             :     static GDALAntiRecursionStruct dummy;
    3155             :     int bMemoryErrorOccurred = false;
    3156             :     void *pData =
    3157             :         CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
    3158             :     if (bMemoryErrorOccurred)
    3159             :     {
    3160             :         return dummy;
    3161             :     }
    3162             :     if (pData == nullptr)
    3163             :     {
    3164             :         auto pAntiRecursion = new GDALAntiRecursionStruct();
    3165             :         CPLSetTLSWithFreeFuncEx(CTLS_GDALOPEN_ANTIRECURSION, pAntiRecursion,
    3166             :                                 FreeAntiRecursionOpen, &bMemoryErrorOccurred);
    3167             :         if (bMemoryErrorOccurred)
    3168             :         {
    3169             :             delete pAntiRecursion;
    3170             :             return dummy;
    3171             :         }
    3172             :         return *pAntiRecursion;
    3173             :     }
    3174             :     return *static_cast<GDALAntiRecursionStruct *>(pData);
    3175             : }
    3176             : #else
    3177             : static thread_local GDALAntiRecursionStruct g_tls_antiRecursion;
    3178             : 
    3179      125993 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
    3180             : {
    3181      125993 :     return g_tls_antiRecursion;
    3182             : }
    3183             : #endif
    3184             : 
    3185             : //! @cond Doxygen_Suppress
    3186       53917 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)
    3187       53917 :     : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),
    3188             :       m_osIdentifier(osIdentifier),
    3189       53917 :       m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
    3190             : {
    3191       53917 :     CPLAssert(!osIdentifier.empty());
    3192       53917 : }
    3193             : 
    3194       53917 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(
    3195       53917 :     const GDALAntiRecursionGuard &other, const std::string &osIdentifier)
    3196       53917 :     : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),
    3197       53917 :       m_osIdentifier(osIdentifier.empty()
    3198             :                          ? osIdentifier
    3199       26852 :                          : other.m_osIdentifier + osIdentifier),
    3200       53917 :       m_nDepth(m_osIdentifier.empty()
    3201       53917 :                    ? 0
    3202       80769 :                    : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
    3203             : {
    3204       53917 : }
    3205             : 
    3206      107834 : GDALAntiRecursionGuard::~GDALAntiRecursionGuard()
    3207             : {
    3208      107834 :     if (!m_osIdentifier.empty())
    3209             :     {
    3210       80769 :         --m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier];
    3211             :     }
    3212      107834 : }
    3213             : 
    3214             : //! @endcond
    3215             : 
    3216             : /************************************************************************/
    3217             : /*                            GetFileList()                             */
    3218             : /************************************************************************/
    3219             : 
    3220             : /**
    3221             :  * \brief Fetch files forming dataset.
    3222             :  *
    3223             :  * Returns a list of files believed to be part of this dataset.  If it returns
    3224             :  * an empty list of files it means there is believed to be no local file
    3225             :  * system files associated with the dataset (for instance a virtual dataset).
    3226             :  * The returned file list is owned by the caller and should be deallocated
    3227             :  * with CSLDestroy().
    3228             :  *
    3229             :  * The returned filenames will normally be relative or absolute paths
    3230             :  * depending on the path used to originally open the dataset.  The strings
    3231             :  * will be UTF-8 encoded.
    3232             :  *
    3233             :  * This method is the same as the C GDALGetFileList() function.
    3234             :  *
    3235             :  * @return NULL or a NULL terminated array of file names.
    3236             :  */
    3237             : 
    3238        4776 : char **GDALDataset::GetFileList()
    3239             : 
    3240             : {
    3241        9552 :     CPLString osMainFilename = GetDescription();
    3242             :     VSIStatBufL sStat;
    3243             : 
    3244        4776 :     GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
    3245             :     const GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,
    3246        9552 :                                                               std::string());
    3247        4776 :     auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
    3248        4776 :     if (cpl::contains(aosDatasetList, datasetCtxt))
    3249           0 :         return nullptr;
    3250             : 
    3251             :     /* -------------------------------------------------------------------- */
    3252             :     /*      Is the main filename even a real filesystem object?             */
    3253             :     /* -------------------------------------------------------------------- */
    3254             :     int bMainFileReal =
    3255        4776 :         VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
    3256             : 
    3257             :     /* -------------------------------------------------------------------- */
    3258             :     /*      Form new list.                                                  */
    3259             :     /* -------------------------------------------------------------------- */
    3260        4776 :     char **papszList = nullptr;
    3261             : 
    3262        4776 :     if (bMainFileReal)
    3263        4721 :         papszList = CSLAddString(papszList, osMainFilename);
    3264             : 
    3265        4776 :     if (sAntiRecursion.nRecLevel == 100)
    3266             :     {
    3267           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    3268             :                  "GetFileList() called with too many recursion levels");
    3269           0 :         return papszList;
    3270             :     }
    3271        4776 :     ++sAntiRecursion.nRecLevel;
    3272             : 
    3273             :     /* -------------------------------------------------------------------- */
    3274             :     /*      Do we have a known overview file?                               */
    3275             :     /* -------------------------------------------------------------------- */
    3276        4776 :     if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
    3277             :     {
    3278          63 :         auto iter = aosDatasetList.insert(datasetCtxt).first;
    3279          63 :         char **papszOvrList = oOvManager.poODS->GetFileList();
    3280          63 :         papszList = CSLInsertStrings(papszList, -1, papszOvrList);
    3281          63 :         CSLDestroy(papszOvrList);
    3282          63 :         aosDatasetList.erase(iter);
    3283             :     }
    3284             : 
    3285             :     /* -------------------------------------------------------------------- */
    3286             :     /*      Do we have a known mask file?                                   */
    3287             :     /* -------------------------------------------------------------------- */
    3288        4776 :     if (oOvManager.HaveMaskFile())
    3289             :     {
    3290          11 :         auto iter = aosDatasetList.insert(datasetCtxt).first;
    3291          11 :         for (const char *pszFile :
    3292          22 :              CPLStringList(oOvManager.poMaskDS->GetFileList()))
    3293             :         {
    3294          11 :             if (CSLFindString(papszList, pszFile) < 0)
    3295          11 :                 papszList = CSLAddString(papszList, pszFile);
    3296             :         }
    3297          11 :         aosDatasetList.erase(iter);
    3298             :     }
    3299             : 
    3300        4776 :     --sAntiRecursion.nRecLevel;
    3301             : 
    3302        4776 :     return papszList;
    3303             : }
    3304             : 
    3305             : /************************************************************************/
    3306             : /*                          GDALGetFileList()                           */
    3307             : /************************************************************************/
    3308             : 
    3309             : /**
    3310             :  * \brief Fetch files forming dataset.
    3311             :  *
    3312             :  * @see GDALDataset::GetFileList()
    3313             :  */
    3314             : 
    3315        3982 : char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)
    3316             : 
    3317             : {
    3318        3982 :     VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
    3319             : 
    3320        3982 :     return GDALDataset::FromHandle(hDS)->GetFileList();
    3321             : }
    3322             : 
    3323             : /************************************************************************/
    3324             : /*                           CreateMaskBand()                           */
    3325             : /************************************************************************/
    3326             : 
    3327             : /**
    3328             :  * \brief Adds a mask band to the dataset
    3329             :  *
    3330             :  * The default implementation of the CreateMaskBand() method is implemented
    3331             :  * based on similar rules to the .ovr handling implemented using the
    3332             :  * GDALDefaultOverviews object. A TIFF file with the extension .msk will
    3333             :  * be created with the same basename as the original file, and it will have
    3334             :  * one band.
    3335             :  * The mask images will be deflate compressed tiled images with the same
    3336             :  * block size as the original image if possible.
    3337             :  * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
    3338             :  * level, where xx matches the band number of a band of the main dataset. The
    3339             :  * value of those items will be the one of the nFlagsIn parameter.
    3340             :  *
    3341             :  * Note that if you got a mask band with a previous call to GetMaskBand(), it
    3342             :  * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
    3343             :  * again.
    3344             :  *
    3345             :  * @since GDAL 1.5.0
    3346             :  *
    3347             :  * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
    3348             :  *                 GMF_PER_DATASET will be always set, even if not explicitly
    3349             :  *                 specified.
    3350             :  * @return CE_None on success or CE_Failure on an error.
    3351             :  *
    3352             :  * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
    3353             :  * @see GDALRasterBand::CreateMaskBand()
    3354             :  *
    3355             :  */
    3356          17 : CPLErr GDALDataset::CreateMaskBand(int nFlagsIn)
    3357             : 
    3358             : {
    3359          17 :     if (oOvManager.IsInitialized())
    3360             :     {
    3361          17 :         CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
    3362          17 :         if (eErr != CE_None)
    3363           0 :             return eErr;
    3364             : 
    3365             :         // Invalidate existing raster band masks.
    3366          45 :         for (int i = 0; i < nBands; ++i)
    3367             :         {
    3368          28 :             GDALRasterBand *poBand = papoBands[i];
    3369          28 :             poBand->poMask.reset();
    3370             :         }
    3371             : 
    3372          17 :         return CE_None;
    3373             :     }
    3374             : 
    3375           0 :     ReportError(CE_Failure, CPLE_NotSupported,
    3376             :                 "CreateMaskBand() not supported for this dataset.");
    3377             : 
    3378           0 :     return CE_Failure;
    3379             : }
    3380             : 
    3381             : /************************************************************************/
    3382             : /*                     GDALCreateDatasetMaskBand()                      */
    3383             : /************************************************************************/
    3384             : 
    3385             : /**
    3386             :  * \brief Adds a mask band to the dataset
    3387             :  * @see GDALDataset::CreateMaskBand()
    3388             :  */
    3389          84 : CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)
    3390             : 
    3391             : {
    3392          84 :     VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
    3393             : 
    3394          84 :     return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
    3395             : }
    3396             : 
    3397             : /************************************************************************/
    3398             : /*                              GDALOpen()                              */
    3399             : /************************************************************************/
    3400             : 
    3401             : /**
    3402             :  * \brief Open a raster file as a GDALDataset.
    3403             :  *
    3404             :  * This function will try to open the passed file, or virtual dataset
    3405             :  * name by invoking the Open method of each registered GDALDriver in turn.
    3406             :  * The first successful open will result in a returned dataset.  If all
    3407             :  * drivers fail then NULL is returned and an error is issued.
    3408             :  *
    3409             :  * Several recommendations :
    3410             :  * <ul>
    3411             :  * <li>If you open a dataset object with GA_Update access, it is not recommended
    3412             :  * to open a new dataset on the same underlying file.</li>
    3413             :  * <li>The returned dataset should only be accessed by one thread at a time. If
    3414             :  * you want to use it from different threads, you must add all necessary code
    3415             :  * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such
    3416             :  * as GeoTIFF, maintain internal state variables that are updated each time a
    3417             :  * new block is read, thus preventing concurrent use.) </li>
    3418             :  * </ul>
    3419             :  *
    3420             :  * For drivers supporting the VSI virtual file API, it is possible to open a
    3421             :  * file in a .zip archive (see VSIInstallZipFileHandler()), in a
    3422             :  * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
    3423             :  * server (see VSIInstallCurlFileHandler())
    3424             :  *
    3425             :  * \sa GDALOpenShared()
    3426             :  * \sa GDALOpenEx()
    3427             :  *
    3428             :  * @param pszFilename the name of the file to access.  In the case of
    3429             :  * exotic drivers this may not refer to a physical file, but instead contain
    3430             :  * information for the driver on how to access a dataset.  It should be in UTF-8
    3431             :  * encoding.
    3432             :  *
    3433             :  * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
    3434             :  * drivers support only read only access.
    3435             :  *
    3436             :  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
    3437             :  * this handle can be cast to a GDALDataset *.
    3438             :  */
    3439             : 
    3440       24259 : GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)
    3441             : 
    3442             : {
    3443       24259 :     const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
    3444       24259 :     const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
    3445             :     GDALDatasetH hDataset =
    3446       24259 :         GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
    3447       24255 :     return hDataset;
    3448             : }
    3449             : 
    3450             : /************************************************************************/
    3451             : /*                             GetSharedDS()                            */
    3452             : /************************************************************************/
    3453             : 
    3454        6481 : static GDALDataset *GetSharedDS(const char *pszFilename,
    3455             :                                 unsigned int nOpenFlags,
    3456             :                                 const char *const *papszOpenOptions)
    3457             : {
    3458       12962 :     CPLMutexHolderD(&hDLMutex);
    3459             : 
    3460        6481 :     if (phSharedDatasetSet != nullptr)
    3461             :     {
    3462        6225 :         const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
    3463             :         SharedDatasetCtxt sStruct;
    3464             : 
    3465        6225 :         sStruct.nPID = nThisPID;
    3466        6225 :         sStruct.pszDescription = const_cast<char *>(pszFilename);
    3467        6225 :         sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
    3468             :         std::string osConcatenatedOpenOptions =
    3469        6225 :             GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
    3470        6225 :         sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
    3471        6225 :         sStruct.poDS = nullptr;
    3472             :         SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
    3473        6225 :             CPLHashSetLookup(phSharedDatasetSet, &sStruct));
    3474        6225 :         if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
    3475             :         {
    3476         120 :             sStruct.nOpenFlags |= GDAL_OF_UPDATE;
    3477             :             psStruct = static_cast<SharedDatasetCtxt *>(
    3478         120 :                 CPLHashSetLookup(phSharedDatasetSet, &sStruct));
    3479             :         }
    3480        6225 :         if (psStruct)
    3481             :         {
    3482        6106 :             return psStruct->poDS;
    3483             :         }
    3484             :     }
    3485         375 :     return nullptr;
    3486             : }
    3487             : 
    3488             : /************************************************************************/
    3489             : /*                             GDALOpenEx()                             */
    3490             : /************************************************************************/
    3491             : 
    3492             : /**
    3493             :  * \brief Open a raster or vector file as a GDALDataset.
    3494             :  *
    3495             :  * This function will try to open the passed file, or virtual dataset
    3496             :  * name by invoking the Open method of each registered GDALDriver in turn.
    3497             :  * The first successful open will result in a returned dataset.  If all
    3498             :  * drivers fail then NULL is returned and an error is issued.
    3499             :  *
    3500             :  * Several recommendations :
    3501             :  * <ul>
    3502             :  * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
    3503             :  * recommended to open a new dataset on the same underlying file.</li>
    3504             :  * <li>The returned dataset should only be accessed by one thread at a time. If
    3505             :  * you want to use it from different threads, you must add all necessary code
    3506             :  * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such
    3507             :  * as GeoTIFF, maintain internal state variables that are updated each time a
    3508             :  * new block is read, thus preventing concurrent use.) </li>
    3509             :  * </ul>
    3510             :  *
    3511             :  * For drivers supporting the VSI virtual file API, it is possible to open a
    3512             :  * file in a .zip archive (see VSIInstallZipFileHandler()), in a
    3513             :  * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
    3514             :  * server (see VSIInstallCurlFileHandler())
    3515             :  *
    3516             :  * In order to reduce the need for searches through the operating system
    3517             :  * file system machinery, it is possible to give an optional list of files with
    3518             :  * the papszSiblingFiles parameter.
    3519             :  * This is the list of all files at the same level in the file system as the
    3520             :  * target file, including the target file. The filenames must not include any
    3521             :  * path components, are essentially just the output of VSIReadDir() on the
    3522             :  * parent directory. If the target object does not have filesystem semantics
    3523             :  * then the file list should be NULL.
    3524             :  *
    3525             :  * @param pszFilename the name of the file to access.  In the case of
    3526             :  * exotic drivers this may not refer to a physical file, but instead contain
    3527             :  * information for the driver on how to access a dataset.  It should be in UTF-8
    3528             :  * encoding.
    3529             :  *
    3530             :  * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
    3531             :  * through logical or operator.
    3532             :  * <ul>
    3533             :  * <li>Driver kind:
    3534             :  *   <ul>
    3535             :  *     <li>GDAL_OF_RASTER for raster drivers,</li>
    3536             :  *     <li>GDAL_OF_MULTIDIM_RASTER for multidimensional raster drivers,</li>
    3537             :  *     <li>GDAL_OF_VECTOR for vector drivers,</li>
    3538             :  *     <li>GDAL_OF_GNM for Geographic Network Model drivers.</li>
    3539             :  *    </ul>
    3540             :  * GDAL_OF_RASTER and GDAL_OF_MULTIDIM_RASTER are generally mutually
    3541             :  * exclusive. If none of the value is specified, GDAL_OF_RASTER | GDAL_OF_VECTOR
    3542             :  * | GDAL_OF_GNM is implied.
    3543             :  * </li>
    3544             :  * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.
    3545             :  * </li>
    3546             :  * <li>Shared mode: GDAL_OF_SHARED. If set,
    3547             :  * it allows the sharing of GDALDataset handles for a dataset with other callers
    3548             :  * that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will first consult
    3549             :  * its list of currently open and shared GDALDataset's, and if the
    3550             :  * GetDescription() name for one exactly matches the pszFilename passed to
    3551             :  * GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called
    3552             :  * from the same thread.
    3553             :  * </li>
    3554             :  * <li>Thread safe mode: GDAL_OF_THREAD_SAFE (added in 3.10).
    3555             :  * This must be use in combination with GDAL_OF_RASTER, and is mutually
    3556             :  * exclusive with GDAL_OF_UPDATE, GDAL_OF_VECTOR, GDAL_OF_MULTIDIM_RASTER or
    3557             :  * GDAL_OF_GNM.
    3558             :  * </li>
    3559             :  * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set,
    3560             :  * a failed attempt to open the file will lead to an error message to be
    3561             :  * reported.
    3562             :  * </li>
    3563             :  * </ul>
    3564             :  *
    3565             :  * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
    3566             :  * terminated list of strings with the driver short names that must be
    3567             :  * considered.
    3568             :  *
    3569             :  * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
    3570             :  * options passed to candidate drivers. An option exists for all drivers,
    3571             :  * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
    3572             :  * The level index starts at 0. The level number can be suffixed by "only" to
    3573             :  * specify that only this overview level must be visible, and not sub-levels.
    3574             :  * Open options are validated by default, and a warning is emitted in case the
    3575             :  * option is not recognized. In some scenarios, it might be not desirable (e.g.
    3576             :  * when not knowing which driver will open the file), so the special open option
    3577             :  * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
    3578             :  * since GDAL 2.1, an option name can be preceded by the @ character to indicate
    3579             :  * that it may not cause a warning if the driver doesn't declare this option.
    3580             :  * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
    3581             :  * no overviews should be exposed.
    3582             :  *
    3583             :  * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
    3584             :  * filenames that are auxiliary to the main filename. If NULL is passed, a
    3585             :  * probing of the file system will be done.
    3586             :  *
    3587             :  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
    3588             :  * this handle can be cast to a GDALDataset *.
    3589             :  *
    3590             :  * @since GDAL 2.0
    3591             :  */
    3592             : 
    3593       73410 : GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
    3594             :                                     unsigned int nOpenFlags,
    3595             :                                     const char *const *papszAllowedDrivers,
    3596             :                                     const char *const *papszOpenOptions,
    3597             :                                     const char *const *papszSiblingFiles)
    3598             : {
    3599       73410 :     VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
    3600             : 
    3601             :     // Do some sanity checks on incompatible flags with thread-safe mode.
    3602       73410 :     if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
    3603             :     {
    3604             :         const struct
    3605             :         {
    3606             :             int nFlag;
    3607             :             const char *pszFlagName;
    3608         128 :         } asFlags[] = {
    3609             :             {GDAL_OF_UPDATE, "GDAL_OF_UPDATE"},
    3610             :             {GDAL_OF_VECTOR, "GDAL_OF_VECTOR"},
    3611             :             {GDAL_OF_MULTIDIM_RASTER, "GDAL_OF_MULTIDIM_RASTER"},
    3612             :             {GDAL_OF_GNM, "GDAL_OF_GNM"},
    3613             :         };
    3614             : 
    3615         630 :         for (const auto &asFlag : asFlags)
    3616             :         {
    3617         506 :             if ((nOpenFlags & asFlag.nFlag) != 0)
    3618             :             {
    3619           4 :                 CPLError(CE_Failure, CPLE_IllegalArg,
    3620             :                          "GDAL_OF_THREAD_SAFE and %s are mutually "
    3621             :                          "exclusive",
    3622           4 :                          asFlag.pszFlagName);
    3623           4 :                 return nullptr;
    3624             :             }
    3625             :         }
    3626             :     }
    3627             : 
    3628             :     // If no driver kind is specified, assume all are to be probed.
    3629       73406 :     if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)
    3630        6032 :         nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
    3631             : 
    3632             :     /* -------------------------------------------------------------------- */
    3633             :     /*      In case of shared dataset, first scan the existing list to see  */
    3634             :     /*      if it could already contain the requested dataset.              */
    3635             :     /* -------------------------------------------------------------------- */
    3636       73406 :     if (nOpenFlags & GDAL_OF_SHARED)
    3637             :     {
    3638        6481 :         if (nOpenFlags & GDAL_OF_INTERNAL)
    3639             :         {
    3640           0 :             CPLError(CE_Failure, CPLE_IllegalArg,
    3641             :                      "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
    3642           0 :             return nullptr;
    3643             :         }
    3644             : 
    3645             :         auto poSharedDS =
    3646        6481 :             GetSharedDS(pszFilename, nOpenFlags, papszOpenOptions);
    3647        6481 :         if (poSharedDS)
    3648             :         {
    3649        6106 :             poSharedDS->Reference();
    3650        6106 :             return poSharedDS;
    3651             :         }
    3652             :     }
    3653             : 
    3654       67300 :     GDALDriverManager *poDM = GetGDALDriverManager();
    3655             :     // CPLLocaleC  oLocaleForcer;
    3656             : 
    3657       67300 :     CPLErrorReset();
    3658       67300 :     VSIErrorReset();
    3659       67300 :     CPLAssert(nullptr != poDM);
    3660             : 
    3661             :     // Build GDALOpenInfo just now to avoid useless file stat'ing if a
    3662             :     // shared dataset was asked before.
    3663             :     GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
    3664      134531 :                            const_cast<char **>(papszSiblingFiles));
    3665       67298 :     oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
    3666             : 
    3667       67298 :     GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
    3668       67299 :     if (sAntiRecursion.nRecLevel == 100)
    3669             :     {
    3670           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    3671             :                  "GDALOpen() called with too many recursion levels");
    3672           0 :         return nullptr;
    3673             :     }
    3674             : 
    3675      134530 :     std::string osAllowedDrivers;
    3676      160204 :     for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
    3677       92904 :         osAllowedDrivers += pszDriverName;
    3678             :     auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(
    3679      201829 :         std::string(pszFilename), nOpenFlags, osAllowedDrivers);
    3680       67292 :     if (cpl::contains(sAntiRecursion.aosDatasetNamesWithFlags, dsCtxt))
    3681             :     {
    3682           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    3683             :                  "GDALOpen() called on %s recursively", pszFilename);
    3684           0 :         return nullptr;
    3685             :     }
    3686             : 
    3687             :     // Remove leading @ if present.
    3688             :     char **papszOpenOptionsCleaned =
    3689       67284 :         CSLDuplicate(const_cast<char **>(papszOpenOptions));
    3690       72581 :     for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
    3691             :          ++papszIter)
    3692             :     {
    3693        5295 :         char *pszOption = *papszIter;
    3694        5295 :         if (pszOption[0] == '@')
    3695         181 :             memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
    3696             :     }
    3697             : 
    3698       67286 :     oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
    3699       67286 :     oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;
    3700             : 
    3701             : #ifdef OGRAPISPY_ENABLED
    3702       67286 :     const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
    3703             :     const int iSnapshot =
    3704       16914 :         (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0
    3705       84200 :             ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)
    3706       67286 :             : INT_MIN;
    3707             : #endif
    3708             : 
    3709       67286 :     const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);
    3710       67296 :     GDALDriver *poMissingPluginDriver = nullptr;
    3711      134594 :     std::vector<GDALDriver *> apoSecondPassDrivers;
    3712             : 
    3713             :     // Lookup of matching driver for dataset can involve up to 2 passes:
    3714             :     // - in the first pass, all drivers that are compabile of the request mode
    3715             :     //   (raster/vector/etc.) are probed using their Identify() method if it
    3716             :     //   exists. If the Identify() method returns FALSE, the driver is skipped.
    3717             :     //   If the Identify() methods returns GDAL_IDENTIFY_UNKNOWN and that the
    3718             :     //   driver is a deferred-loading plugin, it is added to the
    3719             :     //   apoSecondPassDrivers list for potential later probing, and execution
    3720             :     //   continues to the next driver in the list.
    3721             :     //   Otherwise if Identify() returns non-FALSE, the Open() method is used.
    3722             :     //   If Open() returns a non-NULL dataset, the loop stops and it is
    3723             :     //   returned. Otherwise looping over remaining drivers continues.
    3724             :     // - the second pass is optional, only if at least one driver was added
    3725             :     //   into apoSecondPassDrivers during the first pass. It is similar
    3726             :     //   to the first pass except it runs only on apoSecondPassDrivers drivers.
    3727             :     //   And the Open() method of such drivers is used, causing them to be
    3728             :     //   loaded for real.
    3729       67286 :     int iPass = 1;
    3730       67300 : retry:
    3731     7896360 :     for (int iDriver = 0;
    3732     7896400 :          iDriver < (iPass == 1 ? nDriverCount
    3733          39 :                                : static_cast<int>(apoSecondPassDrivers.size()));
    3734             :          ++iDriver)
    3735             :     {
    3736             :         GDALDriver *poDriver =
    3737     7868400 :             iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
    3738           0 :                        : apoSecondPassDrivers[iDriver];
    3739    11405100 :         if (papszAllowedDrivers != nullptr &&
    3740     3522630 :             CSLFindString(papszAllowedDrivers,
    3741             :                           GDALGetDriverShortName(poDriver)) == -1)
    3742             :         {
    3743     7344360 :             continue;
    3744             :         }
    3745             : 
    3746     4447530 :         if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)
    3747       38752 :             continue;
    3748             : 
    3749    11841500 :         if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&
    3750     6502870 :             (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
    3751     2092340 :             poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
    3752      523988 :             continue;
    3753    11281500 :         if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&
    3754     5642690 :             (nOpenFlags & GDAL_OF_RASTER) == 0 &&
    3755     1756150 :             poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
    3756     1347080 :             continue;
    3757     5357600 :         if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
    3758     2682550 :             (nOpenFlags & GDAL_OF_RASTER) == 0 &&
    3759      143081 :             poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)
    3760      135200 :             continue;
    3761             : 
    3762             :         // Remove general OVERVIEW_LEVEL open options from list before passing
    3763             :         // it to the driver, if it isn't a driver specific option already.
    3764     2404270 :         char **papszTmpOpenOptions = nullptr;
    3765     2404270 :         char **papszTmpOpenOptionsToValidate = nullptr;
    3766     2404270 :         char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
    3767     7201400 :         if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
    3768     2404450 :                 nullptr &&
    3769         183 :             (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) == nullptr ||
    3770     2398630 :              CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST))
    3771         111 :                      .ifind("OVERVIEW_LEVEL") == std::string::npos))
    3772             :         {
    3773         183 :             papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
    3774             :             papszTmpOpenOptions =
    3775         183 :                 CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
    3776         183 :             oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
    3777             : 
    3778         183 :             papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
    3779         183 :             papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate,
    3780             :                                                      "OVERVIEW_LEVEL", nullptr);
    3781         183 :             papszTmpOpenOptionsToValidate = papszOptionsToValidate;
    3782             :         }
    3783             : 
    3784             :         const int nIdentifyRes =
    3785     2398610 :             poDriver->pfnIdentifyEx
    3786     4799430 :                 ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)
    3787     2398600 :             : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)
    3788     2400820 :                                     : GDAL_IDENTIFY_UNKNOWN;
    3789     2400820 :         if (nIdentifyRes == FALSE)
    3790             :         {
    3791     1865430 :             CSLDestroy(papszTmpOpenOptions);
    3792     1864180 :             CSLDestroy(papszTmpOpenOptionsToValidate);
    3793     1864300 :             oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
    3794     1864300 :             continue;
    3795             :         }
    3796      535784 :         else if (iPass == 1 && nIdentifyRes < 0 &&
    3797     1071300 :                  poDriver->pfnOpen == nullptr &&
    3798         120 :                  poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN"))
    3799             :         {
    3800             :             // Not loaded plugin
    3801         119 :             apoSecondPassDrivers.push_back(poDriver);
    3802         119 :             CSLDestroy(papszTmpOpenOptions);
    3803         119 :             CSLDestroy(papszTmpOpenOptionsToValidate);
    3804         119 :             oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
    3805         119 :             continue;
    3806             :         }
    3807             : 
    3808      535273 :         const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;
    3809      535273 :         if (bIdentifyRes)
    3810             :         {
    3811       47420 :             GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
    3812             :         }
    3813             : 
    3814             : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
    3815             :         const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
    3816             :         CPLErrorReset();
    3817             : #endif
    3818             : 
    3819      535264 :         sAntiRecursion.nRecLevel++;
    3820      535264 :         sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
    3821             : 
    3822      535358 :         GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
    3823             : 
    3824      534523 :         sAntiRecursion.nRecLevel--;
    3825      534523 :         sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
    3826             : 
    3827      535089 :         if (poDriver->pfnOpen != nullptr)
    3828             :         {
    3829             :             // If we couldn't determine for sure with Identify() (it returned
    3830             :             // -1), but Open() managed to open the file, post validate options.
    3831      534936 :             if (poDS != nullptr &&
    3832       48016 :                 (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&
    3833       47216 :                 !bIdentifyRes)
    3834             :             {
    3835         818 :                 GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
    3836             :             }
    3837             :         }
    3838         153 :         else if (poDriver->pfnOpenWithDriverArg != nullptr)
    3839             :         {
    3840             :             // do nothing
    3841             :         }
    3842           0 :         else if (bIdentifyRes &&
    3843           0 :                  poDriver->GetMetadataItem("MISSING_PLUGIN_FILENAME"))
    3844             :         {
    3845           0 :             if (!poMissingPluginDriver)
    3846             :             {
    3847           0 :                 poMissingPluginDriver = poDriver;
    3848             :             }
    3849             :         }
    3850             :         else
    3851             :         {
    3852             :             // should not happen given the GDAL_DCAP_OPEN check
    3853           0 :             CSLDestroy(papszTmpOpenOptions);
    3854           0 :             CSLDestroy(papszTmpOpenOptionsToValidate);
    3855           0 :             oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
    3856           0 :             continue;
    3857             :         }
    3858             : 
    3859      535089 :         CSLDestroy(papszTmpOpenOptions);
    3860      534645 :         CSLDestroy(papszTmpOpenOptionsToValidate);
    3861      534222 :         oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
    3862             : 
    3863      534222 :         if (poDS != nullptr)
    3864             :         {
    3865       48020 :             if (poDS->papszOpenOptions == nullptr)
    3866             :             {
    3867       47764 :                 poDS->papszOpenOptions = papszOpenOptionsCleaned;
    3868       47764 :                 papszOpenOptionsCleaned = nullptr;
    3869             :             }
    3870             : 
    3871             :             // Deal with generic OVERVIEW_LEVEL open option, unless it is
    3872             :             // driver specific.
    3873      144057 :             if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
    3874       48059 :                     nullptr &&
    3875          39 :                 (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) ==
    3876          78 :                      nullptr ||
    3877       48058 :                  CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST))
    3878          39 :                          .ifind("OVERVIEW_LEVEL") == std::string::npos))
    3879             :             {
    3880             :                 CPLString osVal(
    3881          78 :                     CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
    3882          39 :                 const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
    3883             :                 const bool bThisLevelOnly =
    3884          39 :                     nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
    3885             :                 GDALDataset *poOvrDS =
    3886          39 :                     GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly);
    3887          39 :                 if (poOvrDS && (nOpenFlags & GDAL_OF_SHARED) != 0)
    3888             :                 {
    3889           4 :                     if (strcmp(pszFilename, poDS->GetDescription()) != 0)
    3890             :                     {
    3891           0 :                         CPLError(
    3892             :                             CE_Warning, CPLE_NotSupported,
    3893             :                             "A dataset opened by GDALOpenShared should have "
    3894             :                             "the same filename (%s) "
    3895             :                             "and description (%s)",
    3896           0 :                             pszFilename, poDS->GetDescription());
    3897             :                     }
    3898             :                     else
    3899             :                     {
    3900           4 :                         CSLDestroy(poDS->papszOpenOptions);
    3901           4 :                         poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
    3902           4 :                         poDS->papszOpenOptions = CSLSetNameValue(
    3903             :                             poDS->papszOpenOptions, "OVERVIEW_LEVEL", nullptr);
    3904             :                     }
    3905             :                 }
    3906          39 :                 poDS->ReleaseRef();
    3907          39 :                 poDS = poOvrDS;
    3908          39 :                 if (poDS == nullptr)
    3909             :                 {
    3910           1 :                     if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
    3911             :                     {
    3912           1 :                         CPLError(CE_Failure, CPLE_OpenFailed,
    3913             :                                  "Cannot open overview level %d of %s",
    3914             :                                  nOvrLevel, pszFilename);
    3915             :                     }
    3916             :                 }
    3917             :                 else
    3918             :                 {
    3919             :                     // For thread-safe opening, currently poDS is what will be
    3920             :                     // the "master" dataset owned by the thread-safe dataset
    3921             :                     // returned to the user, hence we do not register it as a
    3922             :                     // visible one in the open dataset list, or mark it as shared.
    3923          38 :                     if (!(nOpenFlags & GDAL_OF_INTERNAL) &&
    3924          36 :                         !(nOpenFlags & GDAL_OF_THREAD_SAFE))
    3925             :                     {
    3926          35 :                         poDS->AddToDatasetOpenList();
    3927             :                     }
    3928          38 :                     if (nOpenFlags & GDAL_OF_SHARED)
    3929             :                     {
    3930           4 :                         CSLDestroy(poDS->papszOpenOptions);
    3931           4 :                         poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
    3932           4 :                         poDS->nOpenFlags = nOpenFlags;
    3933           4 :                         if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
    3934           4 :                             poDS->MarkAsShared();
    3935             :                     }
    3936             :                 }
    3937             :             }
    3938       47979 :             else if (nOpenFlags & GDAL_OF_SHARED)
    3939             :             {
    3940         366 :                 if (strcmp(pszFilename, poDS->GetDescription()) != 0)
    3941             :                 {
    3942           2 :                     CPLError(CE_Warning, CPLE_NotSupported,
    3943             :                              "A dataset opened by GDALOpenShared should have "
    3944             :                              "the same filename (%s) "
    3945             :                              "and description (%s)",
    3946           2 :                              pszFilename, poDS->GetDescription());
    3947             :                 }
    3948         364 :                 else if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
    3949             :                 {
    3950             :                     // For thread-safe opening, currently poDS is what will be
    3951             :                     // the "master" dataset owned by the thread-safe dataset
    3952             :                     // returned to the user, hence we do not or mark it as shared.
    3953         364 :                     poDS->MarkAsShared();
    3954             :                 }
    3955             :             }
    3956             : 
    3957       48018 :             VSIErrorReset();
    3958             : 
    3959       48020 :             CSLDestroy(papszOpenOptionsCleaned);
    3960             : 
    3961             : #ifdef OGRAPISPY_ENABLED
    3962       48018 :             if (iSnapshot != INT_MIN)
    3963             :             {
    3964       10566 :                 GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
    3965       10566 :                 OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
    3966       10566 :                 poDS = GDALDataset::FromHandle(hDS);
    3967             :             }
    3968             : #endif
    3969             : 
    3970       48018 :             if (poDS)
    3971             :             {
    3972       48017 :                 poDS->m_bCanBeReopened = true;
    3973             : 
    3974       48017 :                 if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
    3975             :                 {
    3976             :                     poDS =
    3977         248 :                         GDALGetThreadSafeDataset(
    3978         248 :                             std::unique_ptr<GDALDataset>(poDS), GDAL_OF_RASTER)
    3979         124 :                             .release();
    3980         124 :                     if (poDS)
    3981             :                     {
    3982         124 :                         poDS->m_bCanBeReopened = true;
    3983         124 :                         poDS->poDriver = poDriver;
    3984         124 :                         poDS->nOpenFlags = nOpenFlags;
    3985         124 :                         if (!(nOpenFlags & GDAL_OF_INTERNAL))
    3986         124 :                             poDS->AddToDatasetOpenList();
    3987         124 :                         if (nOpenFlags & GDAL_OF_SHARED)
    3988           0 :                             poDS->MarkAsShared();
    3989             :                     }
    3990             :                 }
    3991             :             }
    3992             : 
    3993       48868 :             return poDS;
    3994             :         }
    3995             : 
    3996             : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
    3997             :         if (bFpAvailableBefore && oOpenInfo.fpL == nullptr)
    3998             :         {
    3999             :             // In case the file descriptor was "consumed" by a driver
    4000             :             // that ultimately failed, re-open it for next drivers.
    4001             :             oOpenInfo.fpL = VSIFOpenL(
    4002             :                 pszFilename, (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
    4003             :         }
    4004             : #else
    4005      486202 :         if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
    4006             :         {
    4007        1426 :             CSLDestroy(papszOpenOptionsCleaned);
    4008             : 
    4009             : #ifdef OGRAPISPY_ENABLED
    4010         850 :             if (iSnapshot != INT_MIN)
    4011             :             {
    4012         140 :                 GDALDatasetH hDS = nullptr;
    4013         140 :                 OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
    4014             :             }
    4015             : #endif
    4016         850 :             return nullptr;
    4017             :         }
    4018             : #endif
    4019             :     }
    4020             : 
    4021             :     // cppcheck-suppress knownConditionTrueFalse
    4022       27987 :     if (iPass == 1 && !apoSecondPassDrivers.empty())
    4023             :     {
    4024          16 :         CPLDebugOnly("GDAL", "GDALOpen(): Second pass");
    4025          14 :         iPass = 2;
    4026          14 :         goto retry;
    4027             :     }
    4028             : 
    4029       27949 :     CSLDestroy(papszOpenOptionsCleaned);
    4030             : 
    4031             : #ifdef OGRAPISPY_ENABLED
    4032       18358 :     if (iSnapshot != INT_MIN)
    4033             :     {
    4034         936 :         GDALDatasetH hDS = nullptr;
    4035         936 :         OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
    4036             :     }
    4037             : #endif
    4038             : 
    4039       18358 :     if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
    4040             :     {
    4041             :         // Check to see if there was a filesystem error, and report it if so.
    4042             :         // If not, return a more generic error.
    4043        5666 :         if (!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
    4044             :         {
    4045         152 :             if (nDriverCount == 0)
    4046             :             {
    4047           1 :                 CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");
    4048             :             }
    4049         151 :             else if (oOpenInfo.bStatOK)
    4050             :             {
    4051         148 :                 if (!poMissingPluginDriver)
    4052             :                 {
    4053         148 :                     CPLError(CE_Failure, CPLE_OpenFailed,
    4054             :                              "`%s' not recognized as being in a supported file "
    4055             :                              "format.",
    4056             :                              pszFilename);
    4057             :                 }
    4058             :                 else
    4059             :                 {
    4060           0 :                     std::string osMsg("`");
    4061           0 :                     osMsg += pszFilename;
    4062             :                     osMsg +=
    4063             :                         "' not recognized as being in a supported file format. "
    4064           0 :                         "It could have been recognized by driver ";
    4065           0 :                     osMsg += poMissingPluginDriver->GetDescription();
    4066           0 :                     osMsg += ", but plugin ";
    4067             :                     osMsg += poMissingPluginDriver->GetMetadataItem(
    4068           0 :                         "MISSING_PLUGIN_FILENAME");
    4069             :                     osMsg += " is not available in your "
    4070           0 :                              "installation.";
    4071           0 :                     if (const char *pszInstallationMsg =
    4072           0 :                             poMissingPluginDriver->GetMetadataItem(
    4073           0 :                                 GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE))
    4074             :                     {
    4075           0 :                         osMsg += " ";
    4076           0 :                         osMsg += pszInstallationMsg;
    4077             :                     }
    4078             : 
    4079             :                     VSIStatBuf sStat;
    4080           0 :                     if (const char *pszGDALDriverPath =
    4081           0 :                             CPLGetConfigOption("GDAL_DRIVER_PATH", nullptr))
    4082             :                     {
    4083           0 :                         if (VSIStat(pszGDALDriverPath, &sStat) != 0)
    4084             :                         {
    4085           0 :                             if (osMsg.back() != '.')
    4086           0 :                                 osMsg += ".";
    4087           0 :                             osMsg += " Directory '";
    4088           0 :                             osMsg += pszGDALDriverPath;
    4089             :                             osMsg +=
    4090           0 :                                 "' pointed by GDAL_DRIVER_PATH does not exist.";
    4091             :                         }
    4092             :                     }
    4093             :                     else
    4094             :                     {
    4095           0 :                         if (osMsg.back() != '.')
    4096           0 :                             osMsg += ".";
    4097             : #ifdef INSTALL_PLUGIN_FULL_DIR
    4098             :                         if (VSIStat(INSTALL_PLUGIN_FULL_DIR, &sStat) != 0)
    4099             :                         {
    4100             :                             osMsg += " Directory '";
    4101             :                             osMsg += INSTALL_PLUGIN_FULL_DIR;
    4102             :                             osMsg += "' hardcoded in the GDAL library does not "
    4103             :                                      "exist and the GDAL_DRIVER_PATH "
    4104             :                                      "configuration option is not set.";
    4105             :                         }
    4106             :                         else
    4107             : #endif
    4108             :                         {
    4109             :                             osMsg += " The GDAL_DRIVER_PATH configuration "
    4110           0 :                                      "option is not set.";
    4111             :                         }
    4112             :                     }
    4113             : 
    4114           0 :                     CPLError(CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str());
    4115             :                 }
    4116             :             }
    4117             :             else
    4118             :             {
    4119             :                 // If Stat failed and no VSI error was set, assume it is because
    4120             :                 // the file did not exist on the filesystem.
    4121           3 :                 CPLError(CE_Failure, CPLE_OpenFailed,
    4122             :                          "`%s' does not exist in the file system, "
    4123             :                          "and is not recognized as a supported dataset name.",
    4124             :                          pszFilename);
    4125             :             }
    4126             :         }
    4127             :     }
    4128             : 
    4129       18430 :     return nullptr;
    4130             : }
    4131             : 
    4132             : /************************************************************************/
    4133             : /*                           GDALOpenShared()                           */
    4134             : /************************************************************************/
    4135             : 
    4136             : /**
    4137             :  * \brief Open a raster file as a GDALDataset.
    4138             :  *
    4139             :  * This function works the same as GDALOpen(), but allows the sharing of
    4140             :  * GDALDataset handles for a dataset with other callers to GDALOpenShared().
    4141             :  *
    4142             :  * In particular, GDALOpenShared() will first consult its list of currently
    4143             :  * open and shared GDALDataset's, and if the GetDescription() name for one
    4144             :  * exactly matches the pszFilename passed to GDALOpenShared() it will be
    4145             :  * referenced and returned.
    4146             :  *
    4147             :  * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
    4148             :  * pszFilename from two different threads, a different GDALDataset object will
    4149             :  * be returned as it is not safe to use the same dataset from different threads,
    4150             :  * unless the user does explicitly use mutexes in its code.
    4151             :  *
    4152             :  * For drivers supporting the VSI virtual file API, it is possible to open a
    4153             :  * file in a .zip archive (see VSIInstallZipFileHandler()), in a
    4154             :  * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
    4155             :  * server (see VSIInstallCurlFileHandler())
    4156             :  *
    4157             :  * \sa GDALOpen()
    4158             :  * \sa GDALOpenEx()
    4159             :  *
    4160             :  * @param pszFilename the name of the file to access.  In the case of
    4161             :  * exotic drivers this may not refer to a physical file, but instead contain
    4162             :  * information for the driver on how to access a dataset.  It should be in
    4163             :  * UTF-8 encoding.
    4164             :  *
    4165             :  * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
    4166             :  * drivers support only read only access.
    4167             :  *
    4168             :  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
    4169             :  * this handle can be cast to a GDALDataset *.
    4170             :  */
    4171             : 
    4172        5221 : GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,
    4173             :                                         GDALAccess eAccess)
    4174             : {
    4175        5221 :     VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
    4176        5221 :     return GDALOpenEx(pszFilename,
    4177             :                       GDAL_OF_RASTER |
    4178             :                           (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
    4179             :                           GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
    4180        5221 :                       nullptr, nullptr, nullptr);
    4181             : }
    4182             : 
    4183             : /************************************************************************/
    4184             : /*                             GDALClose()                              */
    4185             : /************************************************************************/
    4186             : 
    4187             : /**
    4188             :  * \brief Close GDAL dataset.
    4189             :  *
    4190             :  * For non-shared datasets (opened with GDALOpen()) the dataset is closed
    4191             :  * using the C++ "delete" operator, recovering all dataset related resources.
    4192             :  * For shared datasets (opened with GDALOpenShared()) the dataset is
    4193             :  * dereferenced, and closed only if the referenced count has dropped below 1.
    4194             :  *
    4195             :  * @param hDS The dataset to close.  May be cast from a "GDALDataset *".
    4196             :  * @return CE_None in case of success (return value since GDAL 3.7). On a
    4197             :  * shared dataset whose reference count is not dropped below 1, CE_None will
    4198             :  * be returned.
    4199             :  */
    4200             : 
    4201       66026 : CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)
    4202             : 
    4203             : {
    4204       66026 :     if (!hDS)
    4205         414 :         return CE_None;
    4206             : 
    4207             : #ifdef OGRAPISPY_ENABLED
    4208       65612 :     if (bOGRAPISpyEnabled)
    4209          11 :         OGRAPISpyPreClose(hDS);
    4210             : #endif
    4211             : 
    4212       65612 :     GDALDataset *poDS = GDALDataset::FromHandle(hDS);
    4213             : 
    4214       65612 :     if (poDS->GetShared())
    4215             :     {
    4216             :         /* --------------------------------------------------------------------
    4217             :          */
    4218             :         /*      If this file is in the shared dataset list then dereference */
    4219             :         /*      it, and only delete/remote it if the reference count has */
    4220             :         /*      dropped to zero. */
    4221             :         /* --------------------------------------------------------------------
    4222             :          */
    4223         303 :         if (poDS->Dereference() > 0)
    4224          28 :             return CE_None;
    4225             : 
    4226         275 :         CPLErr eErr = poDS->Close();
    4227         275 :         delete poDS;
    4228             : 
    4229             : #ifdef OGRAPISPY_ENABLED
    4230         275 :         if (bOGRAPISpyEnabled)
    4231           0 :             OGRAPISpyPostClose();
    4232             : #endif
    4233             : 
    4234         275 :         return eErr;
    4235             :     }
    4236             : 
    4237             :     /* -------------------------------------------------------------------- */
    4238             :     /*      This is not shared dataset, so directly delete it.              */
    4239             :     /* -------------------------------------------------------------------- */
    4240       65309 :     CPLErr eErr = poDS->Close();
    4241       65308 :     delete poDS;
    4242             : 
    4243             : #ifdef OGRAPISPY_ENABLED
    4244       65305 :     if (bOGRAPISpyEnabled)
    4245          11 :         OGRAPISpyPostClose();
    4246             : #endif
    4247       65295 :     return eErr;
    4248             : }
    4249             : 
    4250             : /************************************************************************/
    4251             : /*                        GDALDumpOpenDataset()                         */
    4252             : /************************************************************************/
    4253             : 
    4254           0 : static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
    4255             : {
    4256           0 :     SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
    4257           0 :     FILE *fp = static_cast<FILE *>(user_data);
    4258           0 :     GDALDataset *poDS = psStruct->poDS;
    4259             : 
    4260           0 :     const char *pszDriverName = poDS->GetDriver() == nullptr
    4261           0 :                                     ? "DriverIsNULL"
    4262           0 :                                     : poDS->GetDriver()->GetDescription();
    4263             : 
    4264           0 :     poDS->Reference();
    4265           0 :     CPL_IGNORE_RET_VAL(
    4266           0 :         VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
    4267           0 :                    poDS->GetShared() ? 'S' : 'N', pszDriverName,
    4268           0 :                    static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
    4269             :                    poDS->GetRasterYSize(), poDS->GetRasterCount(),
    4270           0 :                    poDS->GetDescription()));
    4271             : 
    4272           0 :     return TRUE;
    4273             : }
    4274             : 
    4275           0 : static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
    4276             : {
    4277             : 
    4278             :     // Don't list shared datasets. They have already been listed by
    4279             :     // GDALDumpOpenSharedDatasetsForeach.
    4280           0 :     if (poDS->GetShared())
    4281           0 :         return TRUE;
    4282             : 
    4283           0 :     const char *pszDriverName = poDS->GetDriver() == nullptr
    4284           0 :                                     ? "DriverIsNULL"
    4285           0 :                                     : poDS->GetDriver()->GetDescription();
    4286             : 
    4287           0 :     poDS->Reference();
    4288           0 :     CPL_IGNORE_RET_VAL(
    4289           0 :         VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
    4290           0 :                    poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
    4291             :                    poDS->GetRasterXSize(), poDS->GetRasterYSize(),
    4292           0 :                    poDS->GetRasterCount(), poDS->GetDescription()));
    4293             : 
    4294           0 :     return TRUE;
    4295             : }
    4296             : 
    4297             : /**
    4298             :  * \brief List open datasets.
    4299             :  *
    4300             :  * Dumps a list of all open datasets (shared or not) to the indicated
    4301             :  * text file (may be stdout or stderr).   This function is primarily intended
    4302             :  * to assist in debugging "dataset leaks" and reference counting issues.
    4303             :  * The information reported includes the dataset name, referenced count,
    4304             :  * shared status, driver name, size, and band count.
    4305             :  */
    4306             : 
    4307         277 : int CPL_STDCALL GDALDumpOpenDatasets(FILE *fp)
    4308             : 
    4309             : {
    4310         277 :     VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
    4311             : 
    4312         554 :     CPLMutexHolderD(&hDLMutex);
    4313             : 
    4314         277 :     if (poAllDatasetMap == nullptr)
    4315         277 :         return 0;
    4316             : 
    4317           0 :     CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
    4318             : 
    4319           0 :     for (const auto &oIter : *poAllDatasetMap)
    4320             :     {
    4321           0 :         GDALDumpOpenDatasetsForeach(oIter.first, fp);
    4322             :     }
    4323             : 
    4324           0 :     if (phSharedDatasetSet != nullptr)
    4325             :     {
    4326           0 :         CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach,
    4327             :                           fp);
    4328             :     }
    4329           0 :     return static_cast<int>(poAllDatasetMap->size());
    4330             : }
    4331             : 
    4332             : /************************************************************************/
    4333             : /*                        BeginAsyncReader()                            */
    4334             : /************************************************************************/
    4335             : 
    4336             : /**
    4337             :  * \brief Sets up an asynchronous data request
    4338             :  *
    4339             :  * This method establish an asynchronous raster read request for the
    4340             :  * indicated window on the dataset into the indicated buffer.  The parameters
    4341             :  * for windowing, buffer size, buffer type and buffer organization are similar
    4342             :  * to those for GDALDataset::RasterIO(); however, this call only launches
    4343             :  * the request and filling the buffer is accomplished via calls to
    4344             :  * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
    4345             :  *
    4346             :  * Once all processing for the created session is complete, or if no further
    4347             :  * refinement of the request is required, the GDALAsyncReader object should
    4348             :  * be destroyed with the GDALDataset::EndAsyncReader() method.
    4349             :  *
    4350             :  * Note that the data buffer (pData) will potentially continue to be
    4351             :  * updated as long as the session lives, but it is not deallocated when
    4352             :  * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It
    4353             :  * should be deallocated by the application at that point.
    4354             :  *
    4355             :  * Additional information on asynchronous IO in GDAL may be found at:
    4356             :  *   https://gdal.org/development/rfc/rfc24_progressive_data_support.html
    4357             :  *
    4358             :  * This method is the same as the C GDALBeginAsyncReader() function.
    4359             :  *
    4360             :  * @param nXOff The pixel offset to the top left corner of the region
    4361             :  * of the band to be accessed.  This would be zero to start from the left side.
    4362             :  *
    4363             :  * @param nYOff The line offset to the top left corner of the region
    4364             :  * of the band to be accessed.  This would be zero to start from the top.
    4365             :  *
    4366             :  * @param nXSize The width of the region of the band to be accessed in pixels.
    4367             :  *
    4368             :  * @param nYSize The height of the region of the band to be accessed in lines.
    4369             :  *
    4370             :  * @param pBuf The buffer into which the data should be read. This buffer must
    4371             :  * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
    4372             :  * It is organized in left to right,top to bottom pixel order.  Spacing is
    4373             :  * controlled by the nPixelSpace, and nLineSpace parameters.
    4374             :  *
    4375             :  * @param nBufXSize the width of the buffer image into which the desired region
    4376             :  * is to be read, or from which it is to be written.
    4377             :  *
    4378             :  * @param nBufYSize the height of the buffer image into which the desired
    4379             :  * region is to be read, or from which it is to be written.
    4380             :  *
    4381             :  * @param eBufType the type of the pixel values in the pData data buffer.  The
    4382             :  * pixel values will automatically be translated to/from the GDALRasterBand
    4383             :  * data type as needed.
    4384             :  *
    4385             :  * @param nBandCount the number of bands being read or written.
    4386             :  *
    4387             :  * @param panBandMap the list of nBandCount band numbers being read/written.
    4388             :  * Note band numbers are 1 based.   This may be NULL to select the first
    4389             :  * nBandCount bands.
    4390             :  *
    4391             :  * @param nPixelSpace The byte offset from the start of one pixel value in
    4392             :  * pData to the start of the next pixel value within a scanline.  If defaulted
    4393             :  * (0) the size of the datatype eBufType is used.
    4394             :  *
    4395             :  * @param nLineSpace The byte offset from the start of one scanline in
    4396             :  * pData to the start of the next.  If defaulted the size of the datatype
    4397             :  * eBufType * nBufXSize is used.
    4398             :  *
    4399             :  * @param nBandSpace the byte offset from the start of one bands data to the
    4400             :  * start of the next.  If defaulted (zero) the value will be
    4401             :  * nLineSpace * nBufYSize implying band sequential organization
    4402             :  * of the data buffer.
    4403             :  *
    4404             :  * @param papszOptions Driver specific control options in a string list or NULL.
    4405             :  * Consult driver documentation for options supported.
    4406             :  *
    4407             :  * @return The GDALAsyncReader object representing the request.
    4408             :  */
    4409             : 
    4410           1 : GDALAsyncReader *GDALDataset::BeginAsyncReader(
    4411             :     int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
    4412             :     int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
    4413             :     int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions)
    4414             : {
    4415             :     // See gdaldefaultasync.cpp
    4416             : 
    4417           1 :     return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
    4418             :                                      nBufXSize, nBufYSize, eBufType, nBandCount,
    4419             :                                      panBandMap, nPixelSpace, nLineSpace,
    4420           1 :                                      nBandSpace, papszOptions);
    4421             : }
    4422             : 
    4423             : /************************************************************************/
    4424             : /*                        GDALBeginAsyncReader()                      */
    4425             : /************************************************************************/
    4426             : 
    4427             : /**
    4428             :  * \brief Sets up an asynchronous data request
    4429             :  *
    4430             :  * This method establish an asynchronous raster read request for the
    4431             :  * indicated window on the dataset into the indicated buffer.  The parameters
    4432             :  * for windowing, buffer size, buffer type and buffer organization are similar
    4433             :  * to those for GDALDataset::RasterIO(); however, this call only launches
    4434             :  * the request and filling the buffer is accomplished via calls to
    4435             :  * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
    4436             :  *
    4437             :  * Once all processing for the created session is complete, or if no further
    4438             :  * refinement of the request is required, the GDALAsyncReader object should
    4439             :  * be destroyed with the GDALDataset::EndAsyncReader() method.
    4440             :  *
    4441             :  * Note that the data buffer (pData) will potentially continue to be
    4442             :  * updated as long as the session lives, but it is not deallocated when
    4443             :  * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It
    4444             :  * should be deallocated by the application at that point.
    4445             :  *
    4446             :  * Additional information on asynchronous IO in GDAL may be found at:
    4447             :  *   https://gdal.org/development/rfc/rfc24_progressive_data_support.html
    4448             :  *
    4449             :  * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
    4450             :  *
    4451             :  * @param hDS handle to the dataset object.
    4452             :  *
    4453             :  * @param nXOff The pixel offset to the top left corner of the region
    4454             :  * of the band to be accessed.  This would be zero to start from the left side.
    4455             :  *
    4456             :  * @param nYOff The line offset to the top left corner of the region
    4457             :  * of the band to be accessed.  This would be zero to start from the top.
    4458             :  *
    4459             :  * @param nXSize The width of the region of the band to be accessed in pixels.
    4460             :  *
    4461             :  * @param nYSize The height of the region of the band to be accessed in lines.
    4462             :  *
    4463             :  * @param pBuf The buffer into which the data should be read. This buffer must
    4464             :  * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
    4465             :  * It is organized in left to right,top to bottom pixel order.  Spacing is
    4466             :  * controlled by the nPixelSpace, and nLineSpace parameters.
    4467             :  *
    4468             :  * @param nBufXSize the width of the buffer image into which the desired region
    4469             :  * is to be read, or from which it is to be written.
    4470             :  *
    4471             :  * @param nBufYSize the height of the buffer image into which the desired
    4472             :  * region is to be read, or from which it is to be written.
    4473             :  *
    4474             :  * @param eBufType the type of the pixel values in the pData data buffer.  The
    4475             :  * pixel values will automatically be translated to/from the GDALRasterBand
    4476             :  * data type as needed.
    4477             :  *
    4478             :  * @param nBandCount the number of bands being read or written.
    4479             :  *
    4480             :  * @param panBandMap the list of nBandCount band numbers being read/written.
    4481             :  * Note band numbers are 1 based.   This may be NULL to select the first
    4482             :  * nBandCount bands.
    4483             :  *
    4484             :  * @param nPixelSpace The byte offset from the start of one pixel value in
    4485             :  * pData to the start of the next pixel value within a scanline.  If defaulted
    4486             :  * (0) the size of the datatype eBufType is used.
    4487             :  *
    4488             :  * @param nLineSpace The byte offset from the start of one scanline in
    4489             :  * pData to the start of the next.  If defaulted the size of the datatype
    4490             :  * eBufType * nBufXSize is used.
    4491             :  *
    4492             :  * @param nBandSpace the byte offset from the start of one bands data to the
    4493             :  * start of the next.  If defaulted (zero) the value will be
    4494             :  * nLineSpace * nBufYSize implying band sequential organization
    4495             :  * of the data buffer.
    4496             :  *
    4497             :  * @param papszOptions Driver specific control options in a string list or NULL.
    4498             :  * Consult driver documentation for options supported.
    4499             :  *
    4500             :  * @return handle representing the request.
    4501             :  */
    4502             : 
    4503           2 : GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(
    4504             :     GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf,
    4505             :     int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount,
    4506             :     int *panBandMap, int nPixelSpace, int nLineSpace, int nBandSpace,
    4507             :     CSLConstList papszOptions)
    4508             : 
    4509             : {
    4510           2 :     VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
    4511             :     return static_cast<GDALAsyncReaderH>(
    4512           2 :         GDALDataset::FromHandle(hDS)->BeginAsyncReader(
    4513             :             nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
    4514             :             nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
    4515           2 :             const_cast<char **>(papszOptions)));
    4516             : }
    4517             : 
    4518             : /************************************************************************/
    4519             : /*                        EndAsyncReader()                            */
    4520             : /************************************************************************/
    4521             : 
    4522             : /**
    4523             :  * End asynchronous request.
    4524             :  *
    4525             :  * This method destroys an asynchronous io request and recovers all
    4526             :  * resources associated with it.
    4527             :  *
    4528             :  * This method is the same as the C function GDALEndAsyncReader().
    4529             :  *
    4530             :  * @param poARIO pointer to a GDALAsyncReader
    4531             :  */
    4532             : 
    4533           1 : void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO)
    4534             : {
    4535           1 :     delete poARIO;
    4536           1 : }
    4537             : 
    4538             : /************************************************************************/
    4539             : /*                        GDALEndAsyncReader()                        */
    4540             : /************************************************************************/
    4541             : 
    4542             : /**
    4543             :  * End asynchronous request.
    4544             :  *
    4545             :  * This method destroys an asynchronous io request and recovers all
    4546             :  * resources associated with it.
    4547             :  *
    4548             :  * This method is the same as the C++ method GDALDataset::EndAsyncReader().
    4549             :  *
    4550             :  * @param hDS handle to the dataset object.
    4551             :  * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
    4552             :  */
    4553             : 
    4554           1 : void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS,
    4555             :                                     GDALAsyncReaderH hAsyncReaderH)
    4556             : {
    4557           1 :     VALIDATE_POINTER0(hDS, "GDALDataset");
    4558           1 :     VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
    4559           1 :     GDALDataset::FromHandle(hDS)->EndAsyncReader(
    4560           1 :         static_cast<GDALAsyncReader *>(hAsyncReaderH));
    4561             : }
    4562             : 
    4563             : /************************************************************************/
    4564             : /*                       CloseDependentDatasets()                       */
    4565             : /************************************************************************/
    4566             : 
    4567             : /**
    4568             :  * Drop references to any other datasets referenced by this dataset.
    4569             :  *
    4570             :  * This method should release any reference to other datasets (e.g. a VRT
    4571             :  * dataset to its sources), but not close the current dataset itself.
    4572             :  *
    4573             :  * If at least, one reference to a dependent dataset has been dropped,
    4574             :  * this method should return TRUE. Otherwise it *should* return FALSE.
    4575             :  * (Failure to return the proper value might result in infinite loop)
    4576             :  *
    4577             :  * This method can be called several times on a given dataset. After
    4578             :  * the first time, it should not do anything and return FALSE.
    4579             :  *
    4580             :  * The driver implementation may choose to destroy its raster bands,
    4581             :  * so be careful not to call any method on the raster bands afterwards.
    4582             :  *
    4583             :  * Basically the only safe action you can do after calling
    4584             :  * CloseDependentDatasets() is to call the destructor.
    4585             :  *
    4586             :  * Note: the only legitimate caller of CloseDependentDatasets() is
    4587             :  * GDALDriverManager::~GDALDriverManager()
    4588             :  *
    4589             :  * @return TRUE if at least one reference to another dataset has been dropped.
    4590             :  */
    4591       18489 : int GDALDataset::CloseDependentDatasets()
    4592             : {
    4593       18489 :     return oOvManager.CloseDependentDatasets();
    4594             : }
    4595             : 
    4596             : /************************************************************************/
    4597             : /*                            ReportError()                             */
    4598             : /************************************************************************/
    4599             : 
    4600             : #ifndef DOXYGEN_XML
    4601             : /**
    4602             :  * \brief Emits an error related to a dataset.
    4603             :  *
    4604             :  * This function is a wrapper for regular CPLError(). The only difference
    4605             :  * with CPLError() is that it prepends the error message with the dataset
    4606             :  * name.
    4607             :  *
    4608             :  * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
    4609             :  * @param err_no the error number (CPLE_*) from cpl_error.h.
    4610             :  * @param fmt a printf() style format string.  Any additional arguments
    4611             :  * will be treated as arguments to fill in this format in a manner
    4612             :  * similar to printf().
    4613             :  *
    4614             :  * @since GDAL 1.9.0
    4615             :  */
    4616             : 
    4617          86 : void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
    4618             :                               const char *fmt, ...) const
    4619             : {
    4620             :     va_list args;
    4621          86 :     va_start(args, fmt);
    4622          86 :     ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
    4623          86 :     va_end(args);
    4624          86 : }
    4625             : 
    4626             : /**
    4627             :  * \brief Emits an error related to a dataset (static method)
    4628             :  *
    4629             :  * This function is a wrapper for regular CPLError(). The only difference
    4630             :  * with CPLError() is that it prepends the error message with the dataset
    4631             :  * name.
    4632             :  *
    4633             :  * @param pszDSName dataset name.
    4634             :  * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
    4635             :  * @param err_no the error number (CPLE_*) from cpl_error.h.
    4636             :  * @param fmt a printf() style format string.  Any additional arguments
    4637             :  * will be treated as arguments to fill in this format in a manner
    4638             :  * similar to printf().
    4639             :  *
    4640             :  * @since GDAL 3.2.0
    4641             :  */
    4642             : 
    4643         103 : void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,
    4644             :                               CPLErrorNum err_no, const char *fmt, ...)
    4645             : {
    4646             :     va_list args;
    4647         103 :     va_start(args, fmt);
    4648         103 :     ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
    4649         103 :     va_end(args);
    4650         103 : }
    4651             : 
    4652         189 : void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,
    4653             :                                CPLErrorNum err_no, const char *fmt,
    4654             :                                va_list args)
    4655             : {
    4656         189 :     pszDSName = CPLGetFilename(pszDSName);
    4657         189 :     if (pszDSName[0] != '\0')
    4658             :     {
    4659         177 :         CPLError(eErrClass, err_no, "%s",
    4660         354 :                  std::string(pszDSName)
    4661         177 :                      .append(": ")
    4662         354 :                      .append(CPLString().vPrintf(fmt, args))
    4663             :                      .c_str());
    4664             :     }
    4665             :     else
    4666             :     {
    4667          12 :         CPLErrorV(eErrClass, err_no, fmt, args);
    4668             :     }
    4669         189 : }
    4670             : #endif
    4671             : 
    4672             : /************************************************************************/
    4673             : /*                            GetMetadata()                             */
    4674             : /************************************************************************/
    4675       64983 : char **GDALDataset::GetMetadata(const char *pszDomain)
    4676             : {
    4677             : #ifndef WITHOUT_DERIVED
    4678       64983 :     if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
    4679             :     {
    4680           8 :         oDerivedMetadataList.Clear();
    4681             : 
    4682             :         // First condition: at least one raster band.
    4683           8 :         if (GetRasterCount() > 0)
    4684             :         {
    4685             :             // Check if there is at least one complex band.
    4686           8 :             bool hasAComplexBand = false;
    4687             : 
    4688          14 :             for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
    4689             :             {
    4690           8 :                 if (GDALDataTypeIsComplex(
    4691           8 :                         GetRasterBand(rasterId)->GetRasterDataType()))
    4692             :                 {
    4693           2 :                     hasAComplexBand = true;
    4694           2 :                     break;
    4695             :                 }
    4696             :             }
    4697             : 
    4698           8 :             unsigned int nbSupportedDerivedDS = 0;
    4699             :             const DerivedDatasetDescription *poDDSDesc =
    4700           8 :                 GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
    4701             : 
    4702           8 :             int nNumDataset = 1;
    4703          64 :             for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
    4704             :                  ++derivedId)
    4705             :             {
    4706          98 :                 if (hasAComplexBand ||
    4707          98 :                     CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
    4708             :                         "complex")
    4709             :                 {
    4710             :                     oDerivedMetadataList.SetNameValue(
    4711             :                         CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
    4712             :                         CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
    4713          20 :                                    poDDSDesc[derivedId].pszDatasetName,
    4714          20 :                                    GetDescription()));
    4715             : 
    4716             :                     CPLString osDesc(
    4717             :                         CPLSPrintf("%s from %s",
    4718          20 :                                    poDDSDesc[derivedId].pszDatasetDescription,
    4719          20 :                                    GetDescription()));
    4720             :                     oDerivedMetadataList.SetNameValue(
    4721             :                         CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
    4722          20 :                         osDesc.c_str());
    4723             : 
    4724          20 :                     nNumDataset++;
    4725             :                 }
    4726             :             }
    4727             :         }
    4728           8 :         return oDerivedMetadataList.List();
    4729             :     }
    4730             : #endif
    4731             : 
    4732       64975 :     return GDALMajorObject::GetMetadata(pszDomain);
    4733             : }
    4734             : 
    4735             : // clang-format off
    4736             : 
    4737             : /**
    4738             :  * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
    4739             :  * \brief Set metadata.
    4740             :  *
    4741             :  * CAUTION: depending on the format, older values of the updated information
    4742             :  * might still be found in the file in a "ghost" state, even if no longer
    4743             :  * accessible through the GDAL API. This is for example the case of the GTiff
    4744             :  * format (this is not a exhaustive list)
    4745             :  *
    4746             :  * The C function GDALSetMetadata() does the same thing as this method.
    4747             :  *
    4748             :  * @param papszMetadata the metadata in name=value string list format to
    4749             :  * apply.
    4750             :  * @param pszDomain the domain of interest.  Use "" or NULL for the default
    4751             :  * domain.
    4752             :  * @return CE_None on success, CE_Failure on failure and CE_Warning if the
    4753             :  * metadata has been accepted, but is likely not maintained persistently
    4754             :  * by the underlying object between sessions.
    4755             :  */
    4756             : 
    4757             : /**
    4758             :  * \fn GDALDataset::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
    4759             :  * \brief Set single metadata item.
    4760             :  *
    4761             :  * CAUTION: depending on the format, older values of the updated information
    4762             :  * might still be found in the file in a "ghost" state, even if no longer
    4763             :  * accessible through the GDAL API. This is for example the case of the GTiff
    4764             :  * format (this is not a exhaustive list)
    4765             :  *
    4766             :  * The C function GDALSetMetadataItem() does the same thing as this method.
    4767             :  *
    4768             :  * @param pszName the key for the metadata item to fetch.
    4769             :  * @param pszValue the value to assign to the key.
    4770             :  * @param pszDomain the domain to set within, use NULL for the default domain.
    4771             :  *
    4772             :  * @return CE_None on success, or an error code on failure.
    4773             :  */
    4774             : 
    4775             : // clang-format on
    4776             : 
    4777             : /************************************************************************/
    4778             : /*                            GetMetadataDomainList()                   */
    4779             : /************************************************************************/
    4780             : 
    4781         786 : char **GDALDataset::GetMetadataDomainList()
    4782             : {
    4783         786 :     char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
    4784             : 
    4785             :     // Ensure that we do not duplicate DERIVED domain.
    4786         923 :     if (GetRasterCount() > 0 &&
    4787         137 :         CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
    4788             :     {
    4789             :         currentDomainList =
    4790         137 :             CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
    4791             :     }
    4792         786 :     return currentDomainList;
    4793             : }
    4794             : 
    4795             : /************************************************************************/
    4796             : /*                            GetDriverName()                           */
    4797             : /************************************************************************/
    4798             : 
    4799             : /** Return driver name.
    4800             :  * @return driver name.
    4801             :  */
    4802        2149 : const char *GDALDataset::GetDriverName()
    4803             : {
    4804        2149 :     if (poDriver)
    4805        2137 :         return poDriver->GetDescription();
    4806          12 :     return "";
    4807             : }
    4808             : 
    4809             : /************************************************************************/
    4810             : /*                     GDALDatasetReleaseResultSet()                    */
    4811             : /************************************************************************/
    4812             : 
    4813             : /**
    4814             :  \brief Release results of ExecuteSQL().
    4815             : 
    4816             :  This function should only be used to deallocate OGRLayers resulting from
    4817             :  an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
    4818             :  results set before destroying the GDALDataset may cause errors.
    4819             : 
    4820             :  This function is the same as the C++ method GDALDataset::ReleaseResultSet()
    4821             : 
    4822             :  @since GDAL 2.0
    4823             : 
    4824             :  @param hDS the dataset handle.
    4825             :  @param hLayer the result of a previous ExecuteSQL() call.
    4826             : 
    4827             : */
    4828        3568 : void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)
    4829             : 
    4830             : {
    4831        3568 :     VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
    4832             : 
    4833             : #ifdef OGRAPISPY_ENABLED
    4834        3568 :     if (bOGRAPISpyEnabled)
    4835           6 :         OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
    4836             : #endif
    4837             : 
    4838        7136 :     GDALDataset::FromHandle(hDS)->ReleaseResultSet(
    4839        3568 :         OGRLayer::FromHandle(hLayer));
    4840             : }
    4841             : 
    4842             : /************************************************************************/
    4843             : /*                       GDALDatasetGetLayerCount()                     */
    4844             : /************************************************************************/
    4845             : 
    4846             : /**
    4847             :  \brief Get the number of layers in this dataset.
    4848             : 
    4849             :  This function is the same as the C++ method GDALDataset::GetLayerCount()
    4850             : 
    4851             :  @since GDAL 2.0
    4852             : 
    4853             :  @param hDS the dataset handle.
    4854             :  @return layer count.
    4855             : */
    4856             : 
    4857        1396 : int GDALDatasetGetLayerCount(GDALDatasetH hDS)
    4858             : 
    4859             : {
    4860        1396 :     VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
    4861             : 
    4862             : #ifdef OGRAPISPY_ENABLED
    4863        1396 :     if (bOGRAPISpyEnabled)
    4864           2 :         OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
    4865             : #endif
    4866             : 
    4867        1396 :     return GDALDataset::FromHandle(hDS)->GetLayerCount();
    4868             : }
    4869             : 
    4870             : /************************************************************************/
    4871             : /*                        GDALDatasetGetLayer()                         */
    4872             : /************************************************************************/
    4873             : 
    4874             : /**
    4875             :  \brief Fetch a layer by index.
    4876             : 
    4877             :  The returned layer remains owned by the
    4878             :  GDALDataset and should not be deleted by the application.
    4879             : 
    4880             :  This function is the same as the C++ method GDALDataset::GetLayer()
    4881             : 
    4882             :  @since GDAL 2.0
    4883             : 
    4884             :  @param hDS the dataset handle.
    4885             :  @param iLayer a layer number between 0 and GetLayerCount()-1.
    4886             : 
    4887             :  @return the layer, or NULL if iLayer is out of range or an error occurs.
    4888             : */
    4889             : 
    4890        8994 : OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)
    4891             : 
    4892             : {
    4893        8994 :     VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
    4894             : 
    4895             :     OGRLayerH hLayer =
    4896        8994 :         OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
    4897             : 
    4898             : #ifdef OGRAPISPY_ENABLED
    4899        8994 :     if (bOGRAPISpyEnabled)
    4900           3 :         OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
    4901             : #endif
    4902             : 
    4903        8994 :     return hLayer;
    4904             : }
    4905             : 
    4906             : /************************************************************************/
    4907             : /*                     GDALDatasetGetLayerByName()                      */
    4908             : /************************************************************************/
    4909             : 
    4910             : /**
    4911             :  \brief Fetch a layer by name.
    4912             : 
    4913             :  The returned layer remains owned by the
    4914             :  GDALDataset and should not be deleted by the application.
    4915             : 
    4916             :  This function is the same as the C++ method GDALDataset::GetLayerByName()
    4917             : 
    4918             :  @since GDAL 2.0
    4919             : 
    4920             :  @param hDS the dataset handle.
    4921             :  @param pszName the layer name of the layer to fetch.
    4922             : 
    4923             :  @return the layer, or NULL if Layer is not found or an error occurs.
    4924             : */
    4925             : 
    4926        3498 : OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)
    4927             : 
    4928             : {
    4929        3498 :     VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
    4930             : 
    4931        3498 :     OGRLayerH hLayer = OGRLayer::ToHandle(
    4932        3498 :         GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
    4933             : 
    4934             : #ifdef OGRAPISPY_ENABLED
    4935        3498 :     if (bOGRAPISpyEnabled)
    4936           4 :         OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
    4937             : #endif
    4938             : 
    4939        3498 :     return hLayer;
    4940             : }
    4941             : 
    4942             : /************************************************************************/
    4943             : /*                        GDALDatasetIsLayerPrivate()                   */
    4944             : /************************************************************************/
    4945             : 
    4946             : /**
    4947             :  \brief Returns true if the layer at the specified index is deemed a private or
    4948             :  system table, or an internal detail only.
    4949             : 
    4950             :  This function is the same as the C++ method GDALDataset::IsLayerPrivate()
    4951             : 
    4952             :  @since GDAL 3.4
    4953             : 
    4954             :  @param hDS the dataset handle.
    4955             :  @param iLayer a layer number between 0 and GetLayerCount()-1.
    4956             : 
    4957             :  @return true if the layer is a private or system table.
    4958             : */
    4959             : 
    4960          91 : int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)
    4961             : 
    4962             : {
    4963          91 :     VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);
    4964             : 
    4965          91 :     const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);
    4966             : 
    4967          91 :     return res ? 1 : 0;
    4968             : }
    4969             : 
    4970             : /************************************************************************/
    4971             : /*                        GDALDatasetDeleteLayer()                      */
    4972             : /************************************************************************/
    4973             : 
    4974             : /**
    4975             :  \brief Delete the indicated layer from the datasource.
    4976             : 
    4977             :  If this function is supported
    4978             :  the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
    4979             : 
    4980             :  This method is the same as the C++ method GDALDataset::DeleteLayer().
    4981             : 
    4982             :  @since GDAL 2.0
    4983             : 
    4984             :  @param hDS the dataset handle.
    4985             :  @param iLayer the index of the layer to delete.
    4986             : 
    4987             :  @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
    4988             :  layers is not supported for this datasource.
    4989             : 
    4990             : */
    4991          42 : OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)
    4992             : 
    4993             : {
    4994          42 :     VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
    4995             : 
    4996             : #ifdef OGRAPISPY_ENABLED
    4997          42 :     if (bOGRAPISpyEnabled)
    4998           2 :         OGRAPISpy_DS_DeleteLayer(hDS, iLayer);
    4999             : #endif
    5000             : 
    5001          42 :     return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
    5002             : }
    5003             : 
    5004             : /************************************************************************/
    5005             : /*                            CreateLayer()                             */
    5006             : /************************************************************************/
    5007             : 
    5008             : /**
    5009             : \brief This method attempts to create a new layer on the dataset with the
    5010             : indicated name, coordinate system, geometry type.
    5011             : 
    5012             : The papszOptions argument
    5013             : can be used to control driver specific creation options.  These options are
    5014             : normally documented in the format specific documentation.
    5015             : That function will try to validate the creation option list passed to the
    5016             : driver with the GDALValidateCreationOptions() method. This check can be
    5017             : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
    5018             : to NO.
    5019             : 
    5020             : Drivers should extend the ICreateLayer() method and not
    5021             : CreateLayer(). CreateLayer() adds validation of layer creation options, before
    5022             : delegating the actual work to ICreateLayer().
    5023             : 
    5024             : This method is the same as the C function GDALDatasetCreateLayer() and the
    5025             : deprecated OGR_DS_CreateLayer().
    5026             : 
    5027             : Example:
    5028             : 
    5029             : \code{.cpp}
    5030             : #include "gdal.h"
    5031             : #include "cpl_string.h"
    5032             : 
    5033             : ...
    5034             : 
    5035             :         OGRLayer *poLayer;
    5036             :         char     **papszOptions;
    5037             : 
    5038             :         if( !poDS->TestCapability( ODsCCreateLayer ) )
    5039             :         {
    5040             :         ...
    5041             :         }
    5042             : 
    5043             :         papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
    5044             :         poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
    5045             :                                      papszOptions );
    5046             :         CSLDestroy( papszOptions );
    5047             : 
    5048             :         if( poLayer == NULL )
    5049             :         {
    5050             :             ...
    5051             :         }
    5052             : \endcode
    5053             : 
    5054             : @param pszName the name for the new layer.  This should ideally not
    5055             : match any existing layer on the datasource.
    5056             : @param poSpatialRef the coordinate system to use for the new layer, or NULL if
    5057             : no coordinate system is available.
    5058             : @param eGType the geometry type for the layer.  Use wkbUnknown if there
    5059             : are no constraints on the types geometry to be written.
    5060             : @param papszOptions a StringList of name=value options.  Options are driver
    5061             : specific.
    5062             : 
    5063             : @return NULL is returned on failure, or a new OGRLayer handle on success.
    5064             : 
    5065             : */
    5066             : 
    5067        7365 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
    5068             :                                    const OGRSpatialReference *poSpatialRef,
    5069             :                                    OGRwkbGeometryType eGType,
    5070             :                                    CSLConstList papszOptions)
    5071             : 
    5072             : {
    5073        7365 :     if (eGType == wkbNone)
    5074             :     {
    5075         446 :         return CreateLayer(pszName, nullptr, papszOptions);
    5076             :     }
    5077             :     else
    5078             :     {
    5079       13838 :         OGRGeomFieldDefn oGeomFieldDefn("", eGType);
    5080        6919 :         oGeomFieldDefn.SetSpatialRef(poSpatialRef);
    5081        6919 :         return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);
    5082             :     }
    5083             : }
    5084             : 
    5085             : /**
    5086             : \brief This method attempts to create a new layer on the dataset with the
    5087             : indicated name and geometry field definition.
    5088             : 
    5089             : When poGeomFieldDefn is not null, most drivers should honor
    5090             : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
    5091             : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
    5092             : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
    5093             : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
    5094             : very few currently.
    5095             : 
    5096             : Note that even if a geometry coordinate precision is set and a driver honors the
    5097             : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
    5098             : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
    5099             : with the coordinate precision. That is they are assumed to be valid once their
    5100             : coordinates are rounded to it. If it might not be the case, the user may set
    5101             : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
    5102             : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
    5103             : the passed geometries.
    5104             : 
    5105             : The papszOptions argument
    5106             : can be used to control driver specific creation options. These options are
    5107             : normally documented in the format specific documentation.
    5108             : This function will try to validate the creation option list passed to the
    5109             : driver with the GDALValidateCreationOptions() method. This check can be
    5110             : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
    5111             : to NO.
    5112             : 
    5113             : Drivers should extend the ICreateLayer() method and not
    5114             : CreateLayer(). CreateLayer() adds validation of layer creation options, before
    5115             : delegating the actual work to ICreateLayer().
    5116             : 
    5117             : This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().
    5118             : 
    5119             : @param pszName the name for the new layer.  This should ideally not
    5120             : match any existing layer on the datasource.
    5121             : @param poGeomFieldDefn the geometry field definition to use for the new layer,
    5122             : or NULL if there is no geometry field.
    5123             : @param papszOptions a StringList of name=value options.  Options are driver
    5124             : specific.
    5125             : 
    5126             : @return NULL is returned on failure, or a new OGRLayer handle on success.
    5127             : @since 3.9
    5128             : 
    5129             : */
    5130             : 
    5131        8543 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
    5132             :                                    const OGRGeomFieldDefn *poGeomFieldDefn,
    5133             :                                    CSLConstList papszOptions)
    5134             : 
    5135             : {
    5136        8543 :     if (CPLTestBool(
    5137             :             CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
    5138             :     {
    5139        8543 :         ValidateLayerCreationOptions(papszOptions);
    5140             :     }
    5141             : 
    5142             :     OGRLayer *poLayer;
    5143        8543 :     if (poGeomFieldDefn)
    5144             :     {
    5145        7869 :         OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);
    5146        7963 :         if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&
    5147          94 :             !TestCapability(ODsCCurveGeometries))
    5148             :         {
    5149          23 :             oGeomFieldDefn.SetType(
    5150             :                 OGR_GT_GetLinear(poGeomFieldDefn->GetType()));
    5151             :         }
    5152             : 
    5153        7869 :         poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);
    5154             :     }
    5155             :     else
    5156             :     {
    5157         674 :         poLayer = ICreateLayer(pszName, nullptr, papszOptions);
    5158             :     }
    5159             : #ifdef DEBUG
    5160        8614 :     if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
    5161          71 :         !poLayer->TestCapability(OLCCurveGeometries))
    5162             :     {
    5163           0 :         CPLError(CE_Warning, CPLE_AppDefined,
    5164             :                  "Inconsistent driver: Layer geometry type is non-linear, but "
    5165             :                  "TestCapability(OLCCurveGeometries) returns FALSE.");
    5166             :     }
    5167             : #endif
    5168             : 
    5169        8543 :     return poLayer;
    5170             : }
    5171             : 
    5172             : //! @cond Doxygen_Suppress
    5173             : 
    5174             : // Technical override to avoid ambiguous choice between the old and new
    5175             : // new CreateLayer() signatures.
    5176           7 : OGRLayer *GDALDataset::CreateLayer(const char *pszName)
    5177             : {
    5178          14 :     OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
    5179          14 :     return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
    5180             : }
    5181             : 
    5182             : // Technical override to avoid ambiguous choice between the old and new
    5183             : // new CreateLayer() signatures.
    5184           1 : OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)
    5185             : {
    5186           2 :     OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
    5187           2 :     return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
    5188             : }
    5189             : 
    5190             : //!@endcond
    5191             : 
    5192             : /************************************************************************/
    5193             : /*                         GDALDatasetCreateLayer()                     */
    5194             : /************************************************************************/
    5195             : 
    5196             : /**
    5197             : \brief This function attempts to create a new layer on the dataset with the
    5198             : indicated name, coordinate system, geometry type.
    5199             : 
    5200             : The papszOptions argument can be used to control driver specific creation
    5201             : options.  These options are normally documented in the format specific
    5202             : documentation.
    5203             : 
    5204             : This method is the same as the C++ method GDALDataset::CreateLayer().
    5205             : 
    5206             : Example:
    5207             : 
    5208             : \code{.c}
    5209             : #include "gdal.h"
    5210             : #include "cpl_string.h"
    5211             : 
    5212             : ...
    5213             : 
    5214             :         OGRLayerH  hLayer;
    5215             :         char     **papszOptions;
    5216             : 
    5217             :         if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
    5218             :         {
    5219             :         ...
    5220             :         }
    5221             : 
    5222             :         papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
    5223             :         hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
    5224             :                                          papszOptions );
    5225             :         CSLDestroy( papszOptions );
    5226             : 
    5227             :         if( hLayer == NULL )
    5228             :         {
    5229             :             ...
    5230             :         }
    5231             : \endcode
    5232             : 
    5233             : @since GDAL 2.0
    5234             : 
    5235             : @param hDS the dataset handle
    5236             : @param pszName the name for the new layer.  This should ideally not
    5237             : match any existing layer on the datasource.
    5238             : @param hSpatialRef the coordinate system to use for the new layer, or NULL if
    5239             : no coordinate system is available.
    5240             : @param eGType the geometry type for the layer.  Use wkbUnknown if there
    5241             : are no constraints on the types geometry to be written.
    5242             : @param papszOptions a StringList of name=value options.  Options are driver
    5243             : specific.
    5244             : 
    5245             : @return NULL is returned on failure, or a new OGRLayer handle on success.
    5246             : 
    5247             : */
    5248             : 
    5249        5565 : OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,
    5250             :                                  OGRSpatialReferenceH hSpatialRef,
    5251             :                                  OGRwkbGeometryType eGType,
    5252             :                                  CSLConstList papszOptions)
    5253             : 
    5254             : {
    5255        5565 :     VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
    5256             : 
    5257        5565 :     if (pszName == nullptr)
    5258             :     {
    5259           0 :         CPLError(CE_Failure, CPLE_ObjectNull,
    5260             :                  "Name was NULL in GDALDatasetCreateLayer");
    5261           0 :         return nullptr;
    5262             :     }
    5263             : 
    5264             :     OGRLayerH hLayer =
    5265       11130 :         OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
    5266        5565 :             pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,
    5267             :             const_cast<char **>(papszOptions)));
    5268             : 
    5269             : #ifdef OGRAPISPY_ENABLED
    5270        5565 :     if (bOGRAPISpyEnabled)
    5271           8 :         OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,
    5272             :                                  const_cast<char **>(papszOptions), hLayer);
    5273             : #endif
    5274             : 
    5275        5565 :     return hLayer;
    5276             : }
    5277             : 
    5278             : /************************************************************************/
    5279             : /*                 GDALDatasetCreateLayerFromGeomFieldDefn()            */
    5280             : /************************************************************************/
    5281             : 
    5282             : /**
    5283             : \brief This function attempts to create a new layer on the dataset with the
    5284             : indicated name and geometry field.
    5285             : 
    5286             : When poGeomFieldDefn is not null, most drivers should honor
    5287             : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
    5288             : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
    5289             : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
    5290             : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
    5291             : very few currently.
    5292             : 
    5293             : Note that even if a geometry coordinate precision is set and a driver honors the
    5294             : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
    5295             : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
    5296             : with the coordinate precision. That is they are assumed to be valid once their
    5297             : coordinates are rounded to it. If it might not be the case, the user may set
    5298             : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
    5299             : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
    5300             : the passed geometries.
    5301             : 
    5302             : The papszOptions argument can be used to control driver specific creation
    5303             : options.  These options are normally documented in the format specific
    5304             : documentation.
    5305             : 
    5306             : This method is the same as the C++ method GDALDataset::CreateLayer().
    5307             : 
    5308             : @param hDS the dataset handle
    5309             : @param pszName the name for the new layer.  This should ideally not
    5310             : match any existing layer on the datasource.
    5311             : @param hGeomFieldDefn the geometry field definition. May be NULL to indicate
    5312             : a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()
    5313             : for drivers supporting that interface).
    5314             : @param papszOptions a StringList of name=value options.  Options are driver
    5315             : specific.
    5316             : 
    5317             : @return NULL is returned on failure, or a new OGRLayer handle on success.
    5318             : 
    5319             : @since GDAL 3.9
    5320             : 
    5321             : */
    5322             : 
    5323             : OGRLayerH
    5324          16 : GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,
    5325             :                                         OGRGeomFieldDefnH hGeomFieldDefn,
    5326             :                                         CSLConstList papszOptions)
    5327             : 
    5328             : {
    5329          16 :     VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);
    5330             : 
    5331          16 :     if (!pszName)
    5332             :     {
    5333           0 :         CPLError(CE_Failure, CPLE_ObjectNull,
    5334             :                  "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");
    5335           0 :         return nullptr;
    5336             :     }
    5337             : 
    5338             :     OGRLayerH hLayer =
    5339          32 :         OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
    5340          16 :             pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),
    5341             :             papszOptions));
    5342          16 :     return hLayer;
    5343             : }
    5344             : 
    5345             : /************************************************************************/
    5346             : /*                         GDALDatasetCopyLayer()                       */
    5347             : /************************************************************************/
    5348             : 
    5349             : /**
    5350             :  \brief Duplicate an existing layer.
    5351             : 
    5352             :  This function creates a new layer, duplicate the field definitions of the
    5353             :  source layer and then duplicate each features of the source layer.
    5354             :  The papszOptions argument
    5355             :  can be used to control driver specific creation options.  These options are
    5356             :  normally documented in the format specific documentation.
    5357             :  The source layer may come from another dataset.
    5358             : 
    5359             :  This method is the same as the C++ method GDALDataset::CopyLayer()
    5360             : 
    5361             :  @since GDAL 2.0
    5362             : 
    5363             :  @param hDS the dataset handle.
    5364             :  @param hSrcLayer source layer.
    5365             :  @param pszNewName the name of the layer to create.
    5366             :  @param papszOptions a StringList of name=value options.  Options are driver
    5367             :                      specific.
    5368             : 
    5369             :  @return a handle to the layer, or NULL if an error occurs.
    5370             : */
    5371          10 : OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,
    5372             :                                const char *pszNewName,
    5373             :                                CSLConstList papszOptions)
    5374             : 
    5375             : {
    5376          10 :     VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
    5377          10 :     VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
    5378          10 :     VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
    5379             : 
    5380          20 :     return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(
    5381             :         OGRLayer::FromHandle(hSrcLayer), pszNewName,
    5382          20 :         const_cast<char **>(papszOptions)));
    5383             : }
    5384             : 
    5385             : /************************************************************************/
    5386             : /*                        GDALDatasetExecuteSQL()                       */
    5387             : /************************************************************************/
    5388             : 
    5389             : /**
    5390             :  \brief Execute an SQL statement against the data store.
    5391             : 
    5392             :  The result of an SQL query is either NULL for statements that are in error,
    5393             :  or that have no results set, or an OGRLayer pointer representing a results
    5394             :  set from the query.  Note that this OGRLayer is in addition to the layers
    5395             :  in the data store and must be destroyed with
    5396             :  ReleaseResultSet() before the dataset is closed
    5397             :  (destroyed).
    5398             : 
    5399             :  This method is the same as the C++ method GDALDataset::ExecuteSQL()
    5400             : 
    5401             :  For more information on the SQL dialect supported internally by OGR
    5402             :  review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
    5403             :  document.  Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
    5404             :  to the underlying RDBMS.
    5405             : 
    5406             :  Starting with OGR 1.10, the <a
    5407             :  href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
    5408             :  also be used.
    5409             : 
    5410             :  @since GDAL 2.0
    5411             : 
    5412             :  @param hDS the dataset handle.
    5413             :  @param pszStatement the SQL statement to execute.
    5414             :  @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
    5415             : 
    5416             :  @param pszDialect allows control of the statement dialect. If set to NULL, the
    5417             :  OGR SQL engine will be used, except for RDBMS drivers that will use their
    5418             :  dedicated SQL engine, unless OGRSQL is explicitly passed as the
    5419             :  dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
    5420             : 
    5421             :  @return an OGRLayer containing the results of the query.  Deallocate with
    5422             :  GDALDatasetReleaseResultSet().
    5423             : 
    5424             : */
    5425             : 
    5426       10185 : OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,
    5427             :                                 OGRGeometryH hSpatialFilter,
    5428             :                                 const char *pszDialect)
    5429             : 
    5430             : {
    5431       10185 :     VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
    5432             : 
    5433             :     OGRLayerH hLayer =
    5434       20370 :         OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(
    5435       10185 :             pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));
    5436             : 
    5437             : #ifdef OGRAPISPY_ENABLED
    5438       10185 :     if (bOGRAPISpyEnabled)
    5439           4 :         OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,
    5440             :                                 hLayer);
    5441             : #endif
    5442             : 
    5443       10185 :     return hLayer;
    5444             : }
    5445             : 
    5446             : /************************************************************************/
    5447             : /*                        GDALDatasetAbortSQL()                         */
    5448             : /************************************************************************/
    5449             : 
    5450             : /**
    5451             :  \brief Abort any SQL statement running in the data store.
    5452             : 
    5453             :  This function can be safely called from any thread (pending that the dataset
    5454             :  object is still alive). Driver implementations will make sure that it can be
    5455             :  called in a thread-safe way.
    5456             : 
    5457             :  This might not be implemented by all drivers. At time of writing, only SQLite,
    5458             :  GPKG and PG drivers implement it
    5459             : 
    5460             :  This method is the same as the C++ method GDALDataset::AbortSQL()
    5461             : 
    5462             :  @since GDAL 3.2.0
    5463             : 
    5464             :  @param hDS the dataset handle.
    5465             : 
    5466             :  @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
    5467             :  is not supported for this datasource. .
    5468             : 
    5469             : */
    5470             : 
    5471           6 : OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)
    5472             : 
    5473             : {
    5474           6 :     VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);
    5475           6 :     return GDALDataset::FromHandle(hDS)->AbortSQL();
    5476             : }
    5477             : 
    5478             : /************************************************************************/
    5479             : /*                      GDALDatasetGetStyleTable()                      */
    5480             : /************************************************************************/
    5481             : 
    5482             : /**
    5483             :  \brief Returns dataset style table.
    5484             : 
    5485             :  This function is the same as the C++ method GDALDataset::GetStyleTable()
    5486             : 
    5487             :  @since GDAL 2.0
    5488             : 
    5489             :  @param hDS the dataset handle
    5490             :  @return handle to a style table which should not be modified or freed by the
    5491             :  caller.
    5492             : */
    5493             : 
    5494           6 : OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)
    5495             : 
    5496             : {
    5497           6 :     VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
    5498             : 
    5499             :     return reinterpret_cast<OGRStyleTableH>(
    5500           6 :         GDALDataset::FromHandle(hDS)->GetStyleTable());
    5501             : }
    5502             : 
    5503             : /************************************************************************/
    5504             : /*                    GDALDatasetSetStyleTableDirectly()                */
    5505             : /************************************************************************/
    5506             : 
    5507             : /**
    5508             :  \brief Set dataset style table.
    5509             : 
    5510             :  This function operate exactly as GDALDatasetSetStyleTable() except that it
    5511             :  assumes ownership of the passed table.
    5512             : 
    5513             :  This function is the same as the C++ method
    5514             :  GDALDataset::SetStyleTableDirectly()
    5515             : 
    5516             :  @since GDAL 2.0
    5517             : 
    5518             :  @param hDS the dataset handle
    5519             :  @param hStyleTable style table handle to set
    5520             : 
    5521             : */
    5522             : 
    5523           0 : void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,
    5524             :                                       OGRStyleTableH hStyleTable)
    5525             : 
    5526             : {
    5527           0 :     VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
    5528             : 
    5529           0 :     GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(
    5530           0 :         reinterpret_cast<OGRStyleTable *>(hStyleTable));
    5531             : }
    5532             : 
    5533             : /************************************************************************/
    5534             : /*                     GDALDatasetSetStyleTable()                       */
    5535             : /************************************************************************/
    5536             : 
    5537             : /**
    5538             :  \brief Set dataset style table.
    5539             : 
    5540             :  This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
    5541             :  it assumes ownership of the passed table.
    5542             : 
    5543             :  This function is the same as the C++ method GDALDataset::SetStyleTable()
    5544             : 
    5545             :  @since GDAL 2.0
    5546             : 
    5547             :  @param hDS the dataset handle
    5548             :  @param hStyleTable style table handle to set
    5549             : 
    5550             : */
    5551             : 
    5552           5 : void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)
    5553             : 
    5554             : {
    5555           5 :     VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
    5556           5 :     VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
    5557             : 
    5558           5 :     GDALDataset::FromHandle(hDS)->SetStyleTable(
    5559           5 :         reinterpret_cast<OGRStyleTable *>(hStyleTable));
    5560             : }
    5561             : 
    5562             : /************************************************************************/
    5563             : /*                    ValidateLayerCreationOptions()                    */
    5564             : /************************************************************************/
    5565             : 
    5566             : //! @cond Doxygen_Suppress
    5567        8543 : int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)
    5568             : {
    5569             :     const char *pszOptionList =
    5570        8543 :         GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
    5571        8543 :     if (pszOptionList == nullptr && poDriver != nullptr)
    5572             :     {
    5573             :         pszOptionList =
    5574        8543 :             poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
    5575             :     }
    5576       17086 :     CPLString osDataset;
    5577        8543 :     osDataset.Printf("dataset %s", GetDescription());
    5578        8543 :     return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",
    5579       17086 :                                osDataset);
    5580             : }
    5581             : 
    5582             : //! @endcond
    5583             : 
    5584             : /************************************************************************/
    5585             : /*                              Release()                               */
    5586             : /************************************************************************/
    5587             : 
    5588             : /**
    5589             : \brief Drop a reference to this dataset, and if the reference count drops to one
    5590             : close (destroy) the dataset.
    5591             : 
    5592             : This method is the same as the C function OGRReleaseDataSource().
    5593             : 
    5594             : @deprecated. In GDAL 2, use GDALClose() instead
    5595             : 
    5596             : @return OGRERR_NONE on success or an error code.
    5597             : */
    5598             : 
    5599        2145 : OGRErr GDALDataset::Release()
    5600             : 
    5601             : {
    5602        2145 :     ReleaseRef();
    5603        2145 :     return OGRERR_NONE;
    5604             : }
    5605             : 
    5606             : /************************************************************************/
    5607             : /*                            GetRefCount()                             */
    5608             : /************************************************************************/
    5609             : 
    5610             : /**
    5611             : \brief Fetch reference count.
    5612             : 
    5613             : This method is the same as the C function OGR_DS_GetRefCount().
    5614             : 
    5615             : In GDAL 1.X, this method used to be in the OGRDataSource class.
    5616             : 
    5617             : @return the current reference count for the datasource object itself.
    5618             : */
    5619             : 
    5620         839 : int GDALDataset::GetRefCount() const
    5621             : {
    5622         839 :     return nRefCount;
    5623             : }
    5624             : 
    5625             : /************************************************************************/
    5626             : /*                         GetSummaryRefCount()                         */
    5627             : /************************************************************************/
    5628             : 
    5629             : /**
    5630             : \brief Fetch reference count of datasource and all owned layers.
    5631             : 
    5632             : This method is the same as the C function  OGR_DS_GetSummaryRefCount().
    5633             : 
    5634             : In GDAL 1.X, this method used to be in the OGRDataSource class.
    5635             : 
    5636             : @deprecated
    5637             : 
    5638             : @return the current summary reference count for the datasource and its layers.
    5639             : */
    5640             : 
    5641           0 : int GDALDataset::GetSummaryRefCount() const
    5642             : 
    5643             : {
    5644           0 :     CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
    5645           0 :     int nSummaryCount = nRefCount;
    5646           0 :     GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
    5647             : 
    5648           0 :     for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)
    5649           0 :         nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
    5650             : 
    5651           0 :     return nSummaryCount;
    5652             : }
    5653             : 
    5654             : /************************************************************************/
    5655             : /*                           ICreateLayer()                             */
    5656             : /************************************************************************/
    5657             : 
    5658             : /**
    5659             :  \brief This method attempts to create a new layer on the dataset with the
    5660             :  indicated name, coordinate system, geometry type.
    5661             : 
    5662             :  This method is reserved to implementation by drivers.
    5663             : 
    5664             :  The papszOptions argument can be used to control driver specific creation
    5665             :  options.  These options are normally documented in the format specific
    5666             :  documentation.
    5667             : 
    5668             :  @param pszName the name for the new layer.  This should ideally not
    5669             :  match any existing layer on the datasource.
    5670             :  @param poGeomFieldDefn the geometry field definition to use for the new layer,
    5671             :  or NULL if there is no geometry field.
    5672             :  @param papszOptions a StringList of name=value options.  Options are driver
    5673             :  specific.
    5674             : 
    5675             :  @return NULL is returned on failure, or a new OGRLayer handle on success.
    5676             : 
    5677             :  @since GDAL 2.0 (prototype modified in 3.9)
    5678             : */
    5679             : 
    5680             : OGRLayer *
    5681          16 : GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,
    5682             :                           CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,
    5683             :                           CPL_UNUSED CSLConstList papszOptions)
    5684             : 
    5685             : {
    5686          16 :     CPLError(CE_Failure, CPLE_NotSupported,
    5687             :              "CreateLayer() not supported by this dataset.");
    5688             : 
    5689          16 :     return nullptr;
    5690             : }
    5691             : 
    5692             : /************************************************************************/
    5693             : /*                             CopyLayer()                              */
    5694             : /************************************************************************/
    5695             : 
    5696             : /**
    5697             :  \brief Duplicate an existing layer.
    5698             : 
    5699             :  This method creates a new layer, duplicate the field definitions of the
    5700             :  source layer and then duplicate each features of the source layer.
    5701             :  The papszOptions argument
    5702             :  can be used to control driver specific creation options.  These options are
    5703             :  normally documented in the format specific documentation.
    5704             :  The source layer may come from another dataset.
    5705             : 
    5706             :  This method is the same as the C function GDALDatasetCopyLayer() and the
    5707             :  deprecated OGR_DS_CopyLayer().
    5708             : 
    5709             :  In GDAL 1.X, this method used to be in the OGRDataSource class.
    5710             : 
    5711             :  @param poSrcLayer source layer.
    5712             :  @param pszNewName the name of the layer to create.
    5713             :  @param papszOptions a StringList of name=value options.  Options are driver
    5714             :                      specific. There is a common option to set output layer
    5715             :                      spatial reference: DST_SRSWKT. The option should be in
    5716             :                      WKT format. Starting with GDAL 3.7, the common option
    5717             :                      COPY_MD can be set to NO to prevent the default copying
    5718             :                      of the metadata from the source layer to the target layer.
    5719             : 
    5720             :  @return a handle to the layer, or NULL if an error occurs.
    5721             : */
    5722             : 
    5723         125 : OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
    5724             :                                  char **papszOptions)
    5725             : 
    5726             : {
    5727             :     /* -------------------------------------------------------------------- */
    5728             :     /*      Create the layer.                                               */
    5729             :     /* -------------------------------------------------------------------- */
    5730         125 :     if (!TestCapability(ODsCCreateLayer))
    5731             :     {
    5732           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    5733             :                  "This datasource does not support creation of layers.");
    5734           0 :         return nullptr;
    5735             :     }
    5736             : 
    5737         125 :     const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
    5738         250 :     OGRSpatialReference oDstSpaRef(pszSRSWKT);
    5739         125 :     oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
    5740         125 :     OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
    5741         125 :     OGRLayer *poDstLayer = nullptr;
    5742             : 
    5743         250 :     CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));
    5744         125 :     aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr);
    5745         125 :     aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr);
    5746             : 
    5747         125 :     CPLErrorReset();
    5748         125 :     const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
    5749         125 :     if (nSrcGeomFieldCount == 1)
    5750             :     {
    5751          74 :         OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
    5752          74 :         if (pszSRSWKT)
    5753           5 :             oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);
    5754          74 :         poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,
    5755          74 :                                   aosCleanedUpOptions.List());
    5756             :     }
    5757             :     else
    5758             :     {
    5759             :         poDstLayer =
    5760          51 :             ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());
    5761             :     }
    5762             : 
    5763         125 :     if (poDstLayer == nullptr)
    5764           0 :         return nullptr;
    5765             : 
    5766         125 :     if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))
    5767             :     {
    5768         124 :         char **papszMD = poSrcLayer->GetMetadata();
    5769         124 :         if (papszMD)
    5770           5 :             poDstLayer->SetMetadata(papszMD);
    5771             :     }
    5772             : 
    5773             :     /* -------------------------------------------------------------------- */
    5774             :     /*      Add fields.  Default to copy all fields, and make sure to       */
    5775             :     /*      establish a mapping between indices, rather than names, in      */
    5776             :     /*      case the target datasource has altered it (e.g. Shapefile       */
    5777             :     /*      limited to 10 char field names).                                */
    5778             :     /* -------------------------------------------------------------------- */
    5779         125 :     const int nSrcFieldCount = poSrcDefn->GetFieldCount();
    5780             : 
    5781             :     // Initialize the index-to-index map to -1's.
    5782         250 :     std::vector<int> anMap(nSrcFieldCount, -1);
    5783             : 
    5784             :     // Caution: At the time of writing, the MapInfo driver
    5785             :     // returns NULL until a field has been added.
    5786         125 :     OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
    5787         125 :     int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
    5788         269 :     for (int iField = 0; iField < nSrcFieldCount; ++iField)
    5789             :     {
    5790         144 :         OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
    5791         288 :         OGRFieldDefn oFieldDefn(poSrcFieldDefn);
    5792             : 
    5793             :         // The field may have been already created at layer creation.
    5794         144 :         int iDstField = -1;
    5795         144 :         if (poDstFDefn)
    5796         144 :             iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
    5797         144 :         if (iDstField >= 0)
    5798             :         {
    5799           0 :             anMap[iField] = iDstField;
    5800             :         }
    5801         144 :         else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)
    5802             :         {
    5803             :             // Now that we've created a field, GetLayerDefn() won't return NULL.
    5804         144 :             if (poDstFDefn == nullptr)
    5805           0 :                 poDstFDefn = poDstLayer->GetLayerDefn();
    5806             : 
    5807             :             // Sanity check: if it fails, the driver is buggy.
    5808         288 :             if (poDstFDefn != nullptr &&
    5809         144 :                 poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
    5810             :             {
    5811           0 :                 CPLError(CE_Warning, CPLE_AppDefined,
    5812             :                          "The output driver has claimed to have added the %s "
    5813             :                          "field, but it did not!",
    5814             :                          oFieldDefn.GetNameRef());
    5815             :             }
    5816             :             else
    5817             :             {
    5818         144 :                 anMap[iField] = nDstFieldCount;
    5819         144 :                 ++nDstFieldCount;
    5820             :             }
    5821             :         }
    5822             :     }
    5823             : 
    5824             :     /* -------------------------------------------------------------------- */
    5825         125 :     std::unique_ptr<OGRCoordinateTransformation> poCT;
    5826         125 :     OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
    5827         125 :     if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&
    5828           0 :         sourceSRS->IsSame(&oDstSpaRef) == FALSE)
    5829             :     {
    5830           0 :         poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));
    5831           0 :         if (nullptr == poCT)
    5832             :         {
    5833           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    5834             :                      "This input/output spatial reference is not supported.");
    5835           0 :             return nullptr;
    5836             :         }
    5837             :     }
    5838             :     /* -------------------------------------------------------------------- */
    5839             :     /*      Create geometry fields.                                         */
    5840             :     /* -------------------------------------------------------------------- */
    5841         126 :     if (nSrcGeomFieldCount > 1 &&
    5842           1 :         TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
    5843             :     {
    5844             : 
    5845           3 :         for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
    5846             :         {
    5847           2 :             if (nullptr == pszSRSWKT)
    5848             :             {
    5849           2 :                 poDstLayer->CreateGeomField(
    5850           2 :                     poSrcDefn->GetGeomFieldDefn(iField));
    5851             :             }
    5852             :             else
    5853             :             {
    5854             :                 OGRGeomFieldDefn *pDstGeomFieldDefn =
    5855           0 :                     poSrcDefn->GetGeomFieldDefn(iField);
    5856           0 :                 pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
    5857           0 :                 poDstLayer->CreateGeomField(pDstGeomFieldDefn);
    5858             :             }
    5859             :         }
    5860             :     }
    5861             : 
    5862             :     /* -------------------------------------------------------------------- */
    5863             :     /*      Check if the destination layer supports transactions and set a  */
    5864             :     /*      default number of features in a single transaction.             */
    5865             :     /* -------------------------------------------------------------------- */
    5866             :     const int nGroupTransactions =
    5867         125 :         poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
    5868             : 
    5869             :     /* -------------------------------------------------------------------- */
    5870             :     /*      Transfer features.                                              */
    5871             :     /* -------------------------------------------------------------------- */
    5872         125 :     poSrcLayer->ResetReading();
    5873             : 
    5874         125 :     if (nGroupTransactions <= 0)
    5875             :     {
    5876             :         while (true)
    5877             :         {
    5878             :             auto poFeature =
    5879         399 :                 std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
    5880             : 
    5881         399 :             if (poFeature == nullptr)
    5882         122 :                 break;
    5883             : 
    5884         277 :             CPLErrorReset();
    5885             :             auto poDstFeature =
    5886         277 :                 std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
    5887             : 
    5888         277 :             if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=
    5889             :                 OGRERR_NONE)
    5890             :             {
    5891           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
    5892             :                          "Unable to translate feature " CPL_FRMT_GIB
    5893             :                          " from layer %s.",
    5894           0 :                          poFeature->GetFID(), poSrcDefn->GetName());
    5895           0 :                 return poDstLayer;
    5896             :             }
    5897             : 
    5898         277 :             if (nullptr != poCT)
    5899             :             {
    5900           0 :                 for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
    5901             :                 {
    5902           0 :                     OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
    5903           0 :                     if (nullptr == pGeom)
    5904           0 :                         continue;
    5905             : 
    5906           0 :                     const OGRErr eErr = pGeom->transform(poCT.get());
    5907           0 :                     if (eErr == OGRERR_NONE)
    5908           0 :                         continue;
    5909             : 
    5910           0 :                     CPLError(CE_Failure, CPLE_AppDefined,
    5911             :                              "Unable to transform geometry " CPL_FRMT_GIB
    5912             :                              " from layer %s.",
    5913           0 :                              poFeature->GetFID(), poSrcDefn->GetName());
    5914           0 :                     return poDstLayer;
    5915             :                 }
    5916             :             }
    5917             : 
    5918         277 :             poDstFeature->SetFID(poFeature->GetFID());
    5919             : 
    5920         277 :             CPLErrorReset();
    5921         277 :             if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)
    5922             :             {
    5923           0 :                 return poDstLayer;
    5924             :             }
    5925         277 :         }
    5926             :     }
    5927             :     else
    5928             :     {
    5929           3 :         std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;
    5930             :         try
    5931             :         {
    5932           3 :             apoDstFeatures.resize(nGroupTransactions);
    5933             :         }
    5934           0 :         catch (const std::exception &e)
    5935             :         {
    5936           0 :             CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
    5937           0 :             return poDstLayer;
    5938             :         }
    5939           3 :         bool bStopTransfer = false;
    5940           6 :         while (!bStopTransfer)
    5941             :         {
    5942             :             /* --------------------------------------------------------------------
    5943             :              */
    5944             :             /*      Fill the array with features. */
    5945             :             /* --------------------------------------------------------------------
    5946             :              */
    5947             :             // Number of features in the temporary array.
    5948           3 :             int nFeatCount = 0;  // Used after for.
    5949          33 :             for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)
    5950             :             {
    5951             :                 auto poFeature =
    5952          33 :                     std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
    5953             : 
    5954          33 :                 if (poFeature == nullptr)
    5955             :                 {
    5956           3 :                     bStopTransfer = true;
    5957           3 :                     break;
    5958             :                 }
    5959             : 
    5960          30 :                 CPLErrorReset();
    5961          30 :                 apoDstFeatures[nFeatCount] =
    5962          60 :                     std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
    5963             : 
    5964          60 :                 if (apoDstFeatures[nFeatCount]->SetFrom(
    5965          60 :                         poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)
    5966             :                 {
    5967           0 :                     CPLError(CE_Failure, CPLE_AppDefined,
    5968             :                              "Unable to translate feature " CPL_FRMT_GIB
    5969             :                              " from layer %s.",
    5970           0 :                              poFeature->GetFID(), poSrcDefn->GetName());
    5971           0 :                     bStopTransfer = true;
    5972           0 :                     poFeature.reset();
    5973           0 :                     break;
    5974             :                 }
    5975             : 
    5976          30 :                 if (nullptr != poCT)
    5977             :                 {
    5978           0 :                     for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
    5979             :                     {
    5980             :                         OGRGeometry *pGeom =
    5981           0 :                             apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);
    5982           0 :                         if (nullptr == pGeom)
    5983           0 :                             continue;
    5984             : 
    5985           0 :                         const OGRErr eErr = pGeom->transform(poCT.get());
    5986           0 :                         if (eErr == OGRERR_NONE)
    5987           0 :                             continue;
    5988             : 
    5989           0 :                         CPLError(CE_Failure, CPLE_AppDefined,
    5990             :                                  "Unable to transform geometry " CPL_FRMT_GIB
    5991             :                                  " from layer %s.",
    5992           0 :                                  poFeature->GetFID(), poSrcDefn->GetName());
    5993           0 :                         bStopTransfer = true;
    5994           0 :                         poFeature.reset();
    5995           0 :                         break;
    5996             :                     }
    5997             :                 }
    5998             : 
    5999          30 :                 if (poFeature)
    6000             :                 {
    6001          30 :                     apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());
    6002             :                 }
    6003             :             }
    6004             : 
    6005           3 :             CPLErrorReset();
    6006           3 :             bool bStopTransaction = false;
    6007           6 :             while (!bStopTransaction)
    6008             :             {
    6009           3 :                 bStopTransaction = true;
    6010           3 :                 if (poDstLayer->StartTransaction() != OGRERR_NONE)
    6011           0 :                     break;
    6012          33 :                 for (int i = 0; i < nFeatCount; ++i)
    6013             :                 {
    6014          30 :                     if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=
    6015             :                         OGRERR_NONE)
    6016             :                     {
    6017           0 :                         bStopTransfer = true;
    6018           0 :                         bStopTransaction = false;
    6019           0 :                         break;
    6020             :                     }
    6021          30 :                     apoDstFeatures[i].reset();
    6022             :                 }
    6023           3 :                 if (bStopTransaction)
    6024             :                 {
    6025           3 :                     if (poDstLayer->CommitTransaction() != OGRERR_NONE)
    6026           0 :                         break;
    6027             :                 }
    6028             :                 else
    6029             :                 {
    6030           0 :                     poDstLayer->RollbackTransaction();
    6031             :                 }
    6032             :             }
    6033             :         }
    6034             :     }
    6035             : 
    6036         125 :     return poDstLayer;
    6037             : }
    6038             : 
    6039             : /************************************************************************/
    6040             : /*                            DeleteLayer()                             */
    6041             : /************************************************************************/
    6042             : 
    6043             : /**
    6044             :  \fn GDALDataset::DeleteLayer(int)
    6045             :  \brief Delete the indicated layer from the datasource.
    6046             : 
    6047             :  If this method is supported
    6048             :  the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
    6049             : 
    6050             :  This method is the same as the C function GDALDatasetDeleteLayer() and the
    6051             :  deprecated OGR_DS_DeleteLayer().
    6052             : 
    6053             :  In GDAL 1.X, this method used to be in the OGRDataSource class.
    6054             : 
    6055             :  @param iLayer the index of the layer to delete.
    6056             : 
    6057             :  @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
    6058             :  layers is not supported for this datasource.
    6059             : 
    6060             : */
    6061             : 
    6062         405 : OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)
    6063             : 
    6064             : {
    6065         405 :     CPLError(CE_Failure, CPLE_NotSupported,
    6066             :              "DeleteLayer() not supported by this dataset.");
    6067             : 
    6068         405 :     return OGRERR_UNSUPPORTED_OPERATION;
    6069             : }
    6070             : 
    6071             : /************************************************************************/
    6072             : /*                           GetLayerByName()                           */
    6073             : /************************************************************************/
    6074             : 
    6075             : /**
    6076             :  \brief Fetch a layer by name.
    6077             : 
    6078             :  The returned layer remains owned by the
    6079             :  GDALDataset and should not be deleted by the application.
    6080             : 
    6081             :  This method is the same as the C function GDALDatasetGetLayerByName() and the
    6082             :  deprecated OGR_DS_GetLayerByName().
    6083             : 
    6084             :  In GDAL 1.X, this method used to be in the OGRDataSource class.
    6085             : 
    6086             :  @param pszName the layer name of the layer to fetch.
    6087             : 
    6088             :  @return the layer, or NULL if Layer is not found or an error occurs.
    6089             : */
    6090             : 
    6091       29425 : OGRLayer *GDALDataset::GetLayerByName(const char *pszName)
    6092             : 
    6093             : {
    6094       58850 :     CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
    6095             : 
    6096       29425 :     if (!pszName)
    6097           0 :         return nullptr;
    6098             : 
    6099             :     // First a case sensitive check.
    6100      934586 :     for (int i = 0; i < GetLayerCount(); ++i)
    6101             :     {
    6102      916338 :         OGRLayer *poLayer = GetLayer(i);
    6103             : 
    6104      916338 :         if (strcmp(pszName, poLayer->GetName()) == 0)
    6105       11177 :             return poLayer;
    6106             :     }
    6107             : 
    6108             :     // Then case insensitive.
    6109      895562 :     for (int i = 0; i < GetLayerCount(); ++i)
    6110             :     {
    6111      877464 :         OGRLayer *poLayer = GetLayer(i);
    6112             : 
    6113      877464 :         if (EQUAL(pszName, poLayer->GetName()))
    6114         150 :             return poLayer;
    6115             :     }
    6116             : 
    6117       18098 :     return nullptr;
    6118             : }
    6119             : 
    6120             : //! @cond Doxygen_Suppress
    6121             : /************************************************************************/
    6122             : /*                       ProcessSQLCreateIndex()                        */
    6123             : /*                                                                      */
    6124             : /*      The correct syntax for creating an index in our dialect of      */
    6125             : /*      SQL is:                                                         */
    6126             : /*                                                                      */
    6127             : /*        CREATE INDEX ON <layername> USING <columnname>                */
    6128             : /************************************************************************/
    6129             : 
    6130          28 : OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)
    6131             : 
    6132             : {
    6133          28 :     char **papszTokens = CSLTokenizeString(pszSQLCommand);
    6134             : 
    6135             :     /* -------------------------------------------------------------------- */
    6136             :     /*      Do some general syntax checking.                                */
    6137             :     /* -------------------------------------------------------------------- */
    6138          56 :     if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||
    6139          84 :         !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||
    6140          28 :         !EQUAL(papszTokens[4], "USING"))
    6141             :     {
    6142           0 :         CSLDestroy(papszTokens);
    6143           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6144             :                  "Syntax error in CREATE INDEX command.\n"
    6145             :                  "Was '%s'\n"
    6146             :                  "Should be of form 'CREATE INDEX ON <table> USING <field>'",
    6147             :                  pszSQLCommand);
    6148           0 :         return OGRERR_FAILURE;
    6149             :     }
    6150             : 
    6151             :     /* -------------------------------------------------------------------- */
    6152             :     /*      Find the named layer.                                           */
    6153             :     /* -------------------------------------------------------------------- */
    6154          28 :     OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
    6155          28 :     if (poLayer == nullptr)
    6156             :     {
    6157           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6158             :                  "CREATE INDEX ON failed, no such layer as `%s'.",
    6159           0 :                  papszTokens[3]);
    6160           0 :         CSLDestroy(papszTokens);
    6161           0 :         return OGRERR_FAILURE;
    6162             :     }
    6163             : 
    6164             :     /* -------------------------------------------------------------------- */
    6165             :     /*      Does this layer even support attribute indexes?                 */
    6166             :     /* -------------------------------------------------------------------- */
    6167          28 :     if (poLayer->GetIndex() == nullptr)
    6168             :     {
    6169           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6170             :                  "CREATE INDEX ON not supported by this driver.");
    6171           0 :         CSLDestroy(papszTokens);
    6172           0 :         return OGRERR_FAILURE;
    6173             :     }
    6174             : 
    6175             :     /* -------------------------------------------------------------------- */
    6176             :     /*      Find the named field.                                           */
    6177             :     /* -------------------------------------------------------------------- */
    6178          28 :     int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
    6179             : 
    6180          28 :     CSLDestroy(papszTokens);
    6181             : 
    6182          28 :     if (i >= poLayer->GetLayerDefn()->GetFieldCount())
    6183             :     {
    6184           0 :         CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
    6185             :                  pszSQLCommand);
    6186           0 :         return OGRERR_FAILURE;
    6187             :     }
    6188             : 
    6189             :     /* -------------------------------------------------------------------- */
    6190             :     /*      Attempt to create the index.                                    */
    6191             :     /* -------------------------------------------------------------------- */
    6192          28 :     OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
    6193          28 :     if (eErr == OGRERR_NONE)
    6194             :     {
    6195          28 :         eErr = poLayer->GetIndex()->IndexAllFeatures(i);
    6196             :     }
    6197             :     else
    6198             :     {
    6199           0 :         if (strlen(CPLGetLastErrorMsg()) == 0)
    6200           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
    6201             :     }
    6202             : 
    6203          28 :     return eErr;
    6204             : }
    6205             : 
    6206             : /************************************************************************/
    6207             : /*                        ProcessSQLDropIndex()                         */
    6208             : /*                                                                      */
    6209             : /*      The correct syntax for dropping one or more indexes in          */
    6210             : /*      the OGR SQL dialect is:                                         */
    6211             : /*                                                                      */
    6212             : /*          DROP INDEX ON <layername> [USING <columnname>]              */
    6213             : /************************************************************************/
    6214             : 
    6215          10 : OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)
    6216             : 
    6217             : {
    6218          10 :     char **papszTokens = CSLTokenizeString(pszSQLCommand);
    6219             : 
    6220             :     /* -------------------------------------------------------------------- */
    6221             :     /*      Do some general syntax checking.                                */
    6222             :     /* -------------------------------------------------------------------- */
    6223          20 :     if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||
    6224          10 :         !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||
    6225          30 :         !EQUAL(papszTokens[2], "ON") ||
    6226          10 :         (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))
    6227             :     {
    6228           0 :         CSLDestroy(papszTokens);
    6229           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6230             :                  "Syntax error in DROP INDEX command.\n"
    6231             :                  "Was '%s'\n"
    6232             :                  "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
    6233             :                  pszSQLCommand);
    6234           0 :         return OGRERR_FAILURE;
    6235             :     }
    6236             : 
    6237             :     /* -------------------------------------------------------------------- */
    6238             :     /*      Find the named layer.                                           */
    6239             :     /* -------------------------------------------------------------------- */
    6240          10 :     OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
    6241          10 :     if (poLayer == nullptr)
    6242             :     {
    6243           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6244             :                  "DROP INDEX ON failed, no such layer as `%s'.",
    6245           0 :                  papszTokens[3]);
    6246           0 :         CSLDestroy(papszTokens);
    6247           0 :         return OGRERR_FAILURE;
    6248             :     }
    6249             : 
    6250             :     /* -------------------------------------------------------------------- */
    6251             :     /*      Does this layer even support attribute indexes?                 */
    6252             :     /* -------------------------------------------------------------------- */
    6253          10 :     if (poLayer->GetIndex() == nullptr)
    6254             :     {
    6255           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6256             :                  "Indexes not supported by this driver.");
    6257           0 :         CSLDestroy(papszTokens);
    6258           0 :         return OGRERR_FAILURE;
    6259             :     }
    6260             : 
    6261             :     /* -------------------------------------------------------------------- */
    6262             :     /*      If we were not given a field name, drop all indexes.            */
    6263             :     /* -------------------------------------------------------------------- */
    6264          10 :     if (CSLCount(papszTokens) == 4)
    6265             :     {
    6266           0 :         for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)
    6267             :         {
    6268             :             OGRAttrIndex *poAttrIndex;
    6269             : 
    6270           0 :             poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
    6271           0 :             if (poAttrIndex != nullptr)
    6272             :             {
    6273           0 :                 const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
    6274           0 :                 if (eErr != OGRERR_NONE)
    6275             :                 {
    6276           0 :                     CSLDestroy(papszTokens);
    6277           0 :                     return eErr;
    6278             :                 }
    6279             :             }
    6280             :         }
    6281             : 
    6282           0 :         CSLDestroy(papszTokens);
    6283           0 :         return OGRERR_NONE;
    6284             :     }
    6285             : 
    6286             :     /* -------------------------------------------------------------------- */
    6287             :     /*      Find the named field.                                           */
    6288             :     /* -------------------------------------------------------------------- */
    6289          10 :     int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
    6290          10 :     CSLDestroy(papszTokens);
    6291             : 
    6292          10 :     if (i >= poLayer->GetLayerDefn()->GetFieldCount())
    6293             :     {
    6294           0 :         CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
    6295             :                  pszSQLCommand);
    6296           0 :         return OGRERR_FAILURE;
    6297             :     }
    6298             : 
    6299             :     /* -------------------------------------------------------------------- */
    6300             :     /*      Attempt to drop the index.                                      */
    6301             :     /* -------------------------------------------------------------------- */
    6302          10 :     const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
    6303             : 
    6304          10 :     return eErr;
    6305             : }
    6306             : 
    6307             : /************************************************************************/
    6308             : /*                        ProcessSQLDropTable()                         */
    6309             : /*                                                                      */
    6310             : /*      The correct syntax for dropping a table (layer) in the OGR SQL  */
    6311             : /*      dialect is:                                                     */
    6312             : /*                                                                      */
    6313             : /*          DROP TABLE <layername>                                      */
    6314             : /************************************************************************/
    6315             : 
    6316         500 : OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)
    6317             : 
    6318             : {
    6319         500 :     char **papszTokens = CSLTokenizeString(pszSQLCommand);
    6320             : 
    6321             :     /* -------------------------------------------------------------------- */
    6322             :     /*      Do some general syntax checking.                                */
    6323             :     /* -------------------------------------------------------------------- */
    6324        1000 :     if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||
    6325         500 :         !EQUAL(papszTokens[1], "TABLE"))
    6326             :     {
    6327           0 :         CSLDestroy(papszTokens);
    6328           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6329             :                  "Syntax error in DROP TABLE command.\n"
    6330             :                  "Was '%s'\n"
    6331             :                  "Should be of form 'DROP TABLE <table>'",
    6332             :                  pszSQLCommand);
    6333           0 :         return OGRERR_FAILURE;
    6334             :     }
    6335             : 
    6336             :     /* -------------------------------------------------------------------- */
    6337             :     /*      Find the named layer.                                           */
    6338             :     /* -------------------------------------------------------------------- */
    6339         500 :     OGRLayer *poLayer = nullptr;
    6340             : 
    6341         500 :     int i = 0;  // Used after for.
    6342       40199 :     for (; i < GetLayerCount(); ++i)
    6343             :     {
    6344       40199 :         poLayer = GetLayer(i);
    6345             : 
    6346       40199 :         if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))
    6347         500 :             break;
    6348       39699 :         poLayer = nullptr;
    6349             :     }
    6350             : 
    6351         500 :     if (poLayer == nullptr)
    6352             :     {
    6353           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6354           0 :                  "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
    6355           0 :         CSLDestroy(papszTokens);
    6356           0 :         return OGRERR_FAILURE;
    6357             :     }
    6358             : 
    6359         500 :     CSLDestroy(papszTokens);
    6360             : 
    6361             :     /* -------------------------------------------------------------------- */
    6362             :     /*      Delete it.                                                      */
    6363             :     /* -------------------------------------------------------------------- */
    6364             : 
    6365         500 :     return DeleteLayer(i);
    6366             : }
    6367             : 
    6368             : //! @endcond
    6369             : 
    6370             : /************************************************************************/
    6371             : /*                    GDALDatasetParseSQLType()                       */
    6372             : /************************************************************************/
    6373             : 
    6374             : /* All arguments will be altered */
    6375           6 : static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
    6376             :                                             int &nPrecision)
    6377             : {
    6378           6 :     char *pszParenthesis = strchr(pszType, '(');
    6379           6 :     if (pszParenthesis)
    6380             :     {
    6381           4 :         nWidth = atoi(pszParenthesis + 1);
    6382           4 :         *pszParenthesis = '\0';
    6383           4 :         char *pszComma = strchr(pszParenthesis + 1, ',');
    6384           4 :         if (pszComma)
    6385           2 :             nPrecision = atoi(pszComma + 1);
    6386             :     }
    6387             : 
    6388           6 :     OGRFieldType eType = OFTString;
    6389           6 :     if (EQUAL(pszType, "INTEGER"))
    6390           0 :         eType = OFTInteger;
    6391           6 :     else if (EQUAL(pszType, "INTEGER[]"))
    6392           0 :         eType = OFTIntegerList;
    6393           6 :     else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||
    6394           4 :              EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
    6395           4 :              EQUAL(pszType, "REAL") /* unofficial alias */)
    6396           2 :         eType = OFTReal;
    6397           4 :     else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||
    6398           4 :              EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
    6399           4 :              EQUAL(pszType, "REAL[]") /* unofficial alias */)
    6400           0 :         eType = OFTRealList;
    6401           4 :     else if (EQUAL(pszType, "CHARACTER") ||
    6402           0 :              EQUAL(pszType, "TEXT") /* unofficial alias */ ||
    6403           0 :              EQUAL(pszType, "STRING") /* unofficial alias */ ||
    6404           0 :              EQUAL(pszType, "VARCHAR") /* unofficial alias */)
    6405           4 :         eType = OFTString;
    6406           0 :     else if (EQUAL(pszType, "TEXT[]") ||
    6407           0 :              EQUAL(pszType, "STRING[]") /* unofficial alias */ ||
    6408           0 :              EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
    6409           0 :         eType = OFTStringList;
    6410           0 :     else if (EQUAL(pszType, "DATE"))
    6411           0 :         eType = OFTDate;
    6412           0 :     else if (EQUAL(pszType, "TIME"))
    6413           0 :         eType = OFTTime;
    6414           0 :     else if (EQUAL(pszType, "TIMESTAMP") ||
    6415           0 :              EQUAL(pszType, "DATETIME") /* unofficial alias */)
    6416           0 :         eType = OFTDateTime;
    6417             :     else
    6418           0 :         CPLError(CE_Warning, CPLE_NotSupported,
    6419             :                  "Unsupported column type '%s'. Defaulting to VARCHAR",
    6420             :                  pszType);
    6421             : 
    6422           6 :     return eType;
    6423             : }
    6424             : 
    6425             : /************************************************************************/
    6426             : /*                    ProcessSQLAlterTableAddColumn()                   */
    6427             : /*                                                                      */
    6428             : /*      The correct syntax for adding a column in the OGR SQL           */
    6429             : /*      dialect is:                                                     */
    6430             : /*                                                                      */
    6431             : /*       ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
    6432             : /************************************************************************/
    6433             : 
    6434             : //! @cond Doxygen_Suppress
    6435           2 : OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)
    6436             : 
    6437             : {
    6438           2 :     char **papszTokens = CSLTokenizeString(pszSQLCommand);
    6439             : 
    6440             :     /* -------------------------------------------------------------------- */
    6441             :     /*      Do some general syntax checking.                                */
    6442             :     /* -------------------------------------------------------------------- */
    6443           2 :     const char *pszLayerName = nullptr;
    6444           2 :     const char *pszColumnName = nullptr;
    6445           2 :     int iTypeIndex = 0;
    6446           2 :     const int nTokens = CSLCount(papszTokens);
    6447             : 
    6448           2 :     if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
    6449           2 :         EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&
    6450           2 :         EQUAL(papszTokens[4], "COLUMN"))
    6451             :     {
    6452           1 :         pszLayerName = papszTokens[2];
    6453           1 :         pszColumnName = papszTokens[5];
    6454           1 :         iTypeIndex = 6;
    6455             :     }
    6456           1 :     else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&
    6457           1 :              EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))
    6458             :     {
    6459           1 :         pszLayerName = papszTokens[2];
    6460           1 :         pszColumnName = papszTokens[4];
    6461           1 :         iTypeIndex = 5;
    6462             :     }
    6463             :     else
    6464             :     {
    6465           0 :         CSLDestroy(papszTokens);
    6466           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6467             :                  "Syntax error in ALTER TABLE ADD COLUMN command.\n"
    6468             :                  "Was '%s'\n"
    6469             :                  "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
    6470             :                  "<columnname> <columntype>'",
    6471             :                  pszSQLCommand);
    6472           0 :         return OGRERR_FAILURE;
    6473             :     }
    6474             : 
    6475             :     /* -------------------------------------------------------------------- */
    6476             :     /*      Merge type components into a single string if there were split  */
    6477             :     /*      with spaces                                                     */
    6478             :     /* -------------------------------------------------------------------- */
    6479           4 :     CPLString osType;
    6480           6 :     for (int i = iTypeIndex; i < nTokens; ++i)
    6481             :     {
    6482           4 :         osType += papszTokens[i];
    6483           4 :         CPLFree(papszTokens[i]);
    6484             :     }
    6485           2 :     char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
    6486           2 :     papszTokens[iTypeIndex + 1] = nullptr;
    6487             : 
    6488             :     /* -------------------------------------------------------------------- */
    6489             :     /*      Find the named layer.                                           */
    6490             :     /* -------------------------------------------------------------------- */
    6491           2 :     OGRLayer *poLayer = GetLayerByName(pszLayerName);
    6492           2 :     if (poLayer == nullptr)
    6493             :     {
    6494           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6495             :                  "%s failed, no such layer as `%s'.", pszSQLCommand,
    6496             :                  pszLayerName);
    6497           0 :         CSLDestroy(papszTokens);
    6498           0 :         return OGRERR_FAILURE;
    6499             :     }
    6500             : 
    6501             :     /* -------------------------------------------------------------------- */
    6502             :     /*      Add column.                                                     */
    6503             :     /* -------------------------------------------------------------------- */
    6504             : 
    6505           2 :     int nWidth = 0;
    6506           2 :     int nPrecision = 0;
    6507           2 :     OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
    6508           4 :     OGRFieldDefn oFieldDefn(pszColumnName, eType);
    6509           2 :     oFieldDefn.SetWidth(nWidth);
    6510           2 :     oFieldDefn.SetPrecision(nPrecision);
    6511             : 
    6512           2 :     CSLDestroy(papszTokens);
    6513             : 
    6514           2 :     return poLayer->CreateField(&oFieldDefn);
    6515             : }
    6516             : 
    6517             : /************************************************************************/
    6518             : /*                    ProcessSQLAlterTableDropColumn()                  */
    6519             : /*                                                                      */
    6520             : /*      The correct syntax for dropping a column in the OGR SQL         */
    6521             : /*      dialect is:                                                     */
    6522             : /*                                                                      */
    6523             : /*          ALTER TABLE <layername> DROP [COLUMN] <columnname>          */
    6524             : /************************************************************************/
    6525             : 
    6526           2 : OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)
    6527             : 
    6528             : {
    6529           2 :     char **papszTokens = CSLTokenizeString(pszSQLCommand);
    6530             : 
    6531             :     /* -------------------------------------------------------------------- */
    6532             :     /*      Do some general syntax checking.                                */
    6533             :     /* -------------------------------------------------------------------- */
    6534           2 :     const char *pszLayerName = nullptr;
    6535           2 :     const char *pszColumnName = nullptr;
    6536           3 :     if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&
    6537           4 :         EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&
    6538           1 :         EQUAL(papszTokens[4], "COLUMN"))
    6539             :     {
    6540           1 :         pszLayerName = papszTokens[2];
    6541           1 :         pszColumnName = papszTokens[5];
    6542             :     }
    6543           2 :     else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&
    6544           2 :              EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))
    6545             :     {
    6546           1 :         pszLayerName = papszTokens[2];
    6547           1 :         pszColumnName = papszTokens[4];
    6548             :     }
    6549             :     else
    6550             :     {
    6551           0 :         CSLDestroy(papszTokens);
    6552           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6553             :                  "Syntax error in ALTER TABLE DROP COLUMN command.\n"
    6554             :                  "Was '%s'\n"
    6555             :                  "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
    6556             :                  "<columnname>'",
    6557             :                  pszSQLCommand);
    6558           0 :         return OGRERR_FAILURE;
    6559             :     }
    6560             : 
    6561             :     /* -------------------------------------------------------------------- */
    6562             :     /*      Find the named layer.                                           */
    6563             :     /* -------------------------------------------------------------------- */
    6564           2 :     OGRLayer *poLayer = GetLayerByName(pszLayerName);
    6565           2 :     if (poLayer == nullptr)
    6566             :     {
    6567           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6568             :                  "%s failed, no such layer as `%s'.", pszSQLCommand,
    6569             :                  pszLayerName);
    6570           0 :         CSLDestroy(papszTokens);
    6571           0 :         return OGRERR_FAILURE;
    6572             :     }
    6573             : 
    6574             :     /* -------------------------------------------------------------------- */
    6575             :     /*      Find the field.                                                 */
    6576             :     /* -------------------------------------------------------------------- */
    6577             : 
    6578           2 :     int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
    6579           2 :     if (nFieldIndex < 0)
    6580             :     {
    6581           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6582             :                  "%s failed, no such field as `%s'.", pszSQLCommand,
    6583             :                  pszColumnName);
    6584           0 :         CSLDestroy(papszTokens);
    6585           0 :         return OGRERR_FAILURE;
    6586             :     }
    6587             : 
    6588             :     /* -------------------------------------------------------------------- */
    6589             :     /*      Remove it.                                                      */
    6590             :     /* -------------------------------------------------------------------- */
    6591             : 
    6592           2 :     CSLDestroy(papszTokens);
    6593             : 
    6594           2 :     return poLayer->DeleteField(nFieldIndex);
    6595             : }
    6596             : 
    6597             : /************************************************************************/
    6598             : /*                 ProcessSQLAlterTableRenameColumn()                   */
    6599             : /*                                                                      */
    6600             : /*      The correct syntax for renaming a column in the OGR SQL         */
    6601             : /*      dialect is:                                                     */
    6602             : /*                                                                      */
    6603             : /*       ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
    6604             : /************************************************************************/
    6605             : 
    6606           2 : OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)
    6607             : 
    6608             : {
    6609           2 :     char **papszTokens = CSLTokenizeString(pszSQLCommand);
    6610             : 
    6611             :     /* -------------------------------------------------------------------- */
    6612             :     /*      Do some general syntax checking.                                */
    6613             :     /* -------------------------------------------------------------------- */
    6614           2 :     const char *pszLayerName = nullptr;
    6615           2 :     const char *pszOldColName = nullptr;
    6616           2 :     const char *pszNewColName = nullptr;
    6617           3 :     if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&
    6618           1 :         EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&
    6619           3 :         EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))
    6620             :     {
    6621           1 :         pszLayerName = papszTokens[2];
    6622           1 :         pszOldColName = papszTokens[5];
    6623           1 :         pszNewColName = papszTokens[7];
    6624             :     }
    6625           2 :     else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&
    6626           1 :              EQUAL(papszTokens[1], "TABLE") &&
    6627           2 :              EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))
    6628             :     {
    6629           1 :         pszLayerName = papszTokens[2];
    6630           1 :         pszOldColName = papszTokens[4];
    6631           1 :         pszNewColName = papszTokens[6];
    6632             :     }
    6633             :     else
    6634             :     {
    6635           0 :         CSLDestroy(papszTokens);
    6636           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6637             :                  "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
    6638             :                  "Was '%s'\n"
    6639             :                  "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
    6640             :                  "<columnname> TO <newname>'",
    6641             :                  pszSQLCommand);
    6642           0 :         return OGRERR_FAILURE;
    6643             :     }
    6644             : 
    6645             :     /* -------------------------------------------------------------------- */
    6646             :     /*      Find the named layer.                                           */
    6647             :     /* -------------------------------------------------------------------- */
    6648           2 :     OGRLayer *poLayer = GetLayerByName(pszLayerName);
    6649           2 :     if (poLayer == nullptr)
    6650             :     {
    6651           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6652             :                  "%s failed, no such layer as `%s'.", pszSQLCommand,
    6653             :                  pszLayerName);
    6654           0 :         CSLDestroy(papszTokens);
    6655           0 :         return OGRERR_FAILURE;
    6656             :     }
    6657             : 
    6658             :     /* -------------------------------------------------------------------- */
    6659             :     /*      Find the field.                                                 */
    6660             :     /* -------------------------------------------------------------------- */
    6661             : 
    6662             :     const int nFieldIndex =
    6663           2 :         poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
    6664           2 :     if (nFieldIndex < 0)
    6665             :     {
    6666           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6667             :                  "%s failed, no such field as `%s'.", pszSQLCommand,
    6668             :                  pszOldColName);
    6669           0 :         CSLDestroy(papszTokens);
    6670           0 :         return OGRERR_FAILURE;
    6671             :     }
    6672             : 
    6673             :     /* -------------------------------------------------------------------- */
    6674             :     /*      Rename column.                                                  */
    6675             :     /* -------------------------------------------------------------------- */
    6676             :     OGRFieldDefn *poOldFieldDefn =
    6677           2 :         poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
    6678           4 :     OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
    6679           2 :     oNewFieldDefn.SetName(pszNewColName);
    6680             : 
    6681           2 :     CSLDestroy(papszTokens);
    6682             : 
    6683           2 :     return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
    6684           2 :                                    ALTER_NAME_FLAG);
    6685             : }
    6686             : 
    6687             : /************************************************************************/
    6688             : /*                 ProcessSQLAlterTableAlterColumn()                    */
    6689             : /*                                                                      */
    6690             : /*      The correct syntax for altering the type of a column in the     */
    6691             : /*      OGR SQL dialect is:                                             */
    6692             : /*                                                                      */
    6693             : /*   ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
    6694             : /************************************************************************/
    6695             : 
    6696           4 : OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)
    6697             : 
    6698             : {
    6699           4 :     char **papszTokens = CSLTokenizeString(pszSQLCommand);
    6700             : 
    6701             :     /* -------------------------------------------------------------------- */
    6702             :     /*      Do some general syntax checking.                                */
    6703             :     /* -------------------------------------------------------------------- */
    6704           4 :     const char *pszLayerName = nullptr;
    6705           4 :     const char *pszColumnName = nullptr;
    6706           4 :     int iTypeIndex = 0;
    6707           4 :     const int nTokens = CSLCount(papszTokens);
    6708             : 
    6709           4 :     if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&
    6710           2 :         EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
    6711           2 :         EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))
    6712             :     {
    6713           2 :         pszLayerName = papszTokens[2];
    6714           2 :         pszColumnName = papszTokens[5];
    6715           2 :         iTypeIndex = 7;
    6716             :     }
    6717           2 :     else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
    6718           2 :              EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
    6719           2 :              EQUAL(papszTokens[5], "TYPE"))
    6720             :     {
    6721           2 :         pszLayerName = papszTokens[2];
    6722           2 :         pszColumnName = papszTokens[4];
    6723           2 :         iTypeIndex = 6;
    6724             :     }
    6725             :     else
    6726             :     {
    6727           0 :         CSLDestroy(papszTokens);
    6728           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6729             :                  "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
    6730             :                  "Was '%s'\n"
    6731             :                  "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
    6732             :                  "<columnname> TYPE <columntype>'",
    6733             :                  pszSQLCommand);
    6734           0 :         return OGRERR_FAILURE;
    6735             :     }
    6736             : 
    6737             :     /* -------------------------------------------------------------------- */
    6738             :     /*      Merge type components into a single string if there were split  */
    6739             :     /*      with spaces                                                     */
    6740             :     /* -------------------------------------------------------------------- */
    6741           8 :     CPLString osType;
    6742           8 :     for (int i = iTypeIndex; i < nTokens; ++i)
    6743             :     {
    6744           4 :         osType += papszTokens[i];
    6745           4 :         CPLFree(papszTokens[i]);
    6746             :     }
    6747           4 :     char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
    6748           4 :     papszTokens[iTypeIndex + 1] = nullptr;
    6749             : 
    6750             :     /* -------------------------------------------------------------------- */
    6751             :     /*      Find the named layer.                                           */
    6752             :     /* -------------------------------------------------------------------- */
    6753           4 :     OGRLayer *poLayer = GetLayerByName(pszLayerName);
    6754           4 :     if (poLayer == nullptr)
    6755             :     {
    6756           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6757             :                  "%s failed, no such layer as `%s'.", pszSQLCommand,
    6758             :                  pszLayerName);
    6759           0 :         CSLDestroy(papszTokens);
    6760           0 :         return OGRERR_FAILURE;
    6761             :     }
    6762             : 
    6763             :     /* -------------------------------------------------------------------- */
    6764             :     /*      Find the field.                                                 */
    6765             :     /* -------------------------------------------------------------------- */
    6766             : 
    6767             :     const int nFieldIndex =
    6768           4 :         poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
    6769           4 :     if (nFieldIndex < 0)
    6770             :     {
    6771           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    6772             :                  "%s failed, no such field as `%s'.", pszSQLCommand,
    6773             :                  pszColumnName);
    6774           0 :         CSLDestroy(papszTokens);
    6775           0 :         return OGRERR_FAILURE;
    6776             :     }
    6777             : 
    6778             :     /* -------------------------------------------------------------------- */
    6779             :     /*      Alter column.                                                   */
    6780             :     /* -------------------------------------------------------------------- */
    6781             : 
    6782             :     OGRFieldDefn *poOldFieldDefn =
    6783           4 :         poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
    6784           8 :     OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
    6785             : 
    6786           4 :     int nWidth = 0;
    6787           4 :     int nPrecision = 0;
    6788           4 :     OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
    6789           4 :     oNewFieldDefn.SetType(eType);
    6790           4 :     oNewFieldDefn.SetWidth(nWidth);
    6791           4 :     oNewFieldDefn.SetPrecision(nPrecision);
    6792             : 
    6793           4 :     int l_nFlags = 0;
    6794           4 :     if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
    6795           2 :         l_nFlags |= ALTER_TYPE_FLAG;
    6796           4 :     if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
    6797           0 :         poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
    6798           4 :         l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
    6799             : 
    6800           4 :     CSLDestroy(papszTokens);
    6801             : 
    6802           4 :     if (l_nFlags == 0)
    6803           0 :         return OGRERR_NONE;
    6804             : 
    6805           4 :     return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
    6806             : }
    6807             : 
    6808             : //! @endcond
    6809             : 
    6810             : /************************************************************************/
    6811             : /*                             ExecuteSQL()                             */
    6812             : /************************************************************************/
    6813             : 
    6814             : /**
    6815             :  \brief Execute an SQL statement against the data store.
    6816             : 
    6817             :  The result of an SQL query is either NULL for statements that are in error,
    6818             :  or that have no results set, or an OGRLayer pointer representing a results
    6819             :  set from the query.  Note that this OGRLayer is in addition to the layers
    6820             :  in the data store and must be destroyed with
    6821             :  ReleaseResultSet() before the dataset is closed
    6822             :  (destroyed).
    6823             : 
    6824             :  This method is the same as the C function GDALDatasetExecuteSQL() and the
    6825             :  deprecated OGR_DS_ExecuteSQL().
    6826             : 
    6827             :  For more information on the SQL dialect supported internally by OGR
    6828             :  review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
    6829             :  document.  Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
    6830             :  to the underlying RDBMS.
    6831             : 
    6832             :  Starting with OGR 1.10, the <a
    6833             :  href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
    6834             :  also be used.
    6835             : 
    6836             :  In GDAL 1.X, this method used to be in the OGRDataSource class.
    6837             : 
    6838             :  @param pszStatement the SQL statement to execute.
    6839             :  @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
    6840             :  @param pszDialect allows control of the statement dialect. If set to NULL, the
    6841             :  OGR SQL engine will be used, except for RDBMS drivers that will use their
    6842             :  dedicated SQL engine, unless OGRSQL is explicitly passed as the
    6843             :  dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
    6844             : 
    6845             :  @return an OGRLayer containing the results of the query.  Deallocate with
    6846             :  ReleaseResultSet().
    6847             : 
    6848             : */
    6849             : 
    6850        3474 : OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,
    6851             :                                   OGRGeometry *poSpatialFilter,
    6852             :                                   const char *pszDialect)
    6853             : 
    6854             : {
    6855        3474 :     return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
    6856             : }
    6857             : 
    6858             : //! @cond Doxygen_Suppress
    6859             : OGRLayer *
    6860        3482 : GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
    6861             :                         const char *pszDialect,
    6862             :                         swq_select_parse_options *poSelectParseOptions)
    6863             : 
    6864             : {
    6865        3482 :     if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))
    6866             :     {
    6867             : #ifdef SQLITE_ENABLED
    6868         643 :         return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
    6869         643 :                                    pszDialect);
    6870             : #else
    6871             :         CPLError(CE_Failure, CPLE_NotSupported,
    6872             :                  "The SQLite driver needs to be compiled to support the "
    6873             :                  "SQLite SQL dialect");
    6874             :         return nullptr;
    6875             : #endif
    6876             :     }
    6877             : 
    6878        2839 :     if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
    6879          11 :         !EQUAL(pszDialect, "OGRSQL"))
    6880             :     {
    6881           2 :         std::string osDialectList = "'OGRSQL'";
    6882             : #ifdef SQLITE_ENABLED
    6883           1 :         osDialectList += ", 'SQLITE'";
    6884             : #endif
    6885             :         const char *pszDialects =
    6886           1 :             GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);
    6887           1 :         if (pszDialects)
    6888             :         {
    6889             :             const CPLStringList aosTokens(
    6890           0 :                 CSLTokenizeString2(pszDialects, " ", 0));
    6891           0 :             for (int i = 0; i < aosTokens.size(); ++i)
    6892             :             {
    6893           0 :                 if (!EQUAL(aosTokens[i], "OGRSQL") &&
    6894           0 :                     !EQUAL(aosTokens[i], "SQLITE"))
    6895             :                 {
    6896           0 :                     osDialectList += ", '";
    6897           0 :                     osDialectList += aosTokens[i];
    6898           0 :                     osDialectList += "'";
    6899             :                 }
    6900             :             }
    6901             :         }
    6902           1 :         CPLError(CE_Warning, CPLE_NotSupported,
    6903             :                  "Dialect '%s' is unsupported. Only supported dialects are %s. "
    6904             :                  "Defaulting to OGRSQL",
    6905             :                  pszDialect, osDialectList.c_str());
    6906             :     }
    6907             : 
    6908             :     /* -------------------------------------------------------------------- */
    6909             :     /*      Handle CREATE INDEX statements specially.                       */
    6910             :     /* -------------------------------------------------------------------- */
    6911        2839 :     if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))
    6912             :     {
    6913          28 :         ProcessSQLCreateIndex(pszStatement);
    6914          28 :         return nullptr;
    6915             :     }
    6916             : 
    6917             :     /* -------------------------------------------------------------------- */
    6918             :     /*      Handle DROP INDEX statements specially.                         */
    6919             :     /* -------------------------------------------------------------------- */
    6920        2811 :     if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))
    6921             :     {
    6922          10 :         ProcessSQLDropIndex(pszStatement);
    6923          10 :         return nullptr;
    6924             :     }
    6925             : 
    6926             :     /* -------------------------------------------------------------------- */
    6927             :     /*      Handle DROP TABLE statements specially.                         */
    6928             :     /* -------------------------------------------------------------------- */
    6929        2801 :     if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))
    6930             :     {
    6931         500 :         ProcessSQLDropTable(pszStatement);
    6932         500 :         return nullptr;
    6933             :     }
    6934             : 
    6935             :     /* -------------------------------------------------------------------- */
    6936             :     /*      Handle ALTER TABLE statements specially.                        */
    6937             :     /* -------------------------------------------------------------------- */
    6938        2301 :     if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))
    6939             :     {
    6940          11 :         char **papszTokens = CSLTokenizeString(pszStatement);
    6941          11 :         const int nTokens = CSLCount(papszTokens);
    6942          11 :         if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))
    6943             :         {
    6944           2 :             ProcessSQLAlterTableAddColumn(pszStatement);
    6945           2 :             CSLDestroy(papszTokens);
    6946           2 :             return nullptr;
    6947             :         }
    6948           9 :         else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))
    6949             :         {
    6950           2 :             ProcessSQLAlterTableDropColumn(pszStatement);
    6951           2 :             CSLDestroy(papszTokens);
    6952           2 :             return nullptr;
    6953             :         }
    6954           7 :         else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&
    6955           1 :                  EQUAL(papszTokens[4], "TO"))
    6956             :         {
    6957           1 :             const char *pszSrcTableName = papszTokens[2];
    6958           1 :             const char *pszDstTableName = papszTokens[5];
    6959           1 :             auto poSrcLayer = GetLayerByName(pszSrcTableName);
    6960           1 :             if (poSrcLayer)
    6961             :             {
    6962           1 :                 CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));
    6963             :             }
    6964             :             else
    6965             :             {
    6966           0 :                 CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");
    6967             :             }
    6968           1 :             CSLDestroy(papszTokens);
    6969           1 :             return nullptr;
    6970             :         }
    6971           6 :         else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))
    6972             :         {
    6973           2 :             ProcessSQLAlterTableRenameColumn(pszStatement);
    6974           2 :             CSLDestroy(papszTokens);
    6975           2 :             return nullptr;
    6976             :         }
    6977           4 :         else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))
    6978             :         {
    6979           4 :             ProcessSQLAlterTableAlterColumn(pszStatement);
    6980           4 :             CSLDestroy(papszTokens);
    6981           4 :             return nullptr;
    6982             :         }
    6983             :         else
    6984             :         {
    6985           0 :             CPLError(CE_Failure, CPLE_AppDefined,
    6986             :                      "Unsupported ALTER TABLE command : %s", pszStatement);
    6987           0 :             CSLDestroy(papszTokens);
    6988           0 :             return nullptr;
    6989             :         }
    6990             :     }
    6991             : 
    6992             :     /* -------------------------------------------------------------------- */
    6993             :     /*      Preparse the SQL statement.                                     */
    6994             :     /* -------------------------------------------------------------------- */
    6995        2290 :     swq_select *psSelectInfo = new swq_select();
    6996        2290 :     swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
    6997        2290 :     if (poSelectParseOptions != nullptr)
    6998           8 :         poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
    6999        2290 :     if (psSelectInfo->preparse(pszStatement,
    7000        2290 :                                poCustomFuncRegistrar != nullptr) != CE_None)
    7001             :     {
    7002         114 :         delete psSelectInfo;
    7003         114 :         return nullptr;
    7004             :     }
    7005             : 
    7006             :     /* -------------------------------------------------------------------- */
    7007             :     /*      If there is no UNION ALL, build result layer.                   */
    7008             :     /* -------------------------------------------------------------------- */
    7009        2176 :     if (psSelectInfo->poOtherSelect == nullptr)
    7010             :     {
    7011        2171 :         return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
    7012        2171 :                                         pszDialect, poSelectParseOptions);
    7013             :     }
    7014             : 
    7015             :     /* -------------------------------------------------------------------- */
    7016             :     /*      Build result union layer.                                       */
    7017             :     /* -------------------------------------------------------------------- */
    7018           5 :     int nSrcLayers = 0;
    7019           5 :     OGRLayer **papoSrcLayers = nullptr;
    7020             : 
    7021           5 :     do
    7022             :     {
    7023          10 :         swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
    7024          10 :         psSelectInfo->poOtherSelect = nullptr;
    7025             : 
    7026          10 :         OGRLayer *poLayer = BuildLayerFromSelectInfo(
    7027             :             psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
    7028          10 :         if (poLayer == nullptr)
    7029             :         {
    7030             :             // Each source layer owns an independent select info.
    7031           0 :             for (int i = 0; i < nSrcLayers; ++i)
    7032           0 :                 delete papoSrcLayers[i];
    7033           0 :             CPLFree(papoSrcLayers);
    7034             : 
    7035             :             // So we just have to destroy the remaining select info.
    7036           0 :             delete psNextSelectInfo;
    7037             : 
    7038           0 :             return nullptr;
    7039             :         }
    7040             :         else
    7041             :         {
    7042          20 :             papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
    7043          10 :                 papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
    7044          10 :             papoSrcLayers[nSrcLayers] = poLayer;
    7045          10 :             ++nSrcLayers;
    7046             : 
    7047          10 :             psSelectInfo = psNextSelectInfo;
    7048             :         }
    7049          10 :     } while (psSelectInfo != nullptr);
    7050             : 
    7051           5 :     return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
    7052             : }
    7053             : 
    7054             : //! @endcond
    7055             : 
    7056             : /************************************************************************/
    7057             : /*                             AbortSQL()                             */
    7058             : /************************************************************************/
    7059             : 
    7060             : /**
    7061             :  \brief Abort any SQL statement running in the data store.
    7062             : 
    7063             :  This function can be safely called from any thread (pending that the dataset
    7064             :  object is still alive). Driver implementations will make sure that it can be
    7065             :  called in a thread-safe way.
    7066             : 
    7067             :  This might not be implemented by all drivers. At time of writing, only SQLite,
    7068             :  GPKG and PG drivers implement it
    7069             : 
    7070             :  This method is the same as the C method GDALDatasetAbortSQL()
    7071             : 
    7072             :  @since GDAL 3.2.0
    7073             : 
    7074             : 
    7075             : */
    7076             : 
    7077           0 : OGRErr GDALDataset::AbortSQL()
    7078             : {
    7079           0 :     CPLError(CE_Failure, CPLE_NotSupported,
    7080             :              "AbortSQL is not supported for this driver.");
    7081           0 :     return OGRERR_UNSUPPORTED_OPERATION;
    7082             : }
    7083             : 
    7084             : /************************************************************************/
    7085             : /*                        BuildLayerFromSelectInfo()                    */
    7086             : /************************************************************************/
    7087             : 
    7088             : struct GDALSQLParseInfo
    7089             : {
    7090             :     swq_field_list sFieldList;
    7091             :     int nExtraDSCount;
    7092             :     GDALDataset **papoExtraDS;
    7093             :     char *pszWHERE;
    7094             : };
    7095             : 
    7096        2181 : OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
    7097             :     swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
    7098             :     const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
    7099             : {
    7100        4362 :     std::unique_ptr<swq_select> psSelectInfoUnique(psSelectInfo);
    7101             : 
    7102        2181 :     std::unique_ptr<OGRGenSQLResultsLayer> poResults;
    7103             :     GDALSQLParseInfo *psParseInfo =
    7104        2181 :         BuildParseInfo(psSelectInfoUnique.get(), poSelectParseOptions);
    7105             : 
    7106        2181 :     if (psParseInfo)
    7107             :     {
    7108        2147 :         const auto nErrorCounter = CPLGetErrorCounter();
    7109        4294 :         poResults = std::make_unique<OGRGenSQLResultsLayer>(
    7110        2147 :             this, std::move(psSelectInfoUnique), poSpatialFilter,
    7111        4294 :             psParseInfo->pszWHERE, pszDialect);
    7112        2224 :         if (CPLGetErrorCounter() > nErrorCounter &&
    7113          77 :             CPLGetLastErrorType() != CE_None)
    7114          77 :             poResults.reset();
    7115             :     }
    7116             : 
    7117        2181 :     DestroyParseInfo(psParseInfo);
    7118             : 
    7119        4362 :     return poResults.release();
    7120             : }
    7121             : 
    7122             : /************************************************************************/
    7123             : /*                             DestroyParseInfo()                       */
    7124             : /************************************************************************/
    7125             : 
    7126             : //! @cond Doxygen_Suppress
    7127        2249 : void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
    7128             : {
    7129        2249 :     if (psParseInfo == nullptr)
    7130          34 :         return;
    7131             : 
    7132        2215 :     CPLFree(psParseInfo->sFieldList.names);
    7133        2215 :     CPLFree(psParseInfo->sFieldList.types);
    7134        2215 :     CPLFree(psParseInfo->sFieldList.table_ids);
    7135        2215 :     CPLFree(psParseInfo->sFieldList.ids);
    7136             : 
    7137             :     // Release the datasets we have opened with OGROpenShared()
    7138             :     // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
    7139             :     // has taken a reference on them, which it will release in its
    7140             :     // destructor.
    7141        2222 :     for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)
    7142           7 :         GDALClose(psParseInfo->papoExtraDS[iEDS]);
    7143             : 
    7144        2215 :     CPLFree(psParseInfo->papoExtraDS);
    7145        2215 :     CPLFree(psParseInfo->pszWHERE);
    7146        2215 :     CPLFree(psParseInfo);
    7147             : }
    7148             : 
    7149             : /************************************************************************/
    7150             : /*                            BuildParseInfo()                          */
    7151             : /************************************************************************/
    7152             : 
    7153             : GDALSQLParseInfo *
    7154        2215 : GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
    7155             :                             swq_select_parse_options *poSelectParseOptions)
    7156             : {
    7157        2215 :     int nFirstLayerFirstSpecialFieldIndex = 0;
    7158             : 
    7159             :     GDALSQLParseInfo *psParseInfo =
    7160        2215 :         static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
    7161             : 
    7162             :     /* -------------------------------------------------------------------- */
    7163             :     /*      Validate that all the source tables are recognized, count       */
    7164             :     /*      fields.                                                         */
    7165             :     /* -------------------------------------------------------------------- */
    7166        2215 :     int nFieldCount = 0;
    7167             : 
    7168        4499 :     for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
    7169             :     {
    7170        2286 :         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
    7171        2286 :         GDALDataset *poTableDS = this;
    7172             : 
    7173        2286 :         if (psTableDef->data_source != nullptr)
    7174             :         {
    7175           7 :             poTableDS = GDALDataset::FromHandle(
    7176           7 :                 OGROpenShared(psTableDef->data_source, FALSE, nullptr));
    7177           7 :             if (poTableDS == nullptr)
    7178             :             {
    7179           0 :                 if (strlen(CPLGetLastErrorMsg()) == 0)
    7180           0 :                     CPLError(CE_Failure, CPLE_AppDefined,
    7181             :                              "Unable to open secondary datasource "
    7182             :                              "`%s' required by JOIN.",
    7183             :                              psTableDef->data_source);
    7184             : 
    7185           0 :                 DestroyParseInfo(psParseInfo);
    7186           0 :                 return nullptr;
    7187             :             }
    7188             : 
    7189             :             // Keep in an array to release at the end of this function.
    7190          14 :             psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
    7191           7 :                 psParseInfo->papoExtraDS,
    7192           7 :                 sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
    7193           7 :             psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
    7194             :         }
    7195             : 
    7196             :         OGRLayer *poSrcLayer =
    7197        2286 :             poTableDS->GetLayerByName(psTableDef->table_name);
    7198             : 
    7199        2286 :         if (poSrcLayer == nullptr)
    7200             :         {
    7201           2 :             CPLError(CE_Failure, CPLE_AppDefined,
    7202             :                      "SELECT from table %s failed, no such table/featureclass.",
    7203             :                      psTableDef->table_name);
    7204             : 
    7205           2 :             DestroyParseInfo(psParseInfo);
    7206           2 :             return nullptr;
    7207             :         }
    7208             : 
    7209        2284 :         nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
    7210        2284 :         if (iTable == 0 ||
    7211          34 :             (poSelectParseOptions &&
    7212          34 :              poSelectParseOptions->bAddSecondaryTablesGeometryFields))
    7213        2247 :             nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
    7214             : 
    7215        2284 :         const char *pszFID = poSrcLayer->GetFIDColumn();
    7216        2894 :         if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
    7217         610 :             poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
    7218         560 :             nFieldCount++;
    7219             :     }
    7220             : 
    7221             :     /* -------------------------------------------------------------------- */
    7222             :     /*      Build the field list for all indicated tables.                  */
    7223             :     /* -------------------------------------------------------------------- */
    7224             : 
    7225        2213 :     psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
    7226        2213 :     psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
    7227             : 
    7228        2213 :     psParseInfo->sFieldList.count = 0;
    7229        2213 :     psParseInfo->sFieldList.names = static_cast<char **>(
    7230        2213 :         CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
    7231        4426 :     psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
    7232        2213 :         sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
    7233        2213 :     psParseInfo->sFieldList.table_ids = static_cast<int *>(
    7234        2213 :         CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
    7235        2213 :     psParseInfo->sFieldList.ids = static_cast<int *>(
    7236        2213 :         CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
    7237             : 
    7238        2213 :     bool bIsFID64 = false;
    7239        4497 :     for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
    7240             :     {
    7241        2284 :         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
    7242        2284 :         GDALDataset *poTableDS = this;
    7243             : 
    7244        2284 :         if (psTableDef->data_source != nullptr)
    7245             :         {
    7246           7 :             poTableDS = GDALDataset::FromHandle(
    7247           7 :                 OGROpenShared(psTableDef->data_source, FALSE, nullptr));
    7248           7 :             CPLAssert(poTableDS != nullptr);
    7249           7 :             poTableDS->Dereference();
    7250             :         }
    7251             : 
    7252             :         OGRLayer *poSrcLayer =
    7253        2284 :             poTableDS->GetLayerByName(psTableDef->table_name);
    7254             : 
    7255        2284 :         for (int iField = 0;
    7256       18475 :              iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)
    7257             :         {
    7258             :             OGRFieldDefn *poFDefn =
    7259       16191 :                 poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
    7260       16191 :             const int iOutField = psParseInfo->sFieldList.count++;
    7261       32382 :             psParseInfo->sFieldList.names[iOutField] =
    7262       16191 :                 const_cast<char *>(poFDefn->GetNameRef());
    7263       16191 :             if (poFDefn->GetType() == OFTInteger)
    7264             :             {
    7265        4195 :                 if (poFDefn->GetSubType() == OFSTBoolean)
    7266         160 :                     psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
    7267             :                 else
    7268        4035 :                     psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
    7269             :             }
    7270       11996 :             else if (poFDefn->GetType() == OFTInteger64)
    7271             :             {
    7272         707 :                 if (poFDefn->GetSubType() == OFSTBoolean)
    7273           0 :                     psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
    7274             :                 else
    7275         707 :                     psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
    7276             :             }
    7277       11289 :             else if (poFDefn->GetType() == OFTReal)
    7278        2655 :                 psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
    7279        8634 :             else if (poFDefn->GetType() == OFTString)
    7280        5580 :                 psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
    7281        3054 :             else if (poFDefn->GetType() == OFTTime)
    7282          83 :                 psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
    7283        2971 :             else if (poFDefn->GetType() == OFTDate)
    7284         143 :                 psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
    7285        2828 :             else if (poFDefn->GetType() == OFTDateTime)
    7286         939 :                 psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
    7287             :             else
    7288        1889 :                 psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
    7289             : 
    7290       16191 :             psParseInfo->sFieldList.table_ids[iOutField] = iTable;
    7291       16191 :             psParseInfo->sFieldList.ids[iOutField] = iField;
    7292             :         }
    7293             : 
    7294        2284 :         if (iTable == 0)
    7295             :         {
    7296        2213 :             nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
    7297             :         }
    7298             : 
    7299        2284 :         if (iTable == 0 ||
    7300          34 :             (poSelectParseOptions &&
    7301          34 :              poSelectParseOptions->bAddSecondaryTablesGeometryFields))
    7302             :         {
    7303             : 
    7304        2247 :             for (int iField = 0;
    7305        4144 :                  iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
    7306             :                  iField++)
    7307             :             {
    7308             :                 OGRGeomFieldDefn *poFDefn =
    7309        1897 :                     poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
    7310        1897 :                 const int iOutField = psParseInfo->sFieldList.count++;
    7311        3794 :                 psParseInfo->sFieldList.names[iOutField] =
    7312        1897 :                     const_cast<char *>(poFDefn->GetNameRef());
    7313        1897 :                 if (*psParseInfo->sFieldList.names[iOutField] == '\0')
    7314        1084 :                     psParseInfo->sFieldList.names[iOutField] =
    7315             :                         const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
    7316        1897 :                 psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
    7317             : 
    7318        1897 :                 psParseInfo->sFieldList.table_ids[iOutField] = iTable;
    7319        1897 :                 psParseInfo->sFieldList.ids[iOutField] =
    7320        1897 :                     GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
    7321             :                         poSrcLayer->GetLayerDefn(), iField);
    7322             :             }
    7323             :         }
    7324             : 
    7325        2285 :         if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
    7326           1 :             EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
    7327             :         {
    7328           1 :             bIsFID64 = true;
    7329             :         }
    7330             :     }
    7331             : 
    7332             :     /* -------------------------------------------------------------------- */
    7333             :     /*      Expand '*' in 'SELECT *' now before we add the pseudo fields    */
    7334             :     /* -------------------------------------------------------------------- */
    7335        2213 :     const bool bAlwaysPrefixWithTableName =
    7336        2255 :         poSelectParseOptions &&
    7337          42 :         poSelectParseOptions->bAlwaysPrefixWithTableName;
    7338        2213 :     if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
    7339        2213 :                                       bAlwaysPrefixWithTableName) != CE_None)
    7340             :     {
    7341           2 :         DestroyParseInfo(psParseInfo);
    7342           2 :         return nullptr;
    7343             :     }
    7344             : 
    7345       13266 :     for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
    7346             :     {
    7347       11055 :         psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
    7348       11055 :             const_cast<char *>(SpecialFieldNames[iField]);
    7349       11055 :         psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
    7350       11055 :             (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
    7351             :                                             : SpecialFieldTypes[iField];
    7352       11055 :         psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
    7353       11055 :         psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
    7354       11055 :             nFirstLayerFirstSpecialFieldIndex + iField;
    7355       11055 :         psParseInfo->sFieldList.count++;
    7356             :     }
    7357             : 
    7358             :     /* In the case a layer has an explicit FID column name, then add it */
    7359             :     /* so it can be selected */
    7360        4493 :     for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
    7361             :     {
    7362        2282 :         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
    7363        2282 :         GDALDataset *poTableDS = this;
    7364             : 
    7365        2282 :         if (psTableDef->data_source != nullptr)
    7366             :         {
    7367           7 :             poTableDS = GDALDataset::FromHandle(
    7368           7 :                 OGROpenShared(psTableDef->data_source, FALSE, nullptr));
    7369           7 :             CPLAssert(poTableDS != nullptr);
    7370           7 :             poTableDS->Dereference();
    7371             :         }
    7372             : 
    7373             :         OGRLayer *poSrcLayer =
    7374        2282 :             poTableDS->GetLayerByName(psTableDef->table_name);
    7375             : 
    7376        2282 :         const char *pszFID = poSrcLayer->GetFIDColumn();
    7377        2892 :         if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
    7378         610 :             poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
    7379             :         {
    7380         560 :             const int iOutField = psParseInfo->sFieldList.count++;
    7381         560 :             psParseInfo->sFieldList.names[iOutField] =
    7382             :                 const_cast<char *>(pszFID);
    7383         560 :             if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
    7384           0 :                 EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
    7385             :             {
    7386           0 :                 psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
    7387             :             }
    7388             :             else
    7389             :             {
    7390         560 :                 psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
    7391             :             }
    7392         560 :             psParseInfo->sFieldList.table_ids[iOutField] = iTable;
    7393        1120 :             psParseInfo->sFieldList.ids[iOutField] =
    7394         560 :                 poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
    7395             :         }
    7396             :     }
    7397             : 
    7398             :     /* -------------------------------------------------------------------- */
    7399             :     /*      Finish the parse operation.                                     */
    7400             :     /* -------------------------------------------------------------------- */
    7401        2211 :     if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
    7402             :         CE_None)
    7403             :     {
    7404          30 :         DestroyParseInfo(psParseInfo);
    7405          30 :         return nullptr;
    7406             :     }
    7407             : 
    7408             :     /* -------------------------------------------------------------------- */
    7409             :     /*      Extract the WHERE expression to use separately.                 */
    7410             :     /* -------------------------------------------------------------------- */
    7411        2181 :     if (psSelectInfo->where_expr != nullptr)
    7412             :     {
    7413         952 :         psParseInfo->pszWHERE =
    7414         952 :             psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
    7415             :         // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
    7416             :     }
    7417             : 
    7418        2181 :     return psParseInfo;
    7419             : }
    7420             : 
    7421             : //! @endcond
    7422             : 
    7423             : /************************************************************************/
    7424             : /*                          ReleaseResultSet()                          */
    7425             : /************************************************************************/
    7426             : 
    7427             : /**
    7428             :  \brief Release results of ExecuteSQL().
    7429             : 
    7430             :  This method should only be used to deallocate OGRLayers resulting from
    7431             :  an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
    7432             :  results set before destroying the GDALDataset may cause errors.
    7433             : 
    7434             :  This method is the same as the C function GDALDatasetReleaseResultSet() and the
    7435             :  deprecated OGR_DS_ReleaseResultSet().
    7436             : 
    7437             :  In GDAL 1.X, this method used to be in the OGRDataSource class.
    7438             : 
    7439             :  @param poResultsSet the result of a previous ExecuteSQL() call.
    7440             : */
    7441             : 
    7442        2094 : void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)
    7443             : 
    7444             : {
    7445        2094 :     delete poResultsSet;
    7446        2094 : }
    7447             : 
    7448             : /************************************************************************/
    7449             : /*                            GetStyleTable()                           */
    7450             : /************************************************************************/
    7451             : 
    7452             : /**
    7453             :  \brief Returns dataset style table.
    7454             : 
    7455             :  This method is the same as the C function GDALDatasetGetStyleTable() and the
    7456             :  deprecated OGR_DS_GetStyleTable().
    7457             : 
    7458             :  In GDAL 1.X, this method used to be in the OGRDataSource class.
    7459             : 
    7460             :  @return pointer to a style table which should not be modified or freed by the
    7461             :  caller.
    7462             : */
    7463             : 
    7464         682 : OGRStyleTable *GDALDataset::GetStyleTable()
    7465             : {
    7466         682 :     return m_poStyleTable;
    7467             : }
    7468             : 
    7469             : /************************************************************************/
    7470             : /*                         SetStyleTableDirectly()                      */
    7471             : /************************************************************************/
    7472             : 
    7473             : /**
    7474             :  \brief Set dataset style table.
    7475             : 
    7476             :  This method operate exactly as SetStyleTable() except that it
    7477             :  assumes ownership of the passed table.
    7478             : 
    7479             :  This method is the same as the C function GDALDatasetSetStyleTableDirectly()
    7480             :  and the deprecated OGR_DS_SetStyleTableDirectly().
    7481             : 
    7482             :  In GDAL 1.X, this method used to be in the OGRDataSource class.
    7483             : 
    7484             :  @param poStyleTable pointer to style table to set
    7485             : 
    7486             : */
    7487           0 : void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
    7488             : {
    7489           0 :     if (m_poStyleTable)
    7490           0 :         delete m_poStyleTable;
    7491           0 :     m_poStyleTable = poStyleTable;
    7492           0 : }
    7493             : 
    7494             : /************************************************************************/
    7495             : /*                            SetStyleTable()                           */
    7496             : /************************************************************************/
    7497             : 
    7498             : /**
    7499             :  \brief Set dataset style table.
    7500             : 
    7501             :  This method operate exactly as SetStyleTableDirectly() except
    7502             :  that it does not assume ownership of the passed table.
    7503             : 
    7504             :  This method is the same as the C function GDALDatasetSetStyleTable() and the
    7505             :  deprecated OGR_DS_SetStyleTable().
    7506             : 
    7507             :  In GDAL 1.X, this method used to be in the OGRDataSource class.
    7508             : 
    7509             :  @param poStyleTable pointer to style table to set
    7510             : 
    7511             : */
    7512             : 
    7513         678 : void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
    7514             : {
    7515         678 :     if (m_poStyleTable)
    7516           0 :         delete m_poStyleTable;
    7517         678 :     if (poStyleTable)
    7518           1 :         m_poStyleTable = poStyleTable->Clone();
    7519         678 : }
    7520             : 
    7521             : /************************************************************************/
    7522             : /*                         IsGenericSQLDialect()                        */
    7523             : /************************************************************************/
    7524             : 
    7525             : //! @cond Doxygen_Suppress
    7526        1737 : int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
    7527             : {
    7528        3160 :     return pszDialect != nullptr &&
    7529        3160 :            (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
    7530             : }
    7531             : 
    7532             : //! @endcond
    7533             : 
    7534             : /************************************************************************/
    7535             : /*                            GetLayerCount()                           */
    7536             : /************************************************************************/
    7537             : 
    7538             : /**
    7539             :  \brief Get the number of layers in this dataset.
    7540             : 
    7541             :  This method is the same as the C function GDALDatasetGetLayerCount(),
    7542             :  and the deprecated OGR_DS_GetLayerCount().
    7543             : 
    7544             :  In GDAL 1.X, this method used to be in the OGRDataSource class.
    7545             : 
    7546             :  @return layer count.
    7547             : */
    7548             : 
    7549       85868 : int GDALDataset::GetLayerCount()
    7550             : {
    7551       85868 :     return 0;
    7552             : }
    7553             : 
    7554             : /************************************************************************/
    7555             : /*                                GetLayer()                            */
    7556             : /************************************************************************/
    7557             : 
    7558             : /**
    7559             :  \fn GDALDataset::GetLayer(int)
    7560             :  \brief Fetch a layer by index.
    7561             : 
    7562             :  The returned layer remains owned by the
    7563             :  GDALDataset and should not be deleted by the application.
    7564             : 
    7565             :  See GetLayers() for a C++ iterator version of this method.
    7566             : 
    7567             :  This method is the same as the C function GDALDatasetGetLayer() and the
    7568             :  deprecated OGR_DS_GetLayer().
    7569             : 
    7570             :  In GDAL 1.X, this method used to be in the OGRDataSource class.
    7571             : 
    7572             :  @param iLayer a layer number between 0 and GetLayerCount()-1.
    7573             : 
    7574             :  @return the layer, or NULL if iLayer is out of range or an error occurs.
    7575             : 
    7576             :  @see GetLayers()
    7577             : */
    7578             : 
    7579           0 : OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer)
    7580             : {
    7581           0 :     return nullptr;
    7582             : }
    7583             : 
    7584             : /************************************************************************/
    7585             : /*                                IsLayerPrivate()                      */
    7586             : /************************************************************************/
    7587             : 
    7588             : /**
    7589             :  \fn GDALDataset::IsLayerPrivate(int)
    7590             :  \brief Returns true if the layer at the specified index is deemed a private or
    7591             :  system table, or an internal detail only.
    7592             : 
    7593             :  This method is the same as the C function GDALDatasetIsLayerPrivate().
    7594             : 
    7595             :  @param iLayer a layer number between 0 and GetLayerCount()-1.
    7596             : 
    7597             :  @return true if the layer is a private or system table.
    7598             : 
    7599             :  @since GDAL 3.4
    7600             : */
    7601             : 
    7602         684 : bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const
    7603             : {
    7604         684 :     return false;
    7605             : }
    7606             : 
    7607             : /************************************************************************/
    7608             : /*                           ResetReading()                             */
    7609             : /************************************************************************/
    7610             : 
    7611             : /**
    7612             :  \brief Reset feature reading to start on the first feature.
    7613             : 
    7614             :  This affects GetNextFeature().
    7615             : 
    7616             :  Depending on drivers, this may also have the side effect of calling
    7617             :  OGRLayer::ResetReading() on the layers of this dataset.
    7618             : 
    7619             :  This method is the same as the C function GDALDatasetResetReading().
    7620             : 
    7621             :  @since GDAL 2.2
    7622             : */
    7623           5 : void GDALDataset::ResetReading()
    7624             : {
    7625           5 :     if (!m_poPrivate)
    7626           0 :         return;
    7627           5 :     m_poPrivate->nCurrentLayerIdx = 0;
    7628           5 :     m_poPrivate->nLayerCount = -1;
    7629           5 :     m_poPrivate->poCurrentLayer = nullptr;
    7630           5 :     m_poPrivate->nFeatureReadInLayer = 0;
    7631           5 :     m_poPrivate->nFeatureReadInDataset = 0;
    7632           5 :     m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
    7633           5 :     m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
    7634             : }
    7635             : 
    7636             : /************************************************************************/
    7637             : /*                         GDALDatasetResetReading()                    */
    7638             : /************************************************************************/
    7639             : 
    7640             : /**
    7641             :  \brief Reset feature reading to start on the first feature.
    7642             : 
    7643             :  This affects GDALDatasetGetNextFeature().
    7644             : 
    7645             :  Depending on drivers, this may also have the side effect of calling
    7646             :  OGR_L_ResetReading() on the layers of this dataset.
    7647             : 
    7648             :  This method is the same as the C++ method GDALDataset::ResetReading()
    7649             : 
    7650             :  @param hDS dataset handle
    7651             :  @since GDAL 2.2
    7652             : */
    7653           8 : void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)
    7654             : {
    7655           8 :     VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
    7656             : 
    7657           8 :     return GDALDataset::FromHandle(hDS)->ResetReading();
    7658             : }
    7659             : 
    7660             : /************************************************************************/
    7661             : /*                          GetNextFeature()                            */
    7662             : /************************************************************************/
    7663             : 
    7664             : /**
    7665             :  \brief Fetch the next available feature from this dataset.
    7666             : 
    7667             :  This method is intended for the few drivers where OGRLayer::GetNextFeature()
    7668             :  is not efficient, but in general OGRLayer::GetNextFeature() is a more
    7669             :  natural API.
    7670             : 
    7671             :  See GetFeatures() for a C++ iterator version of this method.
    7672             : 
    7673             :  The returned feature becomes the responsibility of the caller to
    7674             :  delete with OGRFeature::DestroyFeature().
    7675             : 
    7676             :  Depending on the driver, this method may return features from layers in a
    7677             :  non sequential way. This is what may happen when the
    7678             :  ODsCRandomLayerRead capability is declared (for example for the
    7679             :  OSM and GMLAS drivers). When datasets declare this capability, it is strongly
    7680             :  advised to use GDALDataset::GetNextFeature() instead of
    7681             :  OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
    7682             :  implementation.
    7683             : 
    7684             :  The default implementation, used by most drivers, will
    7685             :  however iterate over each layer, and then over each feature within this
    7686             :  layer.
    7687             : 
    7688             :  This method takes into account spatial and attribute filters set on layers that
    7689             :  will be iterated upon.
    7690             : 
    7691             :  The ResetReading() method can be used to start at the beginning again.
    7692             : 
    7693             :  Depending on drivers, this may also have the side effect of calling
    7694             :  OGRLayer::GetNextFeature() on the layers of this dataset.
    7695             : 
    7696             :  This method is the same as the C function GDALDatasetGetNextFeature().
    7697             : 
    7698             :  @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
    7699             :                           layer to which the object belongs to, or NULL.
    7700             :                           It is possible that the output of *ppoBelongingLayer
    7701             :                           to be NULL despite the feature not being NULL.
    7702             :  @param pdfProgressPct    a pointer to a double variable to receive the
    7703             :                           percentage progress (in [0,1] range), or NULL.
    7704             :                           On return, the pointed value might be negative if
    7705             :                           determining the progress is not possible.
    7706             :  @param pfnProgress       a progress callback to report progress (for
    7707             :                           GetNextFeature() calls that might have a long
    7708             :                           duration) and offer cancellation possibility, or NULL.
    7709             :  @param pProgressData     user data provided to pfnProgress, or NULL
    7710             :  @return a feature, or NULL if no more features are available.
    7711             :  @since GDAL 2.2
    7712             :  @see GetFeatures()
    7713             : */
    7714             : 
    7715          47 : OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,
    7716             :                                         double *pdfProgressPct,
    7717             :                                         GDALProgressFunc pfnProgress,
    7718             :                                         void *pProgressData)
    7719             : {
    7720          47 :     if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)
    7721             :     {
    7722           2 :         if (ppoBelongingLayer != nullptr)
    7723           2 :             *ppoBelongingLayer = nullptr;
    7724           2 :         if (pdfProgressPct != nullptr)
    7725           1 :             *pdfProgressPct = 1.0;
    7726           2 :         if (pfnProgress != nullptr)
    7727           0 :             pfnProgress(1.0, "", pProgressData);
    7728           2 :         return nullptr;
    7729             :     }
    7730             : 
    7731          45 :     if (m_poPrivate->poCurrentLayer == nullptr &&
    7732           6 :         (pdfProgressPct != nullptr || pfnProgress != nullptr))
    7733             :     {
    7734           1 :         if (m_poPrivate->nLayerCount < 0)
    7735             :         {
    7736           1 :             m_poPrivate->nLayerCount = GetLayerCount();
    7737             :         }
    7738             : 
    7739           1 :         if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)
    7740             :         {
    7741           1 :             m_poPrivate->nTotalFeatures = 0;
    7742           5 :             for (int i = 0; i < m_poPrivate->nLayerCount; i++)
    7743             :             {
    7744           4 :                 OGRLayer *poLayer = GetLayer(i);
    7745           8 :                 if (poLayer == nullptr ||
    7746           4 :                     !poLayer->TestCapability(OLCFastFeatureCount))
    7747             :                 {
    7748           0 :                     m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
    7749           0 :                     break;
    7750             :                 }
    7751           4 :                 GIntBig nCount = poLayer->GetFeatureCount(FALSE);
    7752           4 :                 if (nCount < 0)
    7753             :                 {
    7754           0 :                     m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
    7755           0 :                     break;
    7756             :                 }
    7757           4 :                 m_poPrivate->nTotalFeatures += nCount;
    7758             :             }
    7759             :         }
    7760             :     }
    7761             : 
    7762             :     while (true)
    7763             :     {
    7764          56 :         if (m_poPrivate->poCurrentLayer == nullptr)
    7765             :         {
    7766          36 :             m_poPrivate->poCurrentLayer =
    7767          18 :                 GetLayer(m_poPrivate->nCurrentLayerIdx);
    7768          18 :             if (m_poPrivate->poCurrentLayer == nullptr)
    7769             :             {
    7770           5 :                 m_poPrivate->nCurrentLayerIdx = -1;
    7771           5 :                 if (ppoBelongingLayer != nullptr)
    7772           5 :                     *ppoBelongingLayer = nullptr;
    7773           5 :                 if (pdfProgressPct != nullptr)
    7774           1 :                     *pdfProgressPct = 1.0;
    7775           5 :                 return nullptr;
    7776             :             }
    7777          13 :             m_poPrivate->poCurrentLayer->ResetReading();
    7778          13 :             m_poPrivate->nFeatureReadInLayer = 0;
    7779          13 :             if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)
    7780             :             {
    7781           0 :                 if (m_poPrivate->poCurrentLayer->TestCapability(
    7782           0 :                         OLCFastFeatureCount))
    7783           0 :                     m_poPrivate->nTotalFeaturesInLayer =
    7784           0 :                         m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
    7785             :                 else
    7786           0 :                     m_poPrivate->nTotalFeaturesInLayer = 0;
    7787             :             }
    7788             :         }
    7789          51 :         OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
    7790          51 :         if (poFeature == nullptr)
    7791             :         {
    7792          11 :             m_poPrivate->nCurrentLayerIdx++;
    7793          11 :             m_poPrivate->poCurrentLayer = nullptr;
    7794          11 :             continue;
    7795             :         }
    7796             : 
    7797          40 :         m_poPrivate->nFeatureReadInLayer++;
    7798          40 :         m_poPrivate->nFeatureReadInDataset++;
    7799          40 :         if (pdfProgressPct != nullptr || pfnProgress != nullptr)
    7800             :         {
    7801           4 :             double dfPct = 0.0;
    7802           4 :             if (m_poPrivate->nTotalFeatures > 0)
    7803             :             {
    7804           4 :                 dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
    7805           4 :                         m_poPrivate->nTotalFeatures;
    7806             :             }
    7807             :             else
    7808             :             {
    7809           0 :                 dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /
    7810           0 :                         m_poPrivate->nLayerCount;
    7811           0 :                 if (m_poPrivate->nTotalFeaturesInLayer > 0)
    7812             :                 {
    7813           0 :                     dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
    7814           0 :                              m_poPrivate->nTotalFeaturesInLayer /
    7815           0 :                              m_poPrivate->nLayerCount;
    7816             :                 }
    7817             :             }
    7818           4 :             if (pdfProgressPct)
    7819           4 :                 *pdfProgressPct = dfPct;
    7820           4 :             if (pfnProgress)
    7821           0 :                 pfnProgress(dfPct, "", nullptr);
    7822             :         }
    7823             : 
    7824          40 :         if (ppoBelongingLayer != nullptr)
    7825          40 :             *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
    7826          40 :         return poFeature;
    7827          11 :     }
    7828             : }
    7829             : 
    7830             : /************************************************************************/
    7831             : /*                     GDALDatasetGetNextFeature()                      */
    7832             : /************************************************************************/
    7833             : /**
    7834             :  \brief Fetch the next available feature from this dataset.
    7835             : 
    7836             :  This method is intended for the few drivers where OGR_L_GetNextFeature()
    7837             :  is not efficient, but in general OGR_L_GetNextFeature() is a more
    7838             :  natural API.
    7839             : 
    7840             :  The returned feature becomes the responsibility of the caller to
    7841             :  delete with OGRFeature::DestroyFeature().
    7842             : 
    7843             :  Depending on the driver, this method may return features from layers in a
    7844             :  non sequential way. This is what may happen when the
    7845             :  ODsCRandomLayerRead capability is declared (for example for the
    7846             :  OSM and GMLAS drivers). When datasets declare this capability, it is strongly
    7847             :  advised to use GDALDataset::GetNextFeature() instead of
    7848             :  OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
    7849             :  implementation.
    7850             : 
    7851             :  The default implementation, used by most drivers, will
    7852             :  however iterate over each layer, and then over each feature within this
    7853             :  layer.
    7854             : 
    7855             :  This method takes into account spatial and attribute filters set on layers that
    7856             :  will be iterated upon.
    7857             : 
    7858             :  The ResetReading() method can be used to start at the beginning again.
    7859             : 
    7860             :  Depending on drivers, this may also have the side effect of calling
    7861             :  OGRLayer::GetNextFeature() on the layers of this dataset.
    7862             : 
    7863             :  This method is the same as the C++ method GDALDataset::GetNextFeature()
    7864             : 
    7865             :  @param hDS               dataset handle.
    7866             :  @param phBelongingLayer  a pointer to a OGRLayer* variable to receive the
    7867             :                           layer to which the object belongs to, or NULL.
    7868             :                           It is possible that the output of *ppoBelongingLayer
    7869             :                           to be NULL despite the feature not being NULL.
    7870             :  @param pdfProgressPct    a pointer to a double variable to receive the
    7871             :                           percentage progress (in [0,1] range), or NULL.
    7872             :                           On return, the pointed value might be negative if
    7873             :                           determining the progress is not possible.
    7874             :  @param pfnProgress       a progress callback to report progress (for
    7875             :                           GetNextFeature() calls that might have a long
    7876             :                           duration) and offer cancellation possibility, or NULL
    7877             :  @param pProgressData     user data provided to pfnProgress, or NULL
    7878             :  @return a feature, or NULL if no more features are available.
    7879             :  @since GDAL 2.2
    7880             : */
    7881        1833 : OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,
    7882             :                                               OGRLayerH *phBelongingLayer,
    7883             :                                               double *pdfProgressPct,
    7884             :                                               GDALProgressFunc pfnProgress,
    7885             :                                               void *pProgressData)
    7886             : {
    7887        1833 :     VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
    7888             : 
    7889        3666 :     return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(
    7890             :         reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
    7891        3666 :         pfnProgress, pProgressData));
    7892             : }
    7893             : 
    7894             : /************************************************************************/
    7895             : /*                            TestCapability()                          */
    7896             : /************************************************************************/
    7897             : 
    7898             : /**
    7899             :  \fn GDALDataset::TestCapability( const char * pszCap )
    7900             :  \brief Test if capability is available.
    7901             : 
    7902             :  One of the following dataset capability names can be passed into this
    7903             :  method, and a TRUE or FALSE value will be returned indicating whether or not
    7904             :  the capability is available for this object.
    7905             : 
    7906             :  <ul>
    7907             :   <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
    7908             :   <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
    7909             :           layers.<p>
    7910             :   <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
    7911             :           datasource support CreateGeomField() just after layer creation.<p>
    7912             :   <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
    7913             :           geometries.<p>
    7914             :   <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
    7915             :           transactions.<p>
    7916             :   <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
    7917             :           transactions through emulation.<p>
    7918             :   <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
    7919             :           GetNextFeature() implementation, potentially returning features from
    7920             :           layers in a non sequential way.<p>
    7921             :   <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
    7922             :          CreateFeature() on layers in a non sequential way.<p>
    7923             :  </ul>
    7924             : 
    7925             :  The \#define macro forms of the capability names should be used in preference
    7926             :  to the strings themselves to avoid misspelling.
    7927             : 
    7928             :  This method is the same as the C function GDALDatasetTestCapability() and the
    7929             :  deprecated OGR_DS_TestCapability().
    7930             : 
    7931             :  In GDAL 1.X, this method used to be in the OGRDataSource class.
    7932             : 
    7933             :  @param pszCap the capability to test.
    7934             : 
    7935             :  @return TRUE if capability available otherwise FALSE.
    7936             : */
    7937             : 
    7938         204 : int GDALDataset::TestCapability(CPL_UNUSED const char *pszCap)
    7939             : {
    7940         204 :     return FALSE;
    7941             : }
    7942             : 
    7943             : /************************************************************************/
    7944             : /*                     GDALDatasetTestCapability()                      */
    7945             : /************************************************************************/
    7946             : 
    7947             : /**
    7948             :  \brief Test if capability is available.
    7949             : 
    7950             :  One of the following dataset capability names can be passed into this
    7951             :  function, and a TRUE or FALSE value will be returned indicating whether or not
    7952             :  the capability is available for this object.
    7953             : 
    7954             :  <ul>
    7955             :   <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
    7956             :   <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
    7957             :           layers.<p>
    7958             :   <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
    7959             :           datasource support CreateGeomField() just after layer creation.<p>
    7960             :   <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
    7961             :           geometries.<p>
    7962             :   <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
    7963             :           transactions.<p>
    7964             :   <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
    7965             :           transactions through emulation.<p>
    7966             :   <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
    7967             :           GetNextFeature() implementation, potentially returning features from
    7968             :           layers in a non sequential way.<p>
    7969             :   <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
    7970             :           CreateFeature() on layers in a non sequential way.<p>
    7971             :  </ul>
    7972             : 
    7973             :  The \#define macro forms of the capability names should be used in preference
    7974             :  to the strings themselves to avoid misspelling.
    7975             : 
    7976             :  This function is the same as the C++ method GDALDataset::TestCapability()
    7977             : 
    7978             :  @since GDAL 2.0
    7979             : 
    7980             :  @param hDS the dataset handle.
    7981             :  @param pszCap the capability to test.
    7982             : 
    7983             :  @return TRUE if capability available otherwise FALSE.
    7984             : */
    7985         115 : int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)
    7986             : 
    7987             : {
    7988         115 :     VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
    7989         115 :     VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
    7990             : 
    7991         115 :     return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
    7992             : }
    7993             : 
    7994             : /************************************************************************/
    7995             : /*                           StartTransaction()                         */
    7996             : /************************************************************************/
    7997             : 
    7998             : /**
    7999             :  \fn GDALDataset::StartTransaction(int)
    8000             :  \brief For datasources which support transactions, StartTransaction creates a
    8001             : `transaction.
    8002             : 
    8003             :  If starting the transaction fails, will return
    8004             :  OGRERR_FAILURE. Datasources which do not support transactions will
    8005             :  always return OGRERR_UNSUPPORTED_OPERATION.
    8006             : 
    8007             :  Nested transactions are not supported.
    8008             : 
    8009             :  All changes done after the start of the transaction are definitely applied in
    8010             :  the datasource if CommitTransaction() is called. They may be canceled by
    8011             :  calling RollbackTransaction() instead.
    8012             : 
    8013             :  At the time of writing, transactions only apply on vector layers.
    8014             : 
    8015             :  Datasets that support transactions will advertise the ODsCTransactions
    8016             :  capability.  Use of transactions at dataset level is generally preferred to
    8017             :  transactions at layer level, whose scope is rarely limited to the layer from
    8018             :  which it was started.
    8019             : 
    8020             :  In case StartTransaction() fails, neither CommitTransaction() or
    8021             :  RollbackTransaction() should be called.
    8022             : 
    8023             :  If an error occurs after a successful StartTransaction(), the whole transaction
    8024             :  may or may not be implicitly canceled, depending on drivers. (e.g.  the PG
    8025             :  driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
    8026             :  an explicit call to RollbackTransaction() should be done to keep things
    8027             :  balanced.
    8028             : 
    8029             :  By default, when bForce is set to FALSE, only "efficient" transactions will be
    8030             :  attempted. Some drivers may offer an emulation of transactions, but sometimes
    8031             :  with significant overhead, in which case the user must explicitly allow for
    8032             :  such an emulation by setting bForce to TRUE. Drivers that offer emulated
    8033             :  transactions should advertise the ODsCEmulatedTransactions capability (and not
    8034             :  ODsCTransactions).
    8035             : 
    8036             :  This function is the same as the C function GDALDatasetStartTransaction().
    8037             : 
    8038             :  @param bForce can be set to TRUE if an emulation, possibly slow, of a
    8039             :  transaction
    8040             :                mechanism is acceptable.
    8041             : 
    8042             :  @return OGRERR_NONE on success.
    8043             :  @since GDAL 2.0
    8044             : */
    8045             : 
    8046          37 : OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
    8047             : {
    8048          37 :     return OGRERR_UNSUPPORTED_OPERATION;
    8049             : }
    8050             : 
    8051             : /************************************************************************/
    8052             : /*                      GDALDatasetStartTransaction()                   */
    8053             : /************************************************************************/
    8054             : 
    8055             : /**
    8056             :  \brief For datasources which support transactions, StartTransaction creates a
    8057             :  transaction.
    8058             : 
    8059             :  If starting the transaction fails, will return
    8060             :  OGRERR_FAILURE. Datasources which do not support transactions will
    8061             :  always return OGRERR_UNSUPPORTED_OPERATION.
    8062             : 
    8063             :  Nested transactions are not supported.
    8064             : 
    8065             :  All changes done after the start of the transaction are definitely applied in
    8066             :  the datasource if CommitTransaction() is called. They may be canceled by
    8067             :  calling RollbackTransaction() instead.
    8068             : 
    8069             :  At the time of writing, transactions only apply on vector layers.
    8070             : 
    8071             :  Datasets that support transactions will advertise the ODsCTransactions
    8072             :  capability.
    8073             :  Use of transactions at dataset level is generally preferred to transactions at
    8074             :  layer level, whose scope is rarely limited to the layer from which it was
    8075             :  started.
    8076             : 
    8077             :  In case StartTransaction() fails, neither CommitTransaction() or
    8078             :  RollbackTransaction() should be called.
    8079             : 
    8080             :  If an error occurs after a successful StartTransaction(), the whole
    8081             :  transaction may or may not be implicitly canceled, depending on drivers. (e.g.
    8082             :  the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
    8083             :  error, an explicit call to RollbackTransaction() should be done to keep things
    8084             :  balanced.
    8085             : 
    8086             :  By default, when bForce is set to FALSE, only "efficient" transactions will be
    8087             :  attempted. Some drivers may offer an emulation of transactions, but sometimes
    8088             :  with significant overhead, in which case the user must explicitly allow for
    8089             :  such an emulation by setting bForce to TRUE. Drivers that offer emulated
    8090             :  transactions should advertise the ODsCEmulatedTransactions capability (and not
    8091             :  ODsCTransactions).
    8092             : 
    8093             :  This function is the same as the C++ method GDALDataset::StartTransaction()
    8094             : 
    8095             :  @param hDS the dataset handle.
    8096             :  @param bForce can be set to TRUE if an emulation, possibly slow, of a
    8097             :  transaction
    8098             :                mechanism is acceptable.
    8099             : 
    8100             :  @return OGRERR_NONE on success.
    8101             :  @since GDAL 2.0
    8102             : */
    8103          77 : OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
    8104             : {
    8105          77 :     VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
    8106             :                       OGRERR_INVALID_HANDLE);
    8107             : 
    8108             : #ifdef OGRAPISPY_ENABLED
    8109          77 :     if (bOGRAPISpyEnabled)
    8110           2 :         OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
    8111             : #endif
    8112             : 
    8113          77 :     return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
    8114             : }
    8115             : 
    8116             : /************************************************************************/
    8117             : /*                           CommitTransaction()                        */
    8118             : /************************************************************************/
    8119             : 
    8120             : /**
    8121             :  \brief For datasources which support transactions, CommitTransaction commits a
    8122             :  transaction.
    8123             : 
    8124             :  If no transaction is active, or the commit fails, will return
    8125             :  OGRERR_FAILURE. Datasources which do not support transactions will
    8126             :  always return OGRERR_UNSUPPORTED_OPERATION.
    8127             : 
    8128             :  Depending on drivers, this may or may not abort layer sequential readings that
    8129             :  are active.
    8130             : 
    8131             :  This function is the same as the C function GDALDatasetCommitTransaction().
    8132             : 
    8133             :  @return OGRERR_NONE on success.
    8134             :  @since GDAL 2.0
    8135             : */
    8136          37 : OGRErr GDALDataset::CommitTransaction()
    8137             : {
    8138          37 :     return OGRERR_UNSUPPORTED_OPERATION;
    8139             : }
    8140             : 
    8141             : /************************************************************************/
    8142             : /*                        GDALDatasetCommitTransaction()                */
    8143             : /************************************************************************/
    8144             : 
    8145             : /**
    8146             :  \brief For datasources which support transactions, CommitTransaction commits a
    8147             :  transaction.
    8148             : 
    8149             :  If no transaction is active, or the commit fails, will return
    8150             :  OGRERR_FAILURE. Datasources which do not support transactions will
    8151             :  always return OGRERR_UNSUPPORTED_OPERATION.
    8152             : 
    8153             :  Depending on drivers, this may or may not abort layer sequential readings that
    8154             :  are active.
    8155             : 
    8156             :  This function is the same as the C++ method GDALDataset::CommitTransaction()
    8157             : 
    8158             :  @return OGRERR_NONE on success.
    8159             :  @since GDAL 2.0
    8160             : */
    8161          46 : OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
    8162             : {
    8163          46 :     VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
    8164             :                       OGRERR_INVALID_HANDLE);
    8165             : 
    8166             : #ifdef OGRAPISPY_ENABLED
    8167          46 :     if (bOGRAPISpyEnabled)
    8168           2 :         OGRAPISpy_Dataset_CommitTransaction(hDS);
    8169             : #endif
    8170             : 
    8171          46 :     return GDALDataset::FromHandle(hDS)->CommitTransaction();
    8172             : }
    8173             : 
    8174             : /************************************************************************/
    8175             : /*                           RollbackTransaction()                      */
    8176             : /************************************************************************/
    8177             : 
    8178             : /**
    8179             :  \brief For datasources which support transactions, RollbackTransaction will
    8180             :  roll back a datasource to its state before the start of the current
    8181             :  transaction.
    8182             :  If no transaction is active, or the rollback fails, will return
    8183             :  OGRERR_FAILURE. Datasources which do not support transactions will
    8184             :  always return OGRERR_UNSUPPORTED_OPERATION.
    8185             : 
    8186             :  This function is the same as the C function GDALDatasetRollbackTransaction().
    8187             : 
    8188             :  @return OGRERR_NONE on success.
    8189             :  @since GDAL 2.0
    8190             : */
    8191           2 : OGRErr GDALDataset::RollbackTransaction()
    8192             : {
    8193           2 :     return OGRERR_UNSUPPORTED_OPERATION;
    8194             : }
    8195             : 
    8196             : /************************************************************************/
    8197             : /*                     GDALDatasetRollbackTransaction()                 */
    8198             : /************************************************************************/
    8199             : 
    8200             : /**
    8201             :  \brief For datasources which support transactions, RollbackTransaction will
    8202             :  roll back a datasource to its state before the start of the current
    8203             :  transaction.
    8204             :  If no transaction is active, or the rollback fails, will return
    8205             :  OGRERR_FAILURE. Datasources which do not support transactions will
    8206             :  always return OGRERR_UNSUPPORTED_OPERATION.
    8207             : 
    8208             :  This function is the same as the C++ method GDALDataset::RollbackTransaction().
    8209             : 
    8210             :  @return OGRERR_NONE on success.
    8211             :  @since GDAL 2.0
    8212             : */
    8213          32 : OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
    8214             : {
    8215          32 :     VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
    8216             :                       OGRERR_INVALID_HANDLE);
    8217             : 
    8218             : #ifdef OGRAPISPY_ENABLED
    8219          32 :     if (bOGRAPISpyEnabled)
    8220           2 :         OGRAPISpy_Dataset_RollbackTransaction(hDS);
    8221             : #endif
    8222             : 
    8223          32 :     return GDALDataset::FromHandle(hDS)->RollbackTransaction();
    8224             : }
    8225             : 
    8226             : //! @cond Doxygen_Suppress
    8227             : 
    8228             : /************************************************************************/
    8229             : /*                   ShareLockWithParentDataset()                       */
    8230             : /************************************************************************/
    8231             : 
    8232             : /* To be used typically by the GTiff driver to link overview datasets */
    8233             : /* with their main dataset, so that they share the same lock */
    8234             : /* Cf https://github.com/OSGeo/gdal/issues/1488 */
    8235             : /* The parent dataset should remain alive while the this dataset is alive */
    8236             : 
    8237        2120 : void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)
    8238             : {
    8239        2120 :     if (m_poPrivate != nullptr)
    8240             :     {
    8241        2120 :         m_poPrivate->poParentDataset = poParentDataset;
    8242             :     }
    8243        2120 : }
    8244             : 
    8245             : /************************************************************************/
    8246             : /*                   SetQueryLoggerFunc()                               */
    8247             : /************************************************************************/
    8248             : 
    8249           0 : bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,
    8250             :                                      CPL_UNUSED void *context)
    8251             : {
    8252           0 :     return false;
    8253             : }
    8254             : 
    8255             : /************************************************************************/
    8256             : /*                          EnterReadWrite()                            */
    8257             : /************************************************************************/
    8258             : 
    8259     6792050 : int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
    8260             : {
    8261    13584000 :     if (m_poPrivate == nullptr ||
    8262     6792040 :         IsThreadSafe(GDAL_OF_RASTER | (nOpenFlags & GDAL_OF_UPDATE)))
    8263        8666 :         return FALSE;
    8264             : 
    8265     6783300 :     if (m_poPrivate->poParentDataset)
    8266       38338 :         return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
    8267             : 
    8268     6744960 :     if (eAccess == GA_Update)
    8269             :     {
    8270     1601510 :         if (m_poPrivate->eStateReadWriteMutex ==
    8271             :             GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
    8272             :         {
    8273             :             // In case dead-lock would occur, which is not impossible,
    8274             :             // this can be used to prevent it, but at the risk of other
    8275             :             // issues.
    8276        7533 :             if (CPLTestBool(
    8277             :                     CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
    8278             :             {
    8279        7533 :                 m_poPrivate->eStateReadWriteMutex =
    8280             :                     GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
    8281             :             }
    8282             :             else
    8283             :             {
    8284           0 :                 m_poPrivate->eStateReadWriteMutex =
    8285             :                     GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
    8286             :             }
    8287             :         }
    8288     1601510 :         if (m_poPrivate->eStateReadWriteMutex ==
    8289             :             GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)
    8290             :         {
    8291             :             // There should be no race related to creating this mutex since
    8292             :             // it should be first created through IWriteBlock() / IRasterIO()
    8293             :             // and then GDALRasterBlock might call it from another thread.
    8294             : #ifdef DEBUG_VERBOSE
    8295             :             CPLDebug("GDAL",
    8296             :                      "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
    8297             :                      CPLGetPID(), GetDescription());
    8298             : #endif
    8299      987749 :             CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
    8300             : 
    8301             :             const int nCountMutex =
    8302      987759 :                 m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
    8303      987760 :             if (nCountMutex == 0 && eRWFlag == GF_Read)
    8304             :             {
    8305      335065 :                 CPLReleaseMutex(m_poPrivate->hMutex);
    8306      865701 :                 for (int i = 0; i < nBands; i++)
    8307             :                 {
    8308      530636 :                     auto blockCache = papoBands[i]->poBandBlockCache;
    8309      530636 :                     if (blockCache)
    8310      489255 :                         blockCache->WaitCompletionPendingTasks();
    8311             :                 }
    8312      335065 :                 CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
    8313             :             }
    8314             : 
    8315      987760 :             return TRUE;
    8316             :         }
    8317             :     }
    8318     5757210 :     return FALSE;
    8319             : }
    8320             : 
    8321             : /************************************************************************/
    8322             : /*                         LeaveReadWrite()                             */
    8323             : /************************************************************************/
    8324             : 
    8325     1014640 : void GDALDataset::LeaveReadWrite()
    8326             : {
    8327     1014640 :     if (m_poPrivate)
    8328             :     {
    8329     1014640 :         if (m_poPrivate->poParentDataset)
    8330             :         {
    8331       26878 :             m_poPrivate->poParentDataset->LeaveReadWrite();
    8332       26878 :             return;
    8333             :         }
    8334             : 
    8335      987759 :         m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
    8336      987754 :         CPLReleaseMutex(m_poPrivate->hMutex);
    8337             : #ifdef DEBUG_VERBOSE
    8338             :         CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
    8339             :                  CPLGetPID(), GetDescription());
    8340             : #endif
    8341             :     }
    8342             : }
    8343             : 
    8344             : /************************************************************************/
    8345             : /*                           InitRWLock()                               */
    8346             : /************************************************************************/
    8347             : 
    8348     3639670 : void GDALDataset::InitRWLock()
    8349             : {
    8350     3639670 :     if (m_poPrivate)
    8351             :     {
    8352     3639670 :         if (m_poPrivate->poParentDataset)
    8353             :         {
    8354        7035 :             m_poPrivate->poParentDataset->InitRWLock();
    8355        7035 :             return;
    8356             :         }
    8357             : 
    8358     3632640 :         if (m_poPrivate->eStateReadWriteMutex ==
    8359             :             GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
    8360             :         {
    8361           1 :             if (EnterReadWrite(GF_Write))
    8362           1 :                 LeaveReadWrite();
    8363             :         }
    8364             :     }
    8365             : }
    8366             : 
    8367             : /************************************************************************/
    8368             : /*                       DisableReadWriteMutex()                        */
    8369             : /************************************************************************/
    8370             : 
    8371             : // The mutex logic is broken in multi-threaded situations, for example
    8372             : // with 2 WarpedVRT datasets being read at the same time. In that
    8373             : // particular case, the mutex is not needed, so allow the VRTWarpedDataset code
    8374             : // to disable it.
    8375       16238 : void GDALDataset::DisableReadWriteMutex()
    8376             : {
    8377       16238 :     if (m_poPrivate)
    8378             :     {
    8379       16239 :         if (m_poPrivate->poParentDataset)
    8380             :         {
    8381           0 :             m_poPrivate->poParentDataset->DisableReadWriteMutex();
    8382           0 :             return;
    8383             :         }
    8384             : 
    8385       16239 :         m_poPrivate->eStateReadWriteMutex =
    8386             :             GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
    8387             :     }
    8388             : }
    8389             : 
    8390             : /************************************************************************/
    8391             : /*                      TemporarilyDropReadWriteLock()                  */
    8392             : /************************************************************************/
    8393             : 
    8394     3151360 : void GDALDataset::TemporarilyDropReadWriteLock()
    8395             : {
    8396     3151360 :     if (m_poPrivate == nullptr)
    8397           0 :         return;
    8398             : 
    8399     3151360 :     if (m_poPrivate->poParentDataset)
    8400             :     {
    8401       23045 :         m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
    8402       23045 :         return;
    8403             :     }
    8404             : 
    8405     3128320 :     if (m_poPrivate->hMutex)
    8406             :     {
    8407             : #ifdef DEBUG_VERBOSE
    8408             :         CPLDebug("GDAL",
    8409             :                  "[Thread " CPL_FRMT_GIB "] "
    8410             :                  "Temporarily drop RW mutex for %s",
    8411             :                  CPLGetPID(), GetDescription());
    8412             : #endif
    8413      291685 :         CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
    8414             :         const int nCount =
    8415      291685 :             m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
    8416             : #ifdef DEBUG_EXTRA
    8417             :         m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
    8418             : #endif
    8419      887823 :         for (int i = 0; i < nCount + 1; i++)
    8420             :         {
    8421             :             // The mutex is recursive
    8422             :             // coverity[double_unlock]
    8423      596138 :             CPLReleaseMutex(m_poPrivate->hMutex);
    8424             :         }
    8425             :     }
    8426             : }
    8427             : 
    8428             : /************************************************************************/
    8429             : /*                       ReacquireReadWriteLock()                       */
    8430             : /************************************************************************/
    8431             : 
    8432     3151480 : void GDALDataset::ReacquireReadWriteLock()
    8433             : {
    8434     3151480 :     if (m_poPrivate == nullptr)
    8435           0 :         return;
    8436             : 
    8437     3151480 :     if (m_poPrivate->poParentDataset)
    8438             :     {
    8439       23045 :         m_poPrivate->poParentDataset->ReacquireReadWriteLock();
    8440       23045 :         return;
    8441             :     }
    8442             : 
    8443     3128430 :     if (m_poPrivate->hMutex)
    8444             :     {
    8445             : #ifdef DEBUG_VERBOSE
    8446             :         CPLDebug("GDAL",
    8447             :                  "[Thread " CPL_FRMT_GIB "] "
    8448             :                  "Reacquire temporarily dropped RW mutex for %s",
    8449             :                  CPLGetPID(), GetDescription());
    8450             : #endif
    8451      291685 :         CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
    8452             :         const int nCount =
    8453      291685 :             m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
    8454             : #ifdef DEBUG_EXTRA
    8455             :         CPLAssert(nCount ==
    8456             :                   m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
    8457             : #endif
    8458      291685 :         if (nCount == 0)
    8459       11462 :             CPLReleaseMutex(m_poPrivate->hMutex);
    8460      315915 :         for (int i = 0; i < nCount - 1; i++)
    8461             :         {
    8462             :             // The mutex is recursive
    8463             :             // coverity[double_lock]
    8464       24230 :             CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
    8465             :         }
    8466             :     }
    8467             : }
    8468             : 
    8469             : /************************************************************************/
    8470             : /*                           AcquireMutex()                             */
    8471             : /************************************************************************/
    8472             : 
    8473         196 : int GDALDataset::AcquireMutex()
    8474             : {
    8475         196 :     if (m_poPrivate == nullptr)
    8476           0 :         return 0;
    8477         196 :     if (m_poPrivate->poParentDataset)
    8478             :     {
    8479           0 :         return m_poPrivate->poParentDataset->AcquireMutex();
    8480             :     }
    8481             : 
    8482         196 :     return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
    8483             : }
    8484             : 
    8485             : /************************************************************************/
    8486             : /*                          ReleaseMutex()                              */
    8487             : /************************************************************************/
    8488             : 
    8489         196 : void GDALDataset::ReleaseMutex()
    8490             : {
    8491         196 :     if (m_poPrivate)
    8492             :     {
    8493         196 :         if (m_poPrivate->poParentDataset)
    8494             :         {
    8495           0 :             m_poPrivate->poParentDataset->ReleaseMutex();
    8496           0 :             return;
    8497             :         }
    8498             : 
    8499         196 :         CPLReleaseMutex(m_poPrivate->hMutex);
    8500             :     }
    8501             : }
    8502             : 
    8503             : //! @endcond
    8504             : 
    8505             : /************************************************************************/
    8506             : /*              GDALDataset::Features::Iterator::Private                */
    8507             : /************************************************************************/
    8508             : 
    8509             : struct GDALDataset::Features::Iterator::Private
    8510             : {
    8511             :     GDALDataset::FeatureLayerPair m_oPair{};
    8512             :     GDALDataset *m_poDS = nullptr;
    8513             :     bool m_bEOF = true;
    8514             : };
    8515             : 
    8516           4 : GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)
    8517           4 :     : m_poPrivate(new GDALDataset::Features::Iterator::Private())
    8518             : {
    8519           4 :     m_poPrivate->m_poDS = poDS;
    8520           4 :     if (bStart)
    8521             :     {
    8522           2 :         poDS->ResetReading();
    8523           4 :         m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(
    8524           2 :             &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
    8525           2 :         m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
    8526             :     }
    8527           4 : }
    8528             : 
    8529             : GDALDataset::Features::Iterator::~Iterator() = default;
    8530             : 
    8531             : const GDALDataset::FeatureLayerPair &
    8532          20 : GDALDataset::Features::Iterator::operator*() const
    8533             : {
    8534          20 :     return m_poPrivate->m_oPair;
    8535             : }
    8536             : 
    8537          20 : GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()
    8538             : {
    8539          40 :     m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(
    8540          20 :         &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
    8541          20 :     m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
    8542          20 :     return *this;
    8543             : }
    8544             : 
    8545          22 : bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const
    8546             : {
    8547          22 :     return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
    8548             : }
    8549             : 
    8550             : /************************************************************************/
    8551             : /*                            GetFeatures()                             */
    8552             : /************************************************************************/
    8553             : 
    8554             : /** Function that return an iterable object over features in the dataset
    8555             :  * layer.
    8556             :  *
    8557             :  * This is a C++ iterator friendly version of GetNextFeature().
    8558             :  *
    8559             :  * Using this iterator for standard range-based loops is safe, but
    8560             :  * due to implementation limitations, you shouldn't try to access
    8561             :  * (dereference) more than one iterator step at a time, since the
    8562             :  * FeatureLayerPair reference which is returned is reused.
    8563             :  *
    8564             :  * Typical use is:
    8565             :  * \code{.cpp}
    8566             :  * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
    8567             :  * {
    8568             :  *       std::cout << "Feature of layer " <<
    8569             :  *               oFeatureLayerPair.layer->GetName() << std::endl;
    8570             :  *       oFeatureLayerPair.feature->DumpReadable();
    8571             :  * }
    8572             :  * \endcode
    8573             :  *
    8574             :  * @see GetNextFeature()
    8575             :  *
    8576             :  * @since GDAL 2.3
    8577             :  */
    8578           2 : GDALDataset::Features GDALDataset::GetFeatures()
    8579             : {
    8580           2 :     return Features(this);
    8581             : }
    8582             : 
    8583             : /************************************************************************/
    8584             : /*                                 begin()                              */
    8585             : /************************************************************************/
    8586             : 
    8587             : /**
    8588             :  \brief Return beginning of feature iterator.
    8589             : 
    8590             :  @since GDAL 2.3
    8591             : */
    8592             : 
    8593           2 : const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
    8594             : {
    8595           2 :     return {m_poSelf, true};
    8596             : }
    8597             : 
    8598             : /************************************************************************/
    8599             : /*                                  end()                               */
    8600             : /************************************************************************/
    8601             : 
    8602             : /**
    8603             :  \brief Return end of feature iterator.
    8604             : 
    8605             :  @since GDAL 2.3
    8606             : */
    8607             : 
    8608           2 : const GDALDataset::Features::Iterator GDALDataset::Features::end() const
    8609             : {
    8610           2 :     return {m_poSelf, false};
    8611             : }
    8612             : 
    8613             : /************************************************************************/
    8614             : /*               GDALDataset::Layers::Iterator::Private                 */
    8615             : /************************************************************************/
    8616             : 
    8617             : struct GDALDataset::Layers::Iterator::Private
    8618             : {
    8619             :     OGRLayer *m_poLayer = nullptr;
    8620             :     int m_iCurLayer = 0;
    8621             :     int m_nLayerCount = 0;
    8622             :     GDALDataset *m_poDS = nullptr;
    8623             : };
    8624             : 
    8625           2 : GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())
    8626             : {
    8627           2 : }
    8628             : 
    8629             : // False positive of cppcheck 1.72
    8630             : // cppcheck-suppress uninitMemberVar
    8631           9 : GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)
    8632           9 :     : m_poPrivate(new Private(*(oOther.m_poPrivate)))
    8633             : {
    8634           9 : }
    8635             : 
    8636           5 : GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept
    8637           5 :     : m_poPrivate(std::move(oOther.m_poPrivate))
    8638             : {
    8639           5 : }
    8640             : 
    8641          16 : GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)
    8642          16 :     : m_poPrivate(new Private())
    8643             : {
    8644          16 :     m_poPrivate->m_poDS = poDS;
    8645          16 :     m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
    8646          16 :     if (bStart)
    8647             :     {
    8648           9 :         if (m_poPrivate->m_nLayerCount)
    8649           8 :             m_poPrivate->m_poLayer = poDS->GetLayer(0);
    8650             :     }
    8651             :     else
    8652             :     {
    8653           7 :         m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
    8654             :     }
    8655          16 : }
    8656             : 
    8657             : GDALDataset::Layers::Iterator::~Iterator() = default;
    8658             : 
    8659             : // False positive of cppcheck 1.72
    8660             : // cppcheck-suppress operatorEqVarError
    8661             : GDALDataset::Layers::Iterator &
    8662           1 : GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)
    8663             : {
    8664           1 :     *m_poPrivate = *oOther.m_poPrivate;
    8665           1 :     return *this;
    8666             : }
    8667             : 
    8668           1 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(
    8669             :     GDALDataset::Layers::Iterator &&oOther) noexcept
    8670             : {
    8671           1 :     m_poPrivate = std::move(oOther.m_poPrivate);
    8672           1 :     return *this;
    8673             : }
    8674             : 
    8675          11 : OGRLayer *GDALDataset::Layers::Iterator::operator*() const
    8676             : {
    8677          11 :     return m_poPrivate->m_poLayer;
    8678             : }
    8679             : 
    8680          11 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()
    8681             : {
    8682          11 :     m_poPrivate->m_iCurLayer++;
    8683          11 :     if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
    8684             :     {
    8685           7 :         m_poPrivate->m_poLayer =
    8686           7 :             m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
    8687             :     }
    8688             :     else
    8689             :     {
    8690           4 :         m_poPrivate->m_poLayer = nullptr;
    8691             :     }
    8692          11 :     return *this;
    8693             : }
    8694             : 
    8695           2 : GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
    8696             : {
    8697           2 :     GDALDataset::Layers::Iterator temp = *this;
    8698           2 :     ++(*this);
    8699           2 :     return temp;
    8700             : }
    8701             : 
    8702          12 : bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const
    8703             : {
    8704          12 :     return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
    8705             : }
    8706             : 
    8707             : /************************************************************************/
    8708             : /*                             GetLayers()                              */
    8709             : /************************************************************************/
    8710             : 
    8711             : /** Function that returns an iterable object over layers in the dataset.
    8712             :  *
    8713             :  * This is a C++ iterator friendly version of GetLayer().
    8714             :  *
    8715             :  * Typical use is:
    8716             :  * \code{.cpp}
    8717             :  * for( auto&& poLayer: poDS->GetLayers() )
    8718             :  * {
    8719             :  *       std::cout << "Layer  << poLayer->GetName() << std::endl;
    8720             :  * }
    8721             :  * \endcode
    8722             :  *
    8723             :  * @see GetLayer()
    8724             :  *
    8725             :  * @since GDAL 2.3
    8726             :  */
    8727          12 : GDALDataset::Layers GDALDataset::GetLayers()
    8728             : {
    8729          12 :     return Layers(this);
    8730             : }
    8731             : 
    8732             : /************************************************************************/
    8733             : /*                                 begin()                              */
    8734             : /************************************************************************/
    8735             : 
    8736             : /**
    8737             :  \brief Return beginning of layer iterator.
    8738             : 
    8739             :  @since GDAL 2.3
    8740             : */
    8741             : 
    8742           9 : GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
    8743             : {
    8744           9 :     return {m_poSelf, true};
    8745             : }
    8746             : 
    8747             : /************************************************************************/
    8748             : /*                                  end()                               */
    8749             : /************************************************************************/
    8750             : 
    8751             : /**
    8752             :  \brief Return end of layer iterator.
    8753             : 
    8754             :  @since GDAL 2.3
    8755             : */
    8756             : 
    8757           7 : GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
    8758             : {
    8759           7 :     return {m_poSelf, false};
    8760             : }
    8761             : 
    8762             : /************************************************************************/
    8763             : /*                                  size()                             */
    8764             : /************************************************************************/
    8765             : 
    8766             : /**
    8767             :  \brief Get the number of layers in this dataset.
    8768             : 
    8769             :  @return layer count.
    8770             : 
    8771             :  @since GDAL 2.3
    8772             : */
    8773             : 
    8774           1 : size_t GDALDataset::Layers::size() const
    8775             : {
    8776           1 :     return static_cast<size_t>(m_poSelf->GetLayerCount());
    8777             : }
    8778             : 
    8779             : /************************************************************************/
    8780             : /*                                operator[]()                          */
    8781             : /************************************************************************/
    8782             : /**
    8783             :  \brief Fetch a layer by index.
    8784             : 
    8785             :  The returned layer remains owned by the
    8786             :  GDALDataset and should not be deleted by the application.
    8787             : 
    8788             :  @param iLayer a layer number between 0 and size()-1.
    8789             : 
    8790             :  @return the layer, or nullptr if iLayer is out of range or an error occurs.
    8791             : 
    8792             :  @since GDAL 2.3
    8793             : */
    8794             : 
    8795           9 : OGRLayer *GDALDataset::Layers::operator[](int iLayer)
    8796             : {
    8797           9 :     return m_poSelf->GetLayer(iLayer);
    8798             : }
    8799             : 
    8800             : /************************************************************************/
    8801             : /*                                operator[]()                          */
    8802             : /************************************************************************/
    8803             : /**
    8804             :  \brief Fetch a layer by index.
    8805             : 
    8806             :  The returned layer remains owned by the
    8807             :  GDALDataset and should not be deleted by the application.
    8808             : 
    8809             :  @param iLayer a layer number between 0 and size()-1.
    8810             : 
    8811             :  @return the layer, or nullptr if iLayer is out of range or an error occurs.
    8812             : 
    8813             :  @since GDAL 2.3
    8814             : */
    8815             : 
    8816           1 : OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)
    8817             : {
    8818           1 :     return m_poSelf->GetLayer(static_cast<int>(iLayer));
    8819             : }
    8820             : 
    8821             : /************************************************************************/
    8822             : /*                                operator[]()                          */
    8823             : /************************************************************************/
    8824             : /**
    8825             :  \brief Fetch a layer by name.
    8826             : 
    8827             :  The returned layer remains owned by the
    8828             :  GDALDataset and should not be deleted by the application.
    8829             : 
    8830             :  @param pszLayerName layer name
    8831             : 
    8832             :  @return the layer, or nullptr if pszLayerName does not match with a layer
    8833             : 
    8834             :  @since GDAL 2.3
    8835             : */
    8836             : 
    8837           1 : OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)
    8838             : {
    8839           1 :     return m_poSelf->GetLayerByName(pszLayerName);
    8840             : }
    8841             : 
    8842             : /************************************************************************/
    8843             : /*               GDALDataset::Bands::Iterator::Private                 */
    8844             : /************************************************************************/
    8845             : 
    8846             : struct GDALDataset::Bands::Iterator::Private
    8847             : {
    8848             :     GDALRasterBand *m_poBand = nullptr;
    8849             :     int m_iCurBand = 0;
    8850             :     int m_nBandCount = 0;
    8851             :     GDALDataset *m_poDS = nullptr;
    8852             : };
    8853             : 
    8854           6 : GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)
    8855           6 :     : m_poPrivate(new GDALDataset::Bands::Iterator::Private())
    8856             : {
    8857           6 :     m_poPrivate->m_poDS = poDS;
    8858           6 :     m_poPrivate->m_nBandCount = poDS->GetRasterCount();
    8859           6 :     if (bStart)
    8860             :     {
    8861           3 :         if (m_poPrivate->m_nBandCount)
    8862           3 :             m_poPrivate->m_poBand = poDS->GetRasterBand(1);
    8863             :     }
    8864             :     else
    8865             :     {
    8866           3 :         m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
    8867             :     }
    8868           6 : }
    8869             : 
    8870             : GDALDataset::Bands::Iterator::~Iterator() = default;
    8871             : 
    8872           5 : GDALRasterBand *GDALDataset::Bands::Iterator::operator*()
    8873             : {
    8874           5 :     return m_poPrivate->m_poBand;
    8875             : }
    8876             : 
    8877           3 : GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()
    8878             : {
    8879           3 :     m_poPrivate->m_iCurBand++;
    8880           3 :     if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
    8881             :     {
    8882           2 :         m_poPrivate->m_poBand =
    8883           2 :             m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
    8884             :     }
    8885             :     else
    8886             :     {
    8887           1 :         m_poPrivate->m_poBand = nullptr;
    8888             :     }
    8889           3 :     return *this;
    8890             : }
    8891             : 
    8892           6 : bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const
    8893             : {
    8894           6 :     return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
    8895             : }
    8896             : 
    8897             : /************************************************************************/
    8898             : /*                            GetBands()                           */
    8899             : /************************************************************************/
    8900             : 
    8901             : /** Function that returns an iterable object over GDALRasterBand in the dataset.
    8902             :  *
    8903             :  * This is a C++ iterator friendly version of GetRasterBand().
    8904             :  *
    8905             :  * Typical use is:
    8906             :  * \code{.cpp}
    8907             :  * for( auto&& poBand: poDS->GetBands() )
    8908             :  * {
    8909             :  *       std::cout << "Band  << poBand->GetDescription() << std::endl;
    8910             :  * }
    8911             :  * \endcode
    8912             :  *
    8913             :  * @see GetRasterBand()
    8914             :  *
    8915             :  * @since GDAL 2.3
    8916             :  */
    8917           7 : GDALDataset::Bands GDALDataset::GetBands()
    8918             : {
    8919           7 :     return Bands(this);
    8920             : }
    8921             : 
    8922             : /************************************************************************/
    8923             : /*                                 begin()                              */
    8924             : /************************************************************************/
    8925             : 
    8926             : /**
    8927             :  \brief Return beginning of band iterator.
    8928             : 
    8929             :  @since GDAL 2.3
    8930             : */
    8931             : 
    8932           3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
    8933             : {
    8934           3 :     return {m_poSelf, true};
    8935             : }
    8936             : 
    8937             : /************************************************************************/
    8938             : /*                                  end()                               */
    8939             : /************************************************************************/
    8940             : 
    8941             : /**
    8942             :  \brief Return end of band iterator.
    8943             : 
    8944             :  @since GDAL 2.3
    8945             : */
    8946             : 
    8947           3 : const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
    8948             : {
    8949           3 :     return {m_poSelf, false};
    8950             : }
    8951             : 
    8952             : /************************************************************************/
    8953             : /*                                  size()                             */
    8954             : /************************************************************************/
    8955             : 
    8956             : /**
    8957             :  \brief Get the number of raster bands in this dataset.
    8958             : 
    8959             :  @return raster band count.
    8960             : 
    8961             :  @since GDAL 2.3
    8962             : */
    8963             : 
    8964           2 : size_t GDALDataset::Bands::size() const
    8965             : {
    8966           2 :     return static_cast<size_t>(m_poSelf->GetRasterCount());
    8967             : }
    8968             : 
    8969             : /************************************************************************/
    8970             : /*                                operator[]()                          */
    8971             : /************************************************************************/
    8972             : /**
    8973             :  \brief Fetch a raster band by index.
    8974             : 
    8975             :  The returned band remains owned by the
    8976             :  GDALDataset and should not be deleted by the application.
    8977             : 
    8978             :  @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
    8979             :  consistent with the conventions of C/C++, i.e. starting at 0.
    8980             : 
    8981             :  @param iBand a band index between 0 and size()-1.
    8982             : 
    8983             :  @return the band, or nullptr if iBand is out of range or an error occurs.
    8984             : 
    8985             :  @since GDAL 2.3
    8986             : */
    8987             : 
    8988           1 : GDALRasterBand *GDALDataset::Bands::operator[](int iBand)
    8989             : {
    8990           1 :     return m_poSelf->GetRasterBand(1 + iBand);
    8991             : }
    8992             : 
    8993             : /************************************************************************/
    8994             : /*                                operator[]()                          */
    8995             : /************************************************************************/
    8996             : 
    8997             : /**
    8998             :  \brief Fetch a raster band by index.
    8999             : 
    9000             :  The returned band remains owned by the
    9001             :  GDALDataset and should not be deleted by the application.
    9002             : 
    9003             :  @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
    9004             :  consistent with the conventions of C/C++, i.e. starting at 0.
    9005             : 
    9006             :  @param iBand a band index between 0 and size()-1.
    9007             : 
    9008             :  @return the band, or nullptr if iBand is out of range or an error occurs.
    9009             : 
    9010             :  @since GDAL 2.3
    9011             : */
    9012             : 
    9013           1 : GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)
    9014             : {
    9015           1 :     return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
    9016             : }
    9017             : 
    9018             : /************************************************************************/
    9019             : /*                           GetRootGroup()                             */
    9020             : /************************************************************************/
    9021             : 
    9022             : /**
    9023             :  \brief Return the root GDALGroup of this dataset.
    9024             : 
    9025             :  Only valid for multidimensional datasets.
    9026             : 
    9027             :  This is the same as the C function GDALDatasetGetRootGroup().
    9028             : 
    9029             :  @since GDAL 3.1
    9030             : */
    9031             : 
    9032        2527 : std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
    9033             : {
    9034        2527 :     return nullptr;
    9035             : }
    9036             : 
    9037             : /************************************************************************/
    9038             : /*                        GetRawBinaryLayout()                          */
    9039             : /************************************************************************/
    9040             : 
    9041             : //! @cond Doxygen_Suppress
    9042             : /**
    9043             :  \brief Return the layout of a dataset that can be considered as a raw binary
    9044             :  format.
    9045             : 
    9046             :  @param sLayout Structure that will be set if the dataset is a raw binary one.
    9047             :  @return true if the dataset is a raw binary one.
    9048             :  @since GDAL 3.1
    9049             : */
    9050             : 
    9051           0 : bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)
    9052             : {
    9053           0 :     CPL_IGNORE_RET_VAL(sLayout);
    9054           0 :     return false;
    9055             : }
    9056             : 
    9057             : //! @endcond
    9058             : 
    9059             : /************************************************************************/
    9060             : /*                          ClearStatistics()                           */
    9061             : /************************************************************************/
    9062             : 
    9063             : /**
    9064             :  \brief Clear statistics
    9065             : 
    9066             :  Only implemented for now in PAM supported datasets
    9067             : 
    9068             :  This is the same as the C function GDALDatasetClearStatistics().
    9069             : 
    9070             :  @since GDAL 3.2
    9071             : */
    9072             : 
    9073           4 : void GDALDataset::ClearStatistics()
    9074             : {
    9075           8 :     auto poRootGroup = GetRootGroup();
    9076           4 :     if (poRootGroup)
    9077           1 :         poRootGroup->ClearStatistics();
    9078           4 : }
    9079             : 
    9080             : /************************************************************************/
    9081             : /*                        GDALDatasetClearStatistics()                  */
    9082             : /************************************************************************/
    9083             : 
    9084             : /**
    9085             :  \brief Clear statistics
    9086             : 
    9087             :  This is the same as the C++ method GDALDataset::ClearStatistics().
    9088             : 
    9089             :  @since GDAL 3.2
    9090             : */
    9091             : 
    9092           2 : void GDALDatasetClearStatistics(GDALDatasetH hDS)
    9093             : {
    9094           2 :     VALIDATE_POINTER0(hDS, __func__);
    9095           2 :     GDALDataset::FromHandle(hDS)->ClearStatistics();
    9096             : }
    9097             : 
    9098             : /************************************************************************/
    9099             : /*                        GetFieldDomainNames()                         */
    9100             : /************************************************************************/
    9101             : 
    9102             : /** Returns a list of the names of all field domains stored in the dataset.
    9103             :  *
    9104             :  * @note The default implementation assumes that drivers fully populate
    9105             :  * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect
    9106             :  * then a specialized implementation of GetFieldDomainNames() must be
    9107             :  * implemented.
    9108             :  *
    9109             :  * @param papszOptions Driver specific options determining how attributes
    9110             :  * should be retrieved. Pass nullptr for default behavior.
    9111             :  *
    9112             :  * @return list of field domain names
    9113             :  * @since GDAL 3.5
    9114             :  */
    9115             : std::vector<std::string>
    9116          32 : GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const
    9117             : {
    9118             : 
    9119          32 :     std::vector<std::string> names;
    9120          32 :     names.reserve(m_oMapFieldDomains.size());
    9121          44 :     for (const auto &it : m_oMapFieldDomains)
    9122             :     {
    9123          12 :         names.emplace_back(it.first);
    9124             :     }
    9125          32 :     return names;
    9126             : }
    9127             : 
    9128             : /************************************************************************/
    9129             : /*                      GDALDatasetGetFieldDomainNames()                */
    9130             : /************************************************************************/
    9131             : 
    9132             : /** Returns a list of the names of all field domains stored in the dataset.
    9133             :  *
    9134             :  * This is the same as the C++ method GDALDataset::GetFieldDomainNames().
    9135             :  *
    9136             :  * @param hDS Dataset handle.
    9137             :  * @param papszOptions Driver specific options determining how attributes
    9138             :  * should be retrieved. Pass nullptr for default behavior.
    9139             :  *
    9140             :  * @return list of field domain names, to be freed with CSLDestroy()
    9141             :  * @since GDAL 3.5
    9142             :  */
    9143          33 : char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,
    9144             :                                       CSLConstList papszOptions)
    9145             : {
    9146          33 :     VALIDATE_POINTER1(hDS, __func__, nullptr);
    9147             :     auto names =
    9148          66 :         GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);
    9149          66 :     CPLStringList res;
    9150         141 :     for (const auto &name : names)
    9151             :     {
    9152         108 :         res.AddString(name.c_str());
    9153             :     }
    9154          33 :     return res.StealList();
    9155             : }
    9156             : 
    9157             : /************************************************************************/
    9158             : /*                        GetFieldDomain()                              */
    9159             : /************************************************************************/
    9160             : 
    9161             : /** Get a field domain from its name.
    9162             :  *
    9163             :  * @return the field domain, or nullptr if not found.
    9164             :  * @since GDAL 3.3
    9165             :  */
    9166         291 : const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const
    9167             : {
    9168         291 :     const auto iter = m_oMapFieldDomains.find(name);
    9169         291 :     if (iter == m_oMapFieldDomains.end())
    9170         126 :         return nullptr;
    9171         165 :     return iter->second.get();
    9172             : }
    9173             : 
    9174             : /************************************************************************/
    9175             : /*                      GDALDatasetGetFieldDomain()                     */
    9176             : /************************************************************************/
    9177             : 
    9178             : /** Get a field domain from its name.
    9179             :  *
    9180             :  * This is the same as the C++ method GDALDataset::GetFieldDomain().
    9181             :  *
    9182             :  * @param hDS Dataset handle.
    9183             :  * @param pszName Name of field domain.
    9184             :  * @return the field domain (ownership remains to the dataset), or nullptr if
    9185             :  * not found.
    9186             :  * @since GDAL 3.3
    9187             :  */
    9188         117 : OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)
    9189             : {
    9190         117 :     VALIDATE_POINTER1(hDS, __func__, nullptr);
    9191         117 :     VALIDATE_POINTER1(pszName, __func__, nullptr);
    9192         117 :     return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(
    9193         117 :         GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
    9194             : }
    9195             : 
    9196             : /************************************************************************/
    9197             : /*                         AddFieldDomain()                             */
    9198             : /************************************************************************/
    9199             : 
    9200             : /** Add a field domain to the dataset.
    9201             :  *
    9202             :  * Only a few drivers will support this operation, and some of them might only
    9203             :  * support it only for some types of field domains.
    9204             :  * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
    9205             :  * support this operation. A dataset having at least some support for this
    9206             :  * operation should report the ODsCAddFieldDomain dataset capability.
    9207             :  *
    9208             :  * Anticipated failures will not be emitted through the CPLError()
    9209             :  * infrastructure, but will be reported in the failureReason output parameter.
    9210             :  *
    9211             :  * @note Drivers should make sure to update m_oMapFieldDomains in order for the
    9212             :  * default implementation of GetFieldDomainNames() to work correctly, or
    9213             :  * alternatively a specialized implementation of GetFieldDomainNames() should be
    9214             :  * implemented.
    9215             :  *
    9216             :  * @param domain The domain definition.
    9217             :  * @param failureReason      Output parameter. Will contain an error message if
    9218             :  *                           an error occurs.
    9219             :  * @return true in case of success.
    9220             :  * @since GDAL 3.3
    9221             :  */
    9222           0 : bool GDALDataset::AddFieldDomain(
    9223             :     CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
    9224             :     std::string &failureReason)
    9225             : {
    9226           0 :     failureReason = "AddFieldDomain not supported by this driver";
    9227           0 :     return false;
    9228             : }
    9229             : 
    9230             : /************************************************************************/
    9231             : /*                     GDALDatasetAddFieldDomain()                      */
    9232             : /************************************************************************/
    9233             : 
    9234             : /** Add a field domain to the dataset.
    9235             :  *
    9236             :  * Only a few drivers will support this operation, and some of them might only
    9237             :  * support it only for some types of field domains.
    9238             :  * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
    9239             :  * support this operation. A dataset having at least some support for this
    9240             :  * operation should report the ODsCAddFieldDomain dataset capability.
    9241             :  *
    9242             :  * Anticipated failures will not be emitted through the CPLError()
    9243             :  * infrastructure, but will be reported in the ppszFailureReason output
    9244             :  * parameter.
    9245             :  *
    9246             :  * @param hDS                Dataset handle.
    9247             :  * @param hFieldDomain       The domain definition. Contrary to the C++ version,
    9248             :  *                           the passed object is copied.
    9249             :  * @param ppszFailureReason  Output parameter. Will contain an error message if
    9250             :  *                           an error occurs (*ppszFailureReason to be freed
    9251             :  *                           with CPLFree). May be NULL.
    9252             :  * @return true in case of success.
    9253             :  * @since GDAL 3.3
    9254             :  */
    9255          35 : bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,
    9256             :                                char **ppszFailureReason)
    9257             : {
    9258          35 :     VALIDATE_POINTER1(hDS, __func__, false);
    9259          35 :     VALIDATE_POINTER1(hFieldDomain, __func__, false);
    9260             :     auto poDomain = std::unique_ptr<OGRFieldDomain>(
    9261          70 :         OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
    9262          35 :     if (poDomain == nullptr)
    9263           0 :         return false;
    9264          35 :     std::string failureReason;
    9265          70 :     const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(
    9266          35 :         std::move(poDomain), failureReason);
    9267          35 :     if (ppszFailureReason)
    9268             :     {
    9269           0 :         *ppszFailureReason =
    9270           0 :             failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
    9271             :     }
    9272          35 :     return bRet;
    9273             : }
    9274             : 
    9275             : /************************************************************************/
    9276             : /*                        DeleteFieldDomain()                           */
    9277             : /************************************************************************/
    9278             : 
    9279             : /** Removes a field domain from the dataset.
    9280             :  *
    9281             :  * Only a few drivers will support this operation.
    9282             :  *
    9283             :  * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
    9284             :  * support this operation. A dataset having at least some support for this
    9285             :  * operation should report the ODsCDeleteFieldDomain dataset capability.
    9286             :  *
    9287             :  * Anticipated failures will not be emitted through the CPLError()
    9288             :  * infrastructure, but will be reported in the failureReason output parameter.
    9289             :  *
    9290             :  * @note Drivers should make sure to update m_oMapFieldDomains in order for the
    9291             :  * default implementation of GetFieldDomainNames() to work correctly, or
    9292             :  * alternatively a specialized implementation of GetFieldDomainNames() should be
    9293             :  * implemented.
    9294             :  *
    9295             :  * @param name The domain name.
    9296             :  * @param failureReason      Output parameter. Will contain an error message if
    9297             :  *                           an error occurs.
    9298             :  * @return true in case of success.
    9299             :  * @since GDAL 3.5
    9300             :  */
    9301           0 : bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,
    9302             :                                     std::string &failureReason)
    9303             : {
    9304           0 :     failureReason = "DeleteFieldDomain not supported by this driver";
    9305           0 :     return false;
    9306             : }
    9307             : 
    9308             : /************************************************************************/
    9309             : /*                  GDALDatasetDeleteFieldDomain()                      */
    9310             : /************************************************************************/
    9311             : 
    9312             : /** Removes a field domain from the dataset.
    9313             :  *
    9314             :  * Only a few drivers will support this operation.
    9315             :  *
    9316             :  * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
    9317             :  * support this operation. A dataset having at least some support for this
    9318             :  * operation should report the ODsCDeleteFieldDomain dataset capability.
    9319             :  *
    9320             :  * Anticipated failures will not be emitted through the CPLError()
    9321             :  * infrastructure, but will be reported in the ppszFailureReason output
    9322             :  * parameter.
    9323             :  *
    9324             :  * @param hDS                Dataset handle.
    9325             :  * @param pszName            The domain name.
    9326             :  * @param ppszFailureReason  Output parameter. Will contain an error message if
    9327             :  *                           an error occurs (*ppszFailureReason to be freed
    9328             :  *                           with CPLFree). May be NULL.
    9329             :  * @return true in case of success.
    9330             :  * @since GDAL 3.3
    9331             :  */
    9332          10 : bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,
    9333             :                                   char **ppszFailureReason)
    9334             : {
    9335          10 :     VALIDATE_POINTER1(hDS, __func__, false);
    9336          10 :     VALIDATE_POINTER1(pszName, __func__, false);
    9337          10 :     std::string failureReason;
    9338             :     const bool bRet =
    9339          10 :         GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);
    9340          10 :     if (ppszFailureReason)
    9341             :     {
    9342           0 :         *ppszFailureReason =
    9343           0 :             failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
    9344             :     }
    9345          10 :     return bRet;
    9346             : }
    9347             : 
    9348             : /************************************************************************/
    9349             : /*                       UpdateFieldDomain()                            */
    9350             : /************************************************************************/
    9351             : 
    9352             : /** Updates an existing field domain by replacing its definition.
    9353             :  *
    9354             :  * The existing field domain with matching name will be replaced.
    9355             :  *
    9356             :  * Only a few drivers will support this operation, and some of them might only
    9357             :  * support it only for some types of field domains.
    9358             :  * At the time of writing (GDAL 3.5), only the Memory driver
    9359             :  * supports this operation. A dataset having at least some support for this
    9360             :  * operation should report the ODsCUpdateFieldDomain dataset capability.
    9361             :  *
    9362             :  * Anticipated failures will not be emitted through the CPLError()
    9363             :  * infrastructure, but will be reported in the failureReason output parameter.
    9364             :  *
    9365             :  * @param domain The domain definition.
    9366             :  * @param failureReason      Output parameter. Will contain an error message if
    9367             :  *                           an error occurs.
    9368             :  * @return true in case of success.
    9369             :  * @since GDAL 3.5
    9370             :  */
    9371           0 : bool GDALDataset::UpdateFieldDomain(
    9372             :     CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
    9373             :     std::string &failureReason)
    9374             : {
    9375           0 :     failureReason = "UpdateFieldDomain not supported by this driver";
    9376           0 :     return false;
    9377             : }
    9378             : 
    9379             : /************************************************************************/
    9380             : /*                  GDALDatasetUpdateFieldDomain()                      */
    9381             : /************************************************************************/
    9382             : 
    9383             : /** Updates an existing field domain by replacing its definition.
    9384             :  *
    9385             :  * The existing field domain with matching name will be replaced.
    9386             :  *
    9387             :  * Only a few drivers will support this operation, and some of them might only
    9388             :  * support it only for some types of field domains.
    9389             :  * At the time of writing (GDAL 3.5), only the Memory driver
    9390             :  * supports this operation. A dataset having at least some support for this
    9391             :  * operation should report the ODsCUpdateFieldDomain dataset capability.
    9392             :  *
    9393             :  * Anticipated failures will not be emitted through the CPLError()
    9394             :  * infrastructure, but will be reported in the failureReason output parameter.
    9395             :  *
    9396             :  * @param hDS                Dataset handle.
    9397             :  * @param hFieldDomain       The domain definition. Contrary to the C++ version,
    9398             :  *                           the passed object is copied.
    9399             :  * @param ppszFailureReason  Output parameter. Will contain an error message if
    9400             :  *                           an error occurs (*ppszFailureReason to be freed
    9401             :  *                           with CPLFree). May be NULL.
    9402             :  * @return true in case of success.
    9403             :  * @since GDAL 3.5
    9404             :  */
    9405           5 : bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,
    9406             :                                   OGRFieldDomainH hFieldDomain,
    9407             :                                   char **ppszFailureReason)
    9408             : {
    9409           5 :     VALIDATE_POINTER1(hDS, __func__, false);
    9410           5 :     VALIDATE_POINTER1(hFieldDomain, __func__, false);
    9411             :     auto poDomain = std::unique_ptr<OGRFieldDomain>(
    9412          10 :         OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
    9413           5 :     if (poDomain == nullptr)
    9414           0 :         return false;
    9415           5 :     std::string failureReason;
    9416          10 :     const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(
    9417           5 :         std::move(poDomain), failureReason);
    9418           5 :     if (ppszFailureReason)
    9419             :     {
    9420           0 :         *ppszFailureReason =
    9421           0 :             failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
    9422             :     }
    9423           5 :     return bRet;
    9424             : }
    9425             : 
    9426             : /************************************************************************/
    9427             : /*                        GetRelationshipNames()                        */
    9428             : /************************************************************************/
    9429             : 
    9430             : /** Returns a list of the names of all relationships stored in the dataset.
    9431             :  *
    9432             :  * @param papszOptions Driver specific options determining how relationships
    9433             :  * should be retrieved. Pass nullptr for default behavior.
    9434             :  *
    9435             :  * @return list of relationship names
    9436             :  * @since GDAL 3.6
    9437             :  */
    9438             : std::vector<std::string>
    9439          46 : GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const
    9440             : {
    9441          46 :     return {};
    9442             : }
    9443             : 
    9444             : /************************************************************************/
    9445             : /*                     GDALDatasetGetRelationshipNames()                */
    9446             : /************************************************************************/
    9447             : 
    9448             : /** Returns a list of the names of all relationships stored in the dataset.
    9449             :  *
    9450             :  * This is the same as the C++ method GDALDataset::GetRelationshipNames().
    9451             :  *
    9452             :  * @param hDS Dataset handle.
    9453             :  * @param papszOptions Driver specific options determining how relationships
    9454             :  * should be retrieved. Pass nullptr for default behavior.
    9455             :  *
    9456             :  * @return list of relationship names, to be freed with CSLDestroy()
    9457             :  * @since GDAL 3.6
    9458             :  */
    9459          41 : char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,
    9460             :                                        CSLConstList papszOptions)
    9461             : {
    9462          41 :     VALIDATE_POINTER1(hDS, __func__, nullptr);
    9463             :     auto names =
    9464          82 :         GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);
    9465          82 :     CPLStringList res;
    9466         130 :     for (const auto &name : names)
    9467             :     {
    9468          89 :         res.AddString(name.c_str());
    9469             :     }
    9470          41 :     return res.StealList();
    9471             : }
    9472             : 
    9473             : /************************************************************************/
    9474             : /*                        GetRelationship()                             */
    9475             : /************************************************************************/
    9476             : 
    9477             : /** Get a relationship from its name.
    9478             :  *
    9479             :  * @return the relationship, or nullptr if not found.
    9480             :  * @since GDAL 3.6
    9481             :  */
    9482             : const GDALRelationship *
    9483           0 : GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const
    9484             : {
    9485           0 :     return nullptr;
    9486             : }
    9487             : 
    9488             : /************************************************************************/
    9489             : /*                      GDALDatasetGetRelationship()                    */
    9490             : /************************************************************************/
    9491             : 
    9492             : /** Get a relationship from its name.
    9493             :  *
    9494             :  * This is the same as the C++ method GDALDataset::GetRelationship().
    9495             :  *
    9496             :  * @param hDS Dataset handle.
    9497             :  * @param pszName Name of relationship.
    9498             :  * @return the relationship (ownership remains to the dataset), or nullptr if
    9499             :  * not found.
    9500             :  * @since GDAL 3.6
    9501             :  */
    9502          50 : GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,
    9503             :                                              const char *pszName)
    9504             : {
    9505          50 :     VALIDATE_POINTER1(hDS, __func__, nullptr);
    9506          50 :     VALIDATE_POINTER1(pszName, __func__, nullptr);
    9507          50 :     return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(
    9508          50 :         GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));
    9509             : }
    9510             : 
    9511             : /************************************************************************/
    9512             : /*                         AddRelationship()                            */
    9513             : /************************************************************************/
    9514             : 
    9515             : /** Add a relationship to the dataset.
    9516             :  *
    9517             :  * Only a few drivers will support this operation, and some of them might only
    9518             :  * support it only for some types of relationships.
    9519             :  *
    9520             :  * A dataset having at least some support for this
    9521             :  * operation should report the GDsCAddRelationship dataset capability.
    9522             :  *
    9523             :  * Anticipated failures will not be emitted through the CPLError()
    9524             :  * infrastructure, but will be reported in the failureReason output parameter.
    9525             :  *
    9526             :  * When adding a many-to-many relationship
    9527             :  * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
    9528             :  * mapping table name (see GDALRelationship::GetMappingTableName) to instruct
    9529             :  * the driver to create an appropriately named and structured mapping table.
    9530             :  * Some dataset formats require particular naming conventions and field
    9531             :  * structures for the mapping table, and delegating the construction of the
    9532             :  * mapping table to the driver will avoid these pitfalls.
    9533             :  *
    9534             :  * @param relationship The relationship definition.
    9535             :  * @param failureReason      Output parameter. Will contain an error message if
    9536             :  *                           an error occurs.
    9537             :  * @return true in case of success.
    9538             :  * @since GDAL 3.6
    9539             :  */
    9540           0 : bool GDALDataset::AddRelationship(
    9541             :     CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
    9542             :     std::string &failureReason)
    9543             : {
    9544           0 :     failureReason = "AddRelationship not supported by this driver";
    9545           0 :     return false;
    9546             : }
    9547             : 
    9548             : /************************************************************************/
    9549             : /*                     GDALDatasetAddRelationship()                     */
    9550             : /************************************************************************/
    9551             : 
    9552             : /** Add a relationship to the dataset.
    9553             :  *
    9554             :  * Only a few drivers will support this operation, and some of them might only
    9555             :  * support it only for some types of relationships.
    9556             :  *
    9557             :  * A dataset having at least some support for this
    9558             :  * operation should report the GDsCAddRelationship dataset capability.
    9559             :  *
    9560             :  * Anticipated failures will not be emitted through the CPLError()
    9561             :  * infrastructure, but will be reported in the failureReason output parameter.
    9562             :  *
    9563             :  * When adding a many-to-many relationship
    9564             :  * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
    9565             :  * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the
    9566             :  * driver to create an appropriately named and structured mapping table. Some
    9567             :  * dataset formats require particular naming conventions and field structures
    9568             :  * for the mapping table, and delegating the construction of the mapping table
    9569             :  * to the driver will avoid these pitfalls.
    9570             :  *
    9571             :  * @param hDS                Dataset handle.
    9572             :  * @param hRelationship      The relationship definition. Contrary to the C++
    9573             :  * version, the passed object is copied.
    9574             :  * @param ppszFailureReason  Output parameter. Will contain an error message if
    9575             :  *                           an error occurs (*ppszFailureReason to be freed
    9576             :  *                           with CPLFree). May be NULL.
    9577             :  * @return true in case of success.
    9578             :  * @since GDAL 3.6
    9579             :  */
    9580          42 : bool GDALDatasetAddRelationship(GDALDatasetH hDS,
    9581             :                                 GDALRelationshipH hRelationship,
    9582             :                                 char **ppszFailureReason)
    9583             : {
    9584          42 :     VALIDATE_POINTER1(hDS, __func__, false);
    9585          42 :     VALIDATE_POINTER1(hRelationship, __func__, false);
    9586             :     std::unique_ptr<GDALRelationship> poRelationship(
    9587          84 :         new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
    9588          42 :     std::string failureReason;
    9589          84 :     const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(
    9590          42 :         std::move(poRelationship), failureReason);
    9591          42 :     if (ppszFailureReason)
    9592             :     {
    9593           0 :         *ppszFailureReason =
    9594           0 :             failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
    9595             :     }
    9596          42 :     return bRet;
    9597             : }
    9598             : 
    9599             : /************************************************************************/
    9600             : /*                        DeleteRelationship()                          */
    9601             : /************************************************************************/
    9602             : 
    9603             : /** Removes a relationship from the dataset.
    9604             :  *
    9605             :  * Only a few drivers will support this operation.
    9606             :  *
    9607             :  * A dataset having at least some support for this
    9608             :  * operation should report the GDsCDeleteRelationship dataset capability.
    9609             :  *
    9610             :  * Anticipated failures will not be emitted through the CPLError()
    9611             :  * infrastructure, but will be reported in the failureReason output parameter.
    9612             :  *
    9613             :  * @param name The relationship name.
    9614             :  * @param failureReason      Output parameter. Will contain an error message if
    9615             :  *                           an error occurs.
    9616             :  * @return true in case of success.
    9617             :  * @since GDAL 3.6
    9618             :  */
    9619           0 : bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,
    9620             :                                      std::string &failureReason)
    9621             : {
    9622           0 :     failureReason = "DeleteRelationship not supported by this driver";
    9623           0 :     return false;
    9624             : }
    9625             : 
    9626             : /************************************************************************/
    9627             : /*                  GDALDatasetDeleteRelationship()                     */
    9628             : /************************************************************************/
    9629             : 
    9630             : /** Removes a relationship from the dataset.
    9631             :  *
    9632             :  * Only a few drivers will support this operation.
    9633             :  *
    9634             :  * A dataset having at least some support for this
    9635             :  * operation should report the GDsCDeleteRelationship dataset capability.
    9636             :  *
    9637             :  * Anticipated failures will not be emitted through the CPLError()
    9638             :  * infrastructure, but will be reported in the ppszFailureReason output
    9639             :  * parameter.
    9640             :  *
    9641             :  * @param hDS                Dataset handle.
    9642             :  * @param pszName            The relationship name.
    9643             :  * @param ppszFailureReason  Output parameter. Will contain an error message if
    9644             :  *                           an error occurs (*ppszFailureReason to be freed
    9645             :  *                           with CPLFree). May be NULL.
    9646             :  * @return true in case of success.
    9647             :  * @since GDAL 3.6
    9648             :  */
    9649           6 : bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,
    9650             :                                    char **ppszFailureReason)
    9651             : {
    9652           6 :     VALIDATE_POINTER1(hDS, __func__, false);
    9653           6 :     VALIDATE_POINTER1(pszName, __func__, false);
    9654           6 :     std::string failureReason;
    9655          12 :     const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(
    9656           6 :         pszName, failureReason);
    9657           6 :     if (ppszFailureReason)
    9658             :     {
    9659           0 :         *ppszFailureReason =
    9660           0 :             failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
    9661             :     }
    9662           6 :     return bRet;
    9663             : }
    9664             : 
    9665             : /************************************************************************/
    9666             : /*                       UpdateRelationship()                           */
    9667             : /************************************************************************/
    9668             : 
    9669             : /** Updates an existing relationship by replacing its definition.
    9670             :  *
    9671             :  * The existing relationship with matching name will be replaced.
    9672             :  *
    9673             :  * Only a few drivers will support this operation, and some of them might only
    9674             :  * support it only for some types of relationships.
    9675             :  * A dataset having at least some support for this
    9676             :  * operation should report the GDsCUpdateRelationship dataset capability.
    9677             :  *
    9678             :  * Anticipated failures will not be emitted through the CPLError()
    9679             :  * infrastructure, but will be reported in the failureReason output parameter.
    9680             :  *
    9681             :  * @param relationship   The relationship definition.
    9682             :  * @param failureReason  Output parameter. Will contain an error message if
    9683             :  *                       an error occurs.
    9684             :  * @return true in case of success.
    9685             :  * @since GDAL 3.6
    9686             :  */
    9687           0 : bool GDALDataset::UpdateRelationship(
    9688             :     CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
    9689             :     std::string &failureReason)
    9690             : {
    9691           0 :     failureReason = "UpdateRelationship not supported by this driver";
    9692           0 :     return false;
    9693             : }
    9694             : 
    9695             : /************************************************************************/
    9696             : /*                  GDALDatasetUpdateRelationship()                     */
    9697             : /************************************************************************/
    9698             : 
    9699             : /** Updates an existing relationship by replacing its definition.
    9700             :  *
    9701             :  * The existing relationship with matching name will be replaced.
    9702             :  *
    9703             :  * Only a few drivers will support this operation, and some of them might only
    9704             :  * support it only for some types of relationships.
    9705             :  * A dataset having at least some support for this
    9706             :  * operation should report the GDsCUpdateRelationship dataset capability.
    9707             :  *
    9708             :  * Anticipated failures will not be emitted through the CPLError()
    9709             :  * infrastructure, but will be reported in the failureReason output parameter.
    9710             :  *
    9711             :  * @param hDS                Dataset handle.
    9712             :  * @param hRelationship      The relationship definition. Contrary to the C++
    9713             :  * version, the passed object is copied.
    9714             :  * @param ppszFailureReason  Output parameter. Will contain an error message if
    9715             :  *                           an error occurs (*ppszFailureReason to be freed
    9716             :  *                           with CPLFree). May be NULL.
    9717             :  * @return true in case of success.
    9718             :  * @since GDAL 3.5
    9719             :  */
    9720           9 : bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,
    9721             :                                    GDALRelationshipH hRelationship,
    9722             :                                    char **ppszFailureReason)
    9723             : {
    9724           9 :     VALIDATE_POINTER1(hDS, __func__, false);
    9725           9 :     VALIDATE_POINTER1(hRelationship, __func__, false);
    9726             :     std::unique_ptr<GDALRelationship> poRelationship(
    9727          18 :         new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
    9728           9 :     std::string failureReason;
    9729          18 :     const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(
    9730           9 :         std::move(poRelationship), failureReason);
    9731           9 :     if (ppszFailureReason)
    9732             :     {
    9733           0 :         *ppszFailureReason =
    9734           0 :             failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
    9735             :     }
    9736           9 :     return bRet;
    9737             : }
    9738             : 
    9739             : /************************************************************************/
    9740             : /*                  GDALDatasetSetQueryLoggerFunc()                     */
    9741             : /************************************************************************/
    9742             : 
    9743             : /**
    9744             :  * Sets the SQL query logger callback.
    9745             :  *
    9746             :  * When supported by the driver, the callback will be called with
    9747             :  * the executed SQL text, the error message, the execution time in milliseconds,
    9748             :  * the number of records fetched/affected and the client status data.
    9749             :  *
    9750             :  * A value of -1 in the execution time or in the number of records indicates
    9751             :  * that the values are unknown.
    9752             :  *
    9753             :  * @param hDS                   Dataset handle.
    9754             :  * @param pfnQueryLoggerFunc    Callback function
    9755             :  * @param poQueryLoggerArg      Opaque client status data
    9756             :  * @return                      true in case of success.
    9757             :  * @since                       GDAL 3.7
    9758             :  */
    9759           1 : bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,
    9760             :                                    GDALQueryLoggerFunc pfnQueryLoggerFunc,
    9761             :                                    void *poQueryLoggerArg)
    9762             : {
    9763           1 :     VALIDATE_POINTER1(hDS, __func__, false);
    9764           2 :     return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,
    9765           1 :                                                             poQueryLoggerArg);
    9766             : }
    9767             : 
    9768             : //! @cond Doxygen_Suppress
    9769             : 
    9770             : /************************************************************************/
    9771             : /*                       SetEnableOverviews()                           */
    9772             : /************************************************************************/
    9773             : 
    9774        7361 : void GDALDataset::SetEnableOverviews(bool bEnable)
    9775             : {
    9776        7361 :     if (m_poPrivate)
    9777             :     {
    9778        7361 :         m_poPrivate->m_bOverviewsEnabled = bEnable;
    9779             :     }
    9780        7361 : }
    9781             : 
    9782             : /************************************************************************/
    9783             : /*                      AreOverviewsEnabled()                           */
    9784             : /************************************************************************/
    9785             : 
    9786     1339160 : bool GDALDataset::AreOverviewsEnabled() const
    9787             : {
    9788     1339160 :     return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
    9789             : }
    9790             : 
    9791             : /************************************************************************/
    9792             : /*                             IsAllBands()                             */
    9793             : /************************************************************************/
    9794             : 
    9795          67 : bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const
    9796             : {
    9797          67 :     if (nBands != nBandCount)
    9798           1 :         return false;
    9799          66 :     if (panBandList)
    9800             :     {
    9801           3 :         for (int i = 0; i < nBandCount; ++i)
    9802             :         {
    9803           2 :             if (panBandList[i] != i + 1)
    9804           1 :                 return false;
    9805             :         }
    9806             :     }
    9807          65 :     return true;
    9808             : }
    9809             : 
    9810             : //! @endcond
    9811             : 
    9812             : /************************************************************************/
    9813             : /*                       GetCompressionFormats()                        */
    9814             : /************************************************************************/
    9815             : 
    9816             : /** Return the compression formats that can be natively obtained for the
    9817             :  * window of interest and requested bands.
    9818             :  *
    9819             :  * For example, a tiled dataset may be able to return data in a compressed
    9820             :  * format if the window of interest matches exactly a tile. For some formats,
    9821             :  * drivers may also be able to merge several tiles together (not currently
    9822             :  * implemented though).
    9823             :  *
    9824             :  * Each format string is a pseudo MIME type, whose first part can be passed
    9825             :  * as the pszFormat argument of ReadCompressedData(), with additional
    9826             :  * parameters specified as key=value with a semi-colon separator.
    9827             :  *
    9828             :  * The amount and types of optional parameters passed after the MIME type is
    9829             :  * format dependent, and driver dependent (some drivers might not be able to
    9830             :  * return those extra information without doing a rather costly processing).
    9831             :  *
    9832             :  * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
    9833             :  * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
    9834             :  * consequently "JPEG" can be passed as the pszFormat argument of
    9835             :  * ReadCompressedData(). For JPEG, implementations can use the
    9836             :  * GDALGetCompressionFormatForJPEG() helper method to generate a string like
    9837             :  * above from a JPEG codestream.
    9838             :  *
    9839             :  * Several values might be returned. For example,
    9840             :  * the JPEGXL driver will return "JXL", but also potentially "JPEG"
    9841             :  * if the JPEGXL codestream includes a JPEG reconstruction box.
    9842             :  *
    9843             :  * In the general case this method will return an empty list.
    9844             :  *
    9845             :  * This is the same as C function GDALDatasetGetCompressionFormats().
    9846             :  *
    9847             :  * @param nXOff The pixel offset to the top left corner of the region
    9848             :  * of the band to be accessed.  This would be zero to start from the left side.
    9849             :  *
    9850             :  * @param nYOff The line offset to the top left corner of the region
    9851             :  * of the band to be accessed.  This would be zero to start from the top.
    9852             :  *
    9853             :  * @param nXSize The width of the region of the band to be accessed in pixels.
    9854             :  *
    9855             :  * @param nYSize The height of the region of the band to be accessed in lines.
    9856             :  *
    9857             :  * @param nBandCount the number of bands being requested.
    9858             :  *
    9859             :  * @param panBandList the list of nBandCount band numbers.
    9860             :  * Note band numbers are 1 based. This may be NULL to select the first
    9861             :  * nBandCount bands.
    9862             :  *
    9863             :  * @return a list of compatible formats (which may be empty)
    9864             :  *
    9865             :  * For example, to check if native compression format(s) are available on the
    9866             :  * whole image:
    9867             :  * \code{.cpp}
    9868             :  *   const CPLStringList aosFormats =
    9869             :  *      poDataset->GetCompressionFormats(0, 0,
    9870             :  *                                       poDataset->GetRasterXSize(),
    9871             :  *                                       poDataset->GetRasterYSize(),
    9872             :  *                                       poDataset->GetRasterCount(),
    9873             :  *                                       nullptr);
    9874             :  *   for( const char* pszFormat: aosFormats )
    9875             :  *   {
    9876             :  *      // Remove optional parameters and just print out the MIME type.
    9877             :  *      const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));
    9878             :  *      printf("Found format %s\n, aosTokens[0]);
    9879             :  *   }
    9880             :  * \endcode
    9881             :  *
    9882             :  * @since GDAL 3.7
    9883             :  */
    9884             : CPLStringList
    9885           0 : GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
    9886             :                                    CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
    9887             :                                    CPL_UNUSED int nBandCount,
    9888             :                                    CPL_UNUSED const int *panBandList)
    9889             : {
    9890           0 :     return CPLStringList();
    9891             : }
    9892             : 
    9893             : /************************************************************************/
    9894             : /*                 GDALDatasetGetCompressionFormats()                   */
    9895             : /************************************************************************/
    9896             : 
    9897             : /** Return the compression formats that can be natively obtained for the
    9898             :  * window of interest and requested bands.
    9899             :  *
    9900             :  * For example, a tiled dataset may be able to return data in a compressed
    9901             :  * format if the window of interest matches exactly a tile. For some formats,
    9902             :  * drivers may also be able to merge several tiles together (not currently
    9903             :  * implemented though).
    9904             :  *
    9905             :  * Each format string is a pseudo MIME type, whose first part can be passed
    9906             :  * as the pszFormat argument of ReadCompressedData(), with additional
    9907             :  * parameters specified as key=value with a semi-colon separator.
    9908             :  *
    9909             :  * The amount and types of optional parameters passed after the MIME type is
    9910             :  * format dependent, and driver dependent (some drivers might not be able to
    9911             :  * return those extra information without doing a rather costly processing).
    9912             :  *
    9913             :  * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
    9914             :  * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
    9915             :  * consequently "JPEG" can be passed as the pszFormat argument of
    9916             :  * ReadCompressedData(). For JPEG, implementations can use the
    9917             :  * GDALGetCompressionFormatForJPEG() helper method to generate a string like
    9918             :  * above from a JPEG codestream.
    9919             :  *
    9920             :  * Several values might be returned. For example,
    9921             :  * the JPEGXL driver will return "JXL", but also potentially "JPEG"
    9922             :  * if the JPEGXL codestream includes a JPEG reconstruction box.
    9923             :  *
    9924             :  * In the general case this method will return an empty list.
    9925             :  *
    9926             :  * This is the same as C++ method GDALDataset::GetCompressionFormats().
    9927             :  *
    9928             :  * @param hDS Dataset handle.
    9929             :  *
    9930             :  * @param nXOff The pixel offset to the top left corner of the region
    9931             :  * of the band to be accessed.  This would be zero to start from the left side.
    9932             :  *
    9933             :  * @param nYOff The line offset to the top left corner of the region
    9934             :  * of the band to be accessed.  This would be zero to start from the top.
    9935             :  *
    9936             :  * @param nXSize The width of the region of the band to be accessed in pixels.
    9937             :  *
    9938             :  * @param nYSize The height of the region of the band to be accessed in lines.
    9939             :  *
    9940             :  * @param nBandCount the number of bands being requested.
    9941             :  *
    9942             :  * @param panBandList the list of nBandCount band numbers.
    9943             :  * Note band numbers are 1 based. This may be NULL to select the first
    9944             :  * nBandCount bands.
    9945             :  *
    9946             :  * @return a list of compatible formats (which may be empty) that should be
    9947             :  * freed with CSLDestroy(), or nullptr.
    9948             :  *
    9949             :  * @since GDAL 3.7
    9950             :  */
    9951           9 : char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,
    9952             :                                         int nXSize, int nYSize, int nBandCount,
    9953             :                                         const int *panBandList)
    9954             : {
    9955           9 :     VALIDATE_POINTER1(hDS, __func__, nullptr);
    9956           9 :     return GDALDataset::FromHandle(hDS)
    9957           9 :         ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,
    9958           9 :                                 panBandList)
    9959           9 :         .StealList();
    9960             : }
    9961             : 
    9962             : /************************************************************************/
    9963             : /*                         ReadCompressedData()                         */
    9964             : /************************************************************************/
    9965             : 
    9966             : /** Return the compressed content that can be natively obtained for the
    9967             :  * window of interest and requested bands.
    9968             :  *
    9969             :  * For example, a tiled dataset may be able to return data in compressed format
    9970             :  * if the window of interest matches exactly a tile. For some formats, drivers
    9971             :  * may also be example to merge several tiles together (not currently
    9972             :  * implemented though).
    9973             :  *
    9974             :  * The implementation should make sure that the content returned forms a valid
    9975             :  * standalone file. For example, for the GeoTIFF implementation of this method,
    9976             :  * when extracting a JPEG tile, the method will automatically add the content
    9977             :  * of the JPEG Huffman and/or quantization tables that might be stored in the
    9978             :  * TIFF JpegTables tag, and not in tile data itself.
    9979             :  *
    9980             :  * In the general case this method will return CE_Failure.
    9981             :  *
    9982             :  * This is the same as C function GDALDatasetReadCompressedData().
    9983             :  *
    9984             :  * @param pszFormat Requested compression format (e.g. "JPEG",
    9985             :  * "WEBP", "JXL"). This is the MIME type of one of the values
    9986             :  * returned by GetCompressionFormats(). The format string is designed to
    9987             :  * potentially include at a later point key=value optional parameters separated
    9988             :  * by a semi-colon character. At time of writing, none are implemented.
    9989             :  * ReadCompressedData() implementations should verify optional parameters and
    9990             :  * return CE_Failure if they cannot support one of them.
    9991             :  *
    9992             :  * @param nXOff The pixel offset to the top left corner of the region
    9993             :  * of the band to be accessed.  This would be zero to start from the left side.
    9994             :  *
    9995             :  * @param nYOff The line offset to the top left corner of the region
    9996             :  * of the band to be accessed.  This would be zero to start from the top.
    9997             :  *
    9998             :  * @param nXSize The width of the region of the band to be accessed in pixels.
    9999             :  *
   10000             :  * @param nYSize The height of the region of the band to be accessed in lines.
   10001             :  *
   10002             :  * @param nBandCount the number of bands being requested.
   10003             :  *
   10004             :  * @param panBandList the list of nBandCount band numbers.
   10005             :  * Note band numbers are 1 based. This may be NULL to select the first
   10006             :  * nBandCount bands.
   10007             :  *
   10008             :  * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
   10009             :  * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
   10010             :  * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
   10011             :  * buffer will be filled with the compressed data, provided that pnBufferSize
   10012             :  * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
   10013             :  * of *ppBuffer, is sufficiently large to hold the data.
   10014             :  * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
   10015             :  * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
   10016             :  * free it with VSIFree().
   10017             :  * If ppBuffer is nullptr, then the compressed data itself will not be returned,
   10018             :  * but *pnBufferSize will be updated with an upper bound of the size that would
   10019             :  * be necessary to hold it (if pnBufferSize != nullptr).
   10020             :  *
   10021             :  * @param pnBufferSize Output buffer size, or nullptr.
   10022             :  * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
   10023             :  * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
   10024             :  * method is successful, *pnBufferSize will be updated with the actual size
   10025             :  * used.
   10026             :  *
   10027             :  * @param ppszDetailedFormat Pointer to an output string, or nullptr.
   10028             :  * If ppszDetailedFormat is not nullptr, then, on success, the method will
   10029             :  * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
   10030             :  * *ppszDetailedFormat might contain strings like
   10031             :  * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
   10032             :  * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
   10033             :  * The string will contain at least as much information as what
   10034             :  * GetCompressionFormats() returns, and potentially more when
   10035             :  * ppBuffer != nullptr.
   10036             :  *
   10037             :  * @return CE_None in case of success, CE_Failure otherwise.
   10038             :  *
   10039             :  * For example, to request JPEG content on the whole image and let GDAL deal
   10040             :  * with the buffer allocation.
   10041             :  * \code{.cpp}
   10042             :  *   void* pBuffer = nullptr;
   10043             :  *   size_t nBufferSize = 0;
   10044             :  *   CPLErr eErr =
   10045             :  *      poDataset->ReadCompressedData("JPEG",
   10046             :  *                                    0, 0,
   10047             :  *                                    poDataset->GetRasterXSize(),
   10048             :  *                                    poDataset->GetRasterYSize(),
   10049             :  *                                    poDataset->GetRasterCount(),
   10050             :  *                                    nullptr, // panBandList
   10051             :  *                                    &pBuffer,
   10052             :  *                                    &nBufferSize,
   10053             :  *                                    nullptr // ppszDetailedFormat
   10054             :  *                                   );
   10055             :  *   if (eErr == CE_None)
   10056             :  *   {
   10057             :  *       CPLAssert(pBuffer != nullptr);
   10058             :  *       CPLAssert(nBufferSize > 0);
   10059             :  *       VSILFILE* fp = VSIFOpenL("my.jpeg", "wb");
   10060             :  *       if (fp)
   10061             :  *       {
   10062             :  *           VSIFWriteL(pBuffer, nBufferSize, 1, fp);
   10063             :  *           VSIFCloseL(fp);
   10064             :  *       }
   10065             :  *       VSIFree(pBuffer);
   10066             :  *   }
   10067             :  * \endcode
   10068             :  *
   10069             :  * Or to manage the buffer allocation on your side:
   10070             :  * \code{.cpp}
   10071             :  *   size_t nUpperBoundBufferSize = 0;
   10072             :  *   CPLErr eErr =
   10073             :  *      poDataset->ReadCompressedData("JPEG",
   10074             :  *                                    0, 0,
   10075             :  *                                    poDataset->GetRasterXSize(),
   10076             :  *                                    poDataset->GetRasterYSize(),
   10077             :  *                                    poDataset->GetRasterCount(),
   10078             :  *                                    nullptr, // panBandList
   10079             :  *                                    nullptr, // ppBuffer,
   10080             :  *                                    &nUpperBoundBufferSize,
   10081             :  *                                    nullptr // ppszDetailedFormat
   10082             :  *                                   );
   10083             :  *   if (eErr == CE_None)
   10084             :  *   {
   10085             :  *       std::vector<uint8_t> myBuffer;
   10086             :  *       myBuffer.resize(nUpperBoundBufferSize);
   10087             :  *       void* pBuffer = myBuffer.data();
   10088             :  *       size_t nActualSize = nUpperBoundBufferSize;
   10089             :  *       char* pszDetailedFormat = nullptr;
   10090             :  *       // We also request detailed format, but we could have passed it to
   10091             :  *       // nullptr as well.
   10092             :  *       eErr =
   10093             :  *         poDataset->ReadCompressedData("JPEG",
   10094             :  *                                       0, 0,
   10095             :  *                                       poDataset->GetRasterXSize(),
   10096             :  *                                       poDataset->GetRasterYSize(),
   10097             :  *                                       poDataset->GetRasterCount(),
   10098             :  *                                       nullptr, // panBandList
   10099             :  *                                       &pBuffer,
   10100             :  *                                       &nActualSize,
   10101             :  *                                       &pszDetailedFormat);
   10102             :  *       if (eErr == CE_None)
   10103             :  *       {
   10104             :  *          CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified
   10105             :  *          CPLAssert(nActualSize <= nUpperBoundBufferSize);
   10106             :  *          myBuffer.resize(nActualSize);
   10107             :  *          // do something useful
   10108             :  *          VSIFree(pszDetailedFormat);
   10109             :  *       }
   10110             :  *   }
   10111             :  * \endcode
   10112             :  *
   10113             :  * @since GDAL 3.7
   10114             :  */
   10115         418 : CPLErr GDALDataset::ReadCompressedData(
   10116             :     CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,
   10117             :     CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
   10118             :     CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,
   10119             :     CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,
   10120             :     CPL_UNUSED char **ppszDetailedFormat)
   10121             : {
   10122         418 :     return CE_Failure;
   10123             : }
   10124             : 
   10125             : /************************************************************************/
   10126             : /*                  GDALDatasetReadCompressedData()                     */
   10127             : /************************************************************************/
   10128             : 
   10129             : /** Return the compressed content that can be natively obtained for the
   10130             :  * window of interest and requested bands.
   10131             :  *
   10132             :  * For example, a tiled dataset may be able to return data in compressed format
   10133             :  * if the window of interest matches exactly a tile. For some formats, drivers
   10134             :  * may also be example to merge several tiles together (not currently
   10135             :  * implemented though).
   10136             :  *
   10137             :  * The implementation should make sure that the content returned forms a valid
   10138             :  * standalone file. For example, for the GeoTIFF implementation of this method,
   10139             :  * when extracting a JPEG tile, the method will automatically adds the content
   10140             :  * of the JPEG Huffman and/or quantization tables that might be stored in the
   10141             :  * TIFF JpegTables tag, and not in tile data itself.
   10142             :  *
   10143             :  * In the general case this method will return CE_Failure.
   10144             :  *
   10145             :  * This is the same as C++ method GDALDataset:ReadCompressedData().
   10146             :  *
   10147             :  * @param hDS Dataset handle.
   10148             :  *
   10149             :  * @param pszFormat Requested compression format (e.g. "JPEG",
   10150             :  * "WEBP", "JXL"). This is the MIME type of one of the values
   10151             :  * returned by GetCompressionFormats(). The format string is designed to
   10152             :  * potentially include at a later point key=value optional parameters separated
   10153             :  * by a semi-colon character. At time of writing, none are implemented.
   10154             :  * ReadCompressedData() implementations should verify optional parameters and
   10155             :  * return CE_Failure if they cannot support one of them.
   10156             :  *
   10157             :  * @param nXOff The pixel offset to the top left corner of the region
   10158             :  * of the band to be accessed.  This would be zero to start from the left side.
   10159             :  *
   10160             :  * @param nYOff The line offset to the top left corner of the region
   10161             :  * of the band to be accessed.  This would be zero to start from the top.
   10162             :  *
   10163             :  * @param nXSize The width of the region of the band to be accessed in pixels.
   10164             :  *
   10165             :  * @param nYSize The height of the region of the band to be accessed in lines.
   10166             :  *
   10167             :  * @param nBandCount the number of bands being requested.
   10168             :  *
   10169             :  * @param panBandList the list of nBandCount band numbers.
   10170             :  * Note band numbers are 1 based. This may be NULL to select the first
   10171             :  * nBandCount bands.
   10172             :  *
   10173             :  * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
   10174             :  * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
   10175             :  * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
   10176             :  * buffer will be filled with the compressed data, provided that pnBufferSize
   10177             :  * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
   10178             :  * of *ppBuffer, is sufficiently large to hold the data.
   10179             :  * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
   10180             :  * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
   10181             :  * free it with VSIFree().
   10182             :  * If ppBuffer is nullptr, then the compressed data itself will not be returned,
   10183             :  * but *pnBufferSize will be updated with an upper bound of the size that would
   10184             :  * be necessary to hold it (if pnBufferSize != nullptr).
   10185             :  *
   10186             :  * @param pnBufferSize Output buffer size, or nullptr.
   10187             :  * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
   10188             :  * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
   10189             :  * method is successful, *pnBufferSize will be updated with the actual size
   10190             :  * used.
   10191             :  *
   10192             :  * @param ppszDetailedFormat Pointer to an output string, or nullptr.
   10193             :  * If ppszDetailedFormat is not nullptr, then, on success, the method will
   10194             :  * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
   10195             :  * *ppszDetailedFormat might contain strings like
   10196             :  * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
   10197             :  * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
   10198             :  * The string will contain at least as much information as what
   10199             :  * GetCompressionFormats() returns, and potentially more when
   10200             :  * ppBuffer != nullptr.
   10201             :  *
   10202             :  * @return CE_None in case of success, CE_Failure otherwise.
   10203             :  *
   10204             :  * @since GDAL 3.7
   10205             :  */
   10206          28 : CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,
   10207             :                                      int nXOff, int nYOff, int nXSize,
   10208             :                                      int nYSize, int nBandCount,
   10209             :                                      const int *panBandList, void **ppBuffer,
   10210             :                                      size_t *pnBufferSize,
   10211             :                                      char **ppszDetailedFormat)
   10212             : {
   10213          28 :     VALIDATE_POINTER1(hDS, __func__, CE_Failure);
   10214          56 :     return GDALDataset::FromHandle(hDS)->ReadCompressedData(
   10215             :         pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,
   10216          28 :         ppBuffer, pnBufferSize, ppszDetailedFormat);
   10217             : }
   10218             : 
   10219             : /************************************************************************/
   10220             : /*                           CanBeCloned()                              */
   10221             : /************************************************************************/
   10222             : 
   10223             : //! @cond Doxygen_Suppress
   10224             : 
   10225             : /** This method is called by GDALThreadSafeDataset::Create() to determine if
   10226             :  * it is possible to create a thread-safe wrapper for a dataset, which involves
   10227             :  * the ability to Clone() it.
   10228             :  *
   10229             :  * Implementations of this method must be thread-safe.
   10230             :  *
   10231             :  * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
   10232             :  *                    expressing the intended use for thread-safety.
   10233             :  *                    Currently, the only valid scope is in the base
   10234             :  *                    implementation is GDAL_OF_RASTER.
   10235             :  * @param bCanShareState Determines if cloned datasets are allowed to share
   10236             :  *                       state with the dataset they have been cloned from.
   10237             :  *                       If set to true, the dataset from which they have been
   10238             :  *                       cloned from must remain opened during the lifetime of
   10239             :  *                       its clones.
   10240             :  * @return true if the Clone() method is expected to succeed with the same values
   10241             :  *         of nScopeFlags and bCanShareState.
   10242             :  */
   10243         125 : bool GDALDataset::CanBeCloned(int nScopeFlags,
   10244             :                               [[maybe_unused]] bool bCanShareState) const
   10245             : {
   10246         125 :     return m_bCanBeReopened && nScopeFlags == GDAL_OF_RASTER;
   10247             : }
   10248             : 
   10249             : //! @endcond
   10250             : 
   10251             : /************************************************************************/
   10252             : /*                               Clone()                                */
   10253             : /************************************************************************/
   10254             : 
   10255             : //! @cond Doxygen_Suppress
   10256             : 
   10257             : /** This method "clones" the current dataset, that is it returns a new instance
   10258             :  * that is opened on the same underlying "file".
   10259             :  *
   10260             :  * The base implementation uses GDALDataset::Open() to re-open the dataset.
   10261             :  * The MEM driver has a specialized implementation that returns a new instance,
   10262             :  * but which shares the same memory buffer as this.
   10263             :  *
   10264             :  * Implementations of this method must be thread-safe.
   10265             :  *
   10266             :  * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
   10267             :  *                    expressing the intended use for thread-safety.
   10268             :  *                    Currently, the only valid scope is in the base
   10269             :  *                    implementation is GDAL_OF_RASTER.
   10270             :  * @param bCanShareState Determines if cloned datasets are allowed to share
   10271             :  *                       state with the dataset they have been cloned from.
   10272             :  *                       If set to true, the dataset from which they have been
   10273             :  *                       cloned from must remain opened during the lifetime of
   10274             :  *                       its clones.
   10275             :  * @return a new instance, or nullptr in case of error.
   10276             :  */
   10277             : std::unique_ptr<GDALDataset>
   10278        2027 : GDALDataset::Clone(int nScopeFlags, [[maybe_unused]] bool bCanShareState) const
   10279             : {
   10280        4054 :     CPLStringList aosAllowedDrivers;
   10281        2027 :     if (poDriver)
   10282        2027 :         aosAllowedDrivers.AddString(poDriver->GetDescription());
   10283             :     return std::unique_ptr<GDALDataset>(GDALDataset::Open(
   10284        2027 :         GetDescription(),
   10285        2027 :         nScopeFlags | GDAL_OF_INTERNAL | GDAL_OF_VERBOSE_ERROR,
   10286        4054 :         aosAllowedDrivers.List(), papszOpenOptions));
   10287             : }
   10288             : 
   10289             : //! @endcond

Generated by: LCOV version 1.14