/src/gdal/gcore/gdaldataset.cpp
Line  | Count  | Source (jump to first uncovered line)  | 
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 "gdal_alg.h"  | 
40  |  | #include "ogr_api.h"  | 
41  |  | #include "ogr_attrind.h"  | 
42  |  | #include "ogr_core.h"  | 
43  |  | #include "ogr_feature.h"  | 
44  |  | #include "ogr_featurestyle.h"  | 
45  |  | #include "ogr_gensql.h"  | 
46  |  | #include "ogr_geometry.h"  | 
47  |  | #include "ogr_p.h"  | 
48  |  | #include "ogr_spatialref.h"  | 
49  |  | #include "ogr_srs_api.h"  | 
50  |  | #include "ograpispy.h"  | 
51  |  | #include "ogrsf_frmts.h"  | 
52  |  | #include "ogrunionlayer.h"  | 
53  |  | #include "ogr_swq.h"  | 
54  |  |  | 
55  |  | #include "../frmts/derived/derivedlist.h"  | 
56  |  |  | 
57  |  | #ifdef SQLITE_ENABLED  | 
58  |  | #include "../sqlite/ogrsqliteexecutesql.h"  | 
59  |  | #endif  | 
60  |  |  | 
61  |  | extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];  | 
62  |  |  | 
63  |  | CPL_C_START  | 
64  |  | GDALAsyncReader *GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff,  | 
65  |  |                                            int nYOff, int nXSize, int nYSize,  | 
66  |  |                                            void *pBuf, int nBufXSize,  | 
67  |  |                                            int nBufYSize, GDALDataType eBufType,  | 
68  |  |                                            int nBandCount, int *panBandMap,  | 
69  |  |                                            int nPixelSpace, int nLineSpace,  | 
70  |  |                                            int nBandSpace, char **papszOptions);  | 
71  |  | CPL_C_END  | 
72  |  |  | 
73  |  | enum class GDALAllowReadWriteMutexState  | 
74  |  | { | 
75  |  |     RW_MUTEX_STATE_UNKNOWN,  | 
76  |  |     RW_MUTEX_STATE_ALLOWED,  | 
77  |  |     RW_MUTEX_STATE_DISABLED  | 
78  |  | };  | 
79  |  |  | 
80  |  | const GIntBig TOTAL_FEATURES_NOT_INIT = -2;  | 
81  |  | const GIntBig TOTAL_FEATURES_UNKNOWN = -1;  | 
82  |  |  | 
83  |  | class GDALDataset::Private  | 
84  |  | { | 
85  |  |     CPL_DISALLOW_COPY_ASSIGN(Private)  | 
86  |  |  | 
87  |  |   public:  | 
88  |  |     CPLMutex *hMutex = nullptr;  | 
89  |  |     std::map<GIntBig, int> oMapThreadToMutexTakenCount{}; | 
90  |  | #ifdef DEBUG_EXTRA  | 
91  |  |     std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{}; | 
92  |  | #endif  | 
93  |  |     GDALAllowReadWriteMutexState eStateReadWriteMutex =  | 
94  |  |         GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;  | 
95  |  |     int nCurrentLayerIdx = 0;  | 
96  |  |     int nLayerCount = -1;  | 
97  |  |     GIntBig nFeatureReadInLayer = 0;  | 
98  |  |     GIntBig nFeatureReadInDataset = 0;  | 
99  |  |     GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;  | 
100  |  |     GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;  | 
101  |  |     OGRLayer *poCurrentLayer = nullptr;  | 
102  |  |  | 
103  |  |     std::mutex m_oMutexWKT{}; | 
104  |  |  | 
105  |  |     char *m_pszWKTCached = nullptr;  | 
106  |  |     OGRSpatialReference *m_poSRSCached = nullptr;  | 
107  |  |     char *m_pszWKTGCPCached = nullptr;  | 
108  |  |     OGRSpatialReference *m_poSRSGCPCached = nullptr;  | 
109  |  |  | 
110  |  |     GDALDataset *poParentDataset = nullptr;  | 
111  |  |  | 
112  |  |     bool m_bOverviewsEnabled = true;  | 
113  |  |  | 
114  |  |     std::vector<int>  | 
115  |  |         m_anBandMap{};  // used by RasterIO(). Values are 1, 2, etc. | 
116  |  |  | 
117  | 0  |     Private() = default;  | 
118  |  | };  | 
119  |  |  | 
120  |  | struct SharedDatasetCtxt  | 
121  |  | { | 
122  |  |     // PID of the thread that mark the dataset as shared  | 
123  |  |     // This may not be the actual PID, but the responsiblePID.  | 
124  |  |     GIntBig nPID;  | 
125  |  |     char *pszDescription;  | 
126  |  |     char *pszConcatenatedOpenOptions;  | 
127  |  |     int nOpenFlags;  | 
128  |  |  | 
129  |  |     GDALDataset *poDS;  | 
130  |  | };  | 
131  |  |  | 
132  |  | // Set of datasets opened as shared datasets (with GDALOpenShared)  | 
133  |  | // The values in the set are of type SharedDatasetCtxt.  | 
134  |  | static CPLHashSet *phSharedDatasetSet = nullptr;  | 
135  |  |  | 
136  |  | // Set of all datasets created in the constructor of GDALDataset.  | 
137  |  | // In the case of a shared dataset, memorize the PID of the thread  | 
138  |  | // that marked the dataset as shared, so that we can remove it from  | 
139  |  | // the phSharedDatasetSet in the destructor of the dataset, even  | 
140  |  | // if GDALClose is called from a different thread.  | 
141  |  | static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;  | 
142  |  |  | 
143  |  | static CPLMutex *hDLMutex = nullptr;  | 
144  |  |  | 
145  |  | // Static array of all datasets. Used by GDALGetOpenDatasets.  | 
146  |  | // Not thread-safe. See GDALGetOpenDatasets.  | 
147  |  | static GDALDataset **ppDatasets = nullptr;  | 
148  |  |  | 
149  |  | static unsigned long GDALSharedDatasetHashFunc(const void *elt)  | 
150  | 0  | { | 
151  | 0  |     const SharedDatasetCtxt *psStruct =  | 
152  | 0  |         static_cast<const SharedDatasetCtxt *>(elt);  | 
153  | 0  |     return static_cast<unsigned long>(  | 
154  | 0  |         CPLHashSetHashStr(psStruct->pszDescription) ^  | 
155  | 0  |         CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^  | 
156  | 0  |         psStruct->nOpenFlags ^ psStruct->nPID);  | 
157  | 0  | }  | 
158  |  |  | 
159  |  | static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)  | 
160  | 0  | { | 
161  | 0  |     const SharedDatasetCtxt *psStruct1 =  | 
162  | 0  |         static_cast<const SharedDatasetCtxt *>(elt1);  | 
163  | 0  |     const SharedDatasetCtxt *psStruct2 =  | 
164  | 0  |         static_cast<const SharedDatasetCtxt *>(elt2);  | 
165  | 0  |     return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&  | 
166  | 0  |            strcmp(psStruct1->pszConcatenatedOpenOptions,  | 
167  | 0  |                   psStruct2->pszConcatenatedOpenOptions) == 0 &&  | 
168  | 0  |            psStruct1->nPID == psStruct2->nPID &&  | 
169  | 0  |            psStruct1->nOpenFlags == psStruct2->nOpenFlags;  | 
170  | 0  | }  | 
171  |  |  | 
172  |  | static void GDALSharedDatasetFreeFunc(void *elt)  | 
173  | 0  | { | 
174  | 0  |     SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);  | 
175  | 0  |     CPLFree(psStruct->pszDescription);  | 
176  | 0  |     CPLFree(psStruct->pszConcatenatedOpenOptions);  | 
177  | 0  |     CPLFree(psStruct);  | 
178  | 0  | }  | 
179  |  |  | 
180  |  | static std::string  | 
181  |  | GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)  | 
182  | 0  | { | 
183  | 0  |     std::string osStr;  | 
184  | 0  |     for (const char *pszOption : cpl::Iterate(papszOpenOptions))  | 
185  | 0  |         osStr += pszOption;  | 
186  | 0  |     return osStr;  | 
187  | 0  | }  | 
188  |  |  | 
189  |  | /************************************************************************/  | 
190  |  | /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */  | 
191  |  | /************************************************************************/  | 
192  |  |  | 
193  |  | // The open-shared mutex must be used by the ProxyPool too.  | 
194  |  | CPLMutex **GDALGetphDLMutex()  | 
195  | 0  | { | 
196  | 0  |     return &hDLMutex;  | 
197  | 0  | }  | 
198  |  |  | 
199  |  | // The current thread will act in the behalf of the thread of PID  | 
200  |  | // responsiblePID.  | 
201  |  | void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)  | 
202  | 0  | { | 
203  | 0  |     GIntBig *pResponsiblePID =  | 
204  | 0  |         static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));  | 
205  | 0  |     if (pResponsiblePID == nullptr)  | 
206  | 0  |     { | 
207  | 0  |         pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));  | 
208  | 0  |         CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);  | 
209  | 0  |     }  | 
210  | 0  |     *pResponsiblePID = responsiblePID;  | 
211  | 0  | }  | 
212  |  |  | 
213  |  | // Get the PID of the thread that the current thread will act in the behalf of  | 
214  |  | // By default : the current thread acts in the behalf of itself.  | 
215  |  | GIntBig GDALGetResponsiblePIDForCurrentThread()  | 
216  | 0  | { | 
217  | 0  |     GIntBig *pResponsiblePID =  | 
218  | 0  |         static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));  | 
219  | 0  |     if (pResponsiblePID == nullptr)  | 
220  | 0  |         return CPLGetPID();  | 
221  | 0  |     return *pResponsiblePID;  | 
222  | 0  | }  | 
223  |  |  | 
224  |  | /************************************************************************/  | 
225  |  | /* ==================================================================== */  | 
226  |  | /*                             GDALDataset                              */  | 
227  |  | /* ==================================================================== */  | 
228  |  | /************************************************************************/  | 
229  |  |  | 
230  |  | /**  | 
231  |  |  * \class GDALDataset "gdal_priv.h"  | 
232  |  |  *  | 
233  |  |  * A dataset encapsulating one or more raster bands.  Details are further  | 
234  |  |  * discussed in the <a href="https://gdal.org/user/raster_data_model.html">GDAL  | 
235  |  |  * Raster Data Model</a>.  | 
236  |  |  *  | 
237  |  |  * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,  | 
238  |  |  * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new  | 
239  |  |  * dataset.  | 
240  |  |  */  | 
241  |  |  | 
242  |  | /************************************************************************/  | 
243  |  | /*                            GDALDataset()                             */  | 
244  |  | /************************************************************************/  | 
245  |  |  | 
246  |  | //! @cond Doxygen_Suppress  | 
247  |  | GDALDataset::GDALDataset()  | 
248  | 0  |     : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO"))) | 
249  | 0  | { | 
250  | 0  | }  | 
251  |  |  | 
252  |  | GDALDataset::GDALDataset(int bForceCachedIOIn)  | 
253  | 0  |     : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),  | 
254  | 0  |       m_poPrivate(new(std::nothrow) GDALDataset::Private)  | 
255  | 0  | { | 
256  | 0  | }  | 
257  |  |  | 
258  |  | //! @endcond  | 
259  |  |  | 
260  |  | /************************************************************************/  | 
261  |  | /*                            ~GDALDataset()                            */  | 
262  |  | /************************************************************************/  | 
263  |  |  | 
264  |  | /**  | 
265  |  |  * \brief Destroy an open GDALDataset.  | 
266  |  |  *  | 
267  |  |  * This is the accepted method of closing a GDAL dataset and deallocating  | 
268  |  |  * all resources associated with it.  | 
269  |  |  *  | 
270  |  |  * Equivalent of the C callable GDALClose().  Except that GDALClose() first  | 
271  |  |  * decrements the reference count, and then closes only if it has dropped to  | 
272  |  |  * zero.  | 
273  |  |  *  | 
274  |  |  * For Windows users, it is not recommended to use the delete operator on the  | 
275  |  |  * dataset object because of known issues when allocating and freeing memory  | 
276  |  |  * across module boundaries. Calling GDALClose() is then a better option.  | 
277  |  |  */  | 
278  |  |  | 
279  |  | GDALDataset::~GDALDataset()  | 
280  |  |  | 
281  | 0  | { | 
282  |  |     // we don't want to report destruction of datasets that  | 
283  |  |     // were never really open or meant as internal  | 
284  | 0  |     if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))  | 
285  | 0  |     { | 
286  | 0  |         if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())  | 
287  | 0  |             CPLDebug("GDAL", | 
288  | 0  |                      "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",  | 
289  | 0  |                      GetDescription(), this, static_cast<int>(CPLGetPID()),  | 
290  | 0  |                      static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));  | 
291  | 0  |         else  | 
292  | 0  |             CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this); | 
293  | 0  |     }  | 
294  |  | 
  | 
295  | 0  |     if (IsMarkedSuppressOnClose())  | 
296  | 0  |     { | 
297  | 0  |         if (poDriver == nullptr ||  | 
298  |  |             // Someone issuing Create("foo.tif") on a | 
299  |  |             // memory driver doesn't expect files with those names to be deleted  | 
300  |  |             // on a file system...  | 
301  |  |             // This is somewhat messy. Ideally there should be a way for the  | 
302  |  |             // driver to overload the default behavior  | 
303  | 0  |             (!EQUAL(poDriver->GetDescription(), "MEM") &&  | 
304  | 0  |              !EQUAL(poDriver->GetDescription(), "Memory")))  | 
305  | 0  |         { | 
306  | 0  |             VSIUnlink(GetDescription());  | 
307  | 0  |         }  | 
308  | 0  |     }  | 
309  |  |  | 
310  |  |     /* -------------------------------------------------------------------- */  | 
311  |  |     /*      Remove dataset from the "open" dataset list.                    */  | 
312  |  |     /* -------------------------------------------------------------------- */  | 
313  | 0  |     if (!bIsInternal)  | 
314  | 0  |     { | 
315  | 0  |         CPLMutexHolderD(&hDLMutex);  | 
316  | 0  |         if (poAllDatasetMap)  | 
317  | 0  |         { | 
318  | 0  |             std::map<GDALDataset *, GIntBig>::iterator oIter =  | 
319  | 0  |                 poAllDatasetMap->find(this);  | 
320  | 0  |             CPLAssert(oIter != poAllDatasetMap->end());  | 
321  |  |  | 
322  | 0  |             UnregisterFromSharedDataset();  | 
323  |  | 
  | 
324  | 0  |             poAllDatasetMap->erase(oIter);  | 
325  |  | 
  | 
326  | 0  |             if (poAllDatasetMap->empty())  | 
327  | 0  |             { | 
328  | 0  |                 delete poAllDatasetMap;  | 
329  | 0  |                 poAllDatasetMap = nullptr;  | 
330  | 0  |                 if (phSharedDatasetSet)  | 
331  | 0  |                 { | 
332  | 0  |                     CPLHashSetDestroy(phSharedDatasetSet);  | 
333  | 0  |                 }  | 
334  | 0  |                 phSharedDatasetSet = nullptr;  | 
335  | 0  |                 CPLFree(ppDatasets);  | 
336  | 0  |                 ppDatasets = nullptr;  | 
337  | 0  |             }  | 
338  | 0  |         }  | 
339  | 0  |     }  | 
340  |  |  | 
341  |  |     /* -------------------------------------------------------------------- */  | 
342  |  |     /*      Destroy the raster bands if they exist.                         */  | 
343  |  |     /* -------------------------------------------------------------------- */  | 
344  | 0  |     for (int i = 0; i < nBands && papoBands != nullptr; ++i)  | 
345  | 0  |     { | 
346  | 0  |         if (papoBands[i] != nullptr)  | 
347  | 0  |             delete papoBands[i];  | 
348  | 0  |         papoBands[i] = nullptr;  | 
349  | 0  |     }  | 
350  |  | 
  | 
351  | 0  |     CPLFree(papoBands);  | 
352  |  | 
  | 
353  | 0  |     if (m_poStyleTable)  | 
354  | 0  |     { | 
355  | 0  |         delete m_poStyleTable;  | 
356  | 0  |         m_poStyleTable = nullptr;  | 
357  | 0  |     }  | 
358  |  | 
  | 
359  | 0  |     if (m_poPrivate != nullptr)  | 
360  | 0  |     { | 
361  | 0  |         if (m_poPrivate->hMutex != nullptr)  | 
362  | 0  |             CPLDestroyMutex(m_poPrivate->hMutex);  | 
363  |  | 
  | 
364  | 0  | #if defined(__COVERITY__) || defined(DEBUG)  | 
365  |  |         // Not needed since at destruction there is no risk of concurrent use.  | 
366  | 0  |         std::lock_guard oLock(m_poPrivate->m_oMutexWKT);  | 
367  | 0  | #endif  | 
368  | 0  |         CPLFree(m_poPrivate->m_pszWKTCached);  | 
369  | 0  |         if (m_poPrivate->m_poSRSCached)  | 
370  | 0  |         { | 
371  | 0  |             m_poPrivate->m_poSRSCached->Release();  | 
372  | 0  |         }  | 
373  | 0  |         CPLFree(m_poPrivate->m_pszWKTGCPCached);  | 
374  | 0  |         if (m_poPrivate->m_poSRSGCPCached)  | 
375  | 0  |         { | 
376  | 0  |             m_poPrivate->m_poSRSGCPCached->Release();  | 
377  | 0  |         }  | 
378  | 0  |     }  | 
379  |  | 
  | 
380  | 0  |     delete m_poPrivate;  | 
381  |  | 
  | 
382  | 0  |     CSLDestroy(papszOpenOptions);  | 
383  | 0  | }  | 
384  |  |  | 
385  |  | /************************************************************************/  | 
386  |  | /*                             Close()                                  */  | 
387  |  | /************************************************************************/  | 
388  |  |  | 
389  |  | /** Do final cleanup before a dataset is destroyed.  | 
390  |  |  *  | 
391  |  |  * This method is typically called by GDALClose() or the destructor of a  | 
392  |  |  * GDALDataset subclass. It might also be called by C++ users before  | 
393  |  |  * destroying a dataset. It should not be called on a shared dataset whose  | 
394  |  |  * reference count is greater than one.  | 
395  |  |  *  | 
396  |  |  * It gives a last chance to the closing process to return an error code if  | 
397  |  |  * something goes wrong, in particular in creation / update scenarios where  | 
398  |  |  * file write or network communication might occur when finalizing the dataset.  | 
399  |  |  *  | 
400  |  |  * Implementations should be robust to this method to be called several times  | 
401  |  |  * (on subsequent calls, it should do nothing and return CE_None).  | 
402  |  |  * Once it has been called, no other method than Close() or the dataset  | 
403  |  |  * destructor should be called. RasterBand or OGRLayer owned by the dataset  | 
404  |  |  * should be assumed as no longer being valid.  | 
405  |  |  *  | 
406  |  |  * If a driver implements this method, it must also call it from its  | 
407  |  |  * dataset destructor.  | 
408  |  |  *  | 
409  |  |  * A typical implementation might look as the following  | 
410  |  |  * \code{.cpp} | 
411  |  |  *  | 
412  |  |  *  MyDataset::~MyDataset()  | 
413  |  |  *  { | 
414  |  |  *     try  | 
415  |  |  *     { | 
416  |  |  *         MyDataset::Close();  | 
417  |  |  *     }  | 
418  |  |  *     catch (const std::exception &exc)  | 
419  |  |  *     { | 
420  |  |  *         // If Close() can throw exception  | 
421  |  |  *         CPLError(CE_Failure, CPLE_AppDefined,  | 
422  |  |  *                  "Exception thrown in MyDataset::Close(): %s",  | 
423  |  |  *                  exc.what());  | 
424  |  |  *     }  | 
425  |  |  *     catch (...)  | 
426  |  |  *     { | 
427  |  |  *         // If Close() can throw exception  | 
428  |  |  *         CPLError(CE_Failure, CPLE_AppDefined,  | 
429  |  |  *                  "Exception thrown in MyDataset::Close()");  | 
430  |  |  *     }  | 
431  |  |  *  }  | 
432  |  |  *  | 
433  |  |  *  CPLErr MyDataset::Close()  | 
434  |  |  *  { | 
435  |  |  *      CPLErr eErr = CE_None;  | 
436  |  |  *      if( nOpenFlags != OPEN_FLAGS_CLOSED )  | 
437  |  |  *      { | 
438  |  |  *          if( MyDataset::FlushCache(true) != CE_None )  | 
439  |  |  *              eErr = CE_Failure;  | 
440  |  |  *  | 
441  |  |  *          // Do something driver specific  | 
442  |  |  *          if (m_fpImage)  | 
443  |  |  *          { | 
444  |  |  *              if( VSIFCloseL(m_fpImage) != 0 )  | 
445  |  |  *              { | 
446  |  |  *                  CPLError(CE_Failure, CPLE_FileIO, "VSIFCloseL() failed");  | 
447  |  |  *                  eErr = CE_Failure;  | 
448  |  |  *              }  | 
449  |  |  *          }  | 
450  |  |  *  | 
451  |  |  *          // Call parent Close() implementation.  | 
452  |  |  *          if( MyParentDatasetClass::Close() != CE_None )  | 
453  |  |  *              eErr = CE_Failure;  | 
454  |  |  *      }  | 
455  |  |  *      return eErr;  | 
456  |  |  *  }  | 
457  |  |  * \endcode  | 
458  |  |  *  | 
459  |  |  * @since GDAL 3.7  | 
460  |  |  */  | 
461  |  | CPLErr GDALDataset::Close()  | 
462  | 0  | { | 
463  |  |     // Call UnregisterFromSharedDataset() before altering nOpenFlags  | 
464  | 0  |     UnregisterFromSharedDataset();  | 
465  |  | 
  | 
466  | 0  |     nOpenFlags = OPEN_FLAGS_CLOSED;  | 
467  | 0  |     return CE_None;  | 
468  | 0  | }  | 
469  |  |  | 
470  |  | /************************************************************************/  | 
471  |  | /*                UnregisterFromSharedDataset()                         */  | 
472  |  | /************************************************************************/  | 
473  |  |  | 
474  |  | void GDALDataset::UnregisterFromSharedDataset()  | 
475  | 0  | { | 
476  | 0  |     if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))  | 
477  | 0  |         return;  | 
478  |  |  | 
479  | 0  |     CPLMutexHolderD(&hDLMutex);  | 
480  |  | 
  | 
481  | 0  |     std::map<GDALDataset *, GIntBig>::iterator oIter =  | 
482  | 0  |         poAllDatasetMap->find(this);  | 
483  | 0  |     CPLAssert(oIter != poAllDatasetMap->end());  | 
484  | 0  |     const GIntBig nPIDCreatorForShared = oIter->second;  | 
485  | 0  |     bShared = false;  | 
486  | 0  |     SharedDatasetCtxt sStruct;  | 
487  | 0  |     sStruct.nPID = nPIDCreatorForShared;  | 
488  | 0  |     sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;  | 
489  | 0  |     sStruct.pszDescription = const_cast<char *>(GetDescription());  | 
490  | 0  |     std::string osConcatenatedOpenOptions =  | 
491  | 0  |         GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);  | 
492  | 0  |     sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];  | 
493  | 0  |     sStruct.poDS = nullptr;  | 
494  | 0  |     SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(  | 
495  | 0  |         CPLHashSetLookup(phSharedDatasetSet, &sStruct));  | 
496  | 0  |     if (psStruct && psStruct->poDS == this)  | 
497  | 0  |     { | 
498  | 0  |         CPLHashSetRemove(phSharedDatasetSet, psStruct);  | 
499  | 0  |     }  | 
500  | 0  |     else  | 
501  | 0  |     { | 
502  | 0  |         CPLDebug("GDAL", | 
503  | 0  |                  "Should not happen. Cannot find %s, "  | 
504  | 0  |                  "this=%p in phSharedDatasetSet",  | 
505  | 0  |                  GetDescription(), this);  | 
506  | 0  |     }  | 
507  | 0  | }  | 
508  |  |  | 
509  |  | /************************************************************************/  | 
510  |  | /*                      AddToDatasetOpenList()                          */  | 
511  |  | /************************************************************************/  | 
512  |  |  | 
513  |  | void GDALDataset::AddToDatasetOpenList()  | 
514  | 0  | { | 
515  |  |     /* -------------------------------------------------------------------- */  | 
516  |  |     /*      Add this dataset to the open dataset list.                      */  | 
517  |  |     /* -------------------------------------------------------------------- */  | 
518  | 0  |     bIsInternal = false;  | 
519  |  | 
  | 
520  | 0  |     CPLMutexHolderD(&hDLMutex);  | 
521  |  | 
  | 
522  | 0  |     if (poAllDatasetMap == nullptr)  | 
523  | 0  |         poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;  | 
524  | 0  |     (*poAllDatasetMap)[this] = -1;  | 
525  | 0  | }  | 
526  |  |  | 
527  |  | /************************************************************************/  | 
528  |  | /*                             FlushCache()                             */  | 
529  |  | /************************************************************************/  | 
530  |  |  | 
531  |  | /**  | 
532  |  |  * \brief Flush all write cached data to disk.  | 
533  |  |  *  | 
534  |  |  * Any raster (or other GDAL) data written via GDAL calls, but buffered  | 
535  |  |  * internally will be written to disk.  | 
536  |  |  *  | 
537  |  |  * The default implementation of this method just calls the FlushCache() method  | 
538  |  |  * on each of the raster bands and the SyncToDisk() method  | 
539  |  |  * on each of the layers.  Conceptually, calling FlushCache() on a dataset  | 
540  |  |  * should include any work that might be accomplished by calling SyncToDisk()  | 
541  |  |  * on layers in that dataset.  | 
542  |  |  *  | 
543  |  |  * Using this method does not prevent use from calling GDALClose()  | 
544  |  |  * to properly close a dataset and ensure that important data not addressed  | 
545  |  |  * by FlushCache() is written in the file.  | 
546  |  |  *  | 
547  |  |  * This method is the same as the C function GDALFlushCache().  | 
548  |  |  *  | 
549  |  |  * @param bAtClosing Whether this is called from a GDALDataset destructor  | 
550  |  |  * @return CE_None in case of success (note: return value added in GDAL 3.7)  | 
551  |  |  */  | 
552  |  |  | 
553  |  | CPLErr GDALDataset::FlushCache(bool bAtClosing)  | 
554  |  |  | 
555  | 0  | { | 
556  | 0  |     CPLErr eErr = CE_None;  | 
557  |  |     // This sometimes happens if a dataset is destroyed before completely  | 
558  |  |     // built.  | 
559  |  | 
  | 
560  | 0  |     if (papoBands)  | 
561  | 0  |     { | 
562  | 0  |         for (int i = 0; i < nBands; ++i)  | 
563  | 0  |         { | 
564  | 0  |             if (papoBands[i])  | 
565  | 0  |             { | 
566  | 0  |                 if (papoBands[i]->FlushCache(bAtClosing) != CE_None)  | 
567  | 0  |                     eErr = CE_Failure;  | 
568  | 0  |             }  | 
569  | 0  |         }  | 
570  | 0  |     }  | 
571  |  | 
  | 
572  | 0  |     const int nLayers = GetLayerCount();  | 
573  |  |     // cppcheck-suppress knownConditionTrueFalse  | 
574  | 0  |     if (nLayers > 0)  | 
575  | 0  |     { | 
576  | 0  |         CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);  | 
577  | 0  |         for (int i = 0; i < nLayers; ++i)  | 
578  | 0  |         { | 
579  | 0  |             OGRLayer *poLayer = GetLayer(i);  | 
580  |  | 
  | 
581  | 0  |             if (poLayer)  | 
582  | 0  |             { | 
583  | 0  |                 if (poLayer->SyncToDisk() != OGRERR_NONE)  | 
584  | 0  |                     eErr = CE_Failure;  | 
585  | 0  |             }  | 
586  | 0  |         }  | 
587  | 0  |     }  | 
588  |  | 
  | 
589  | 0  |     return eErr;  | 
590  | 0  | }  | 
591  |  |  | 
592  |  | /************************************************************************/  | 
593  |  | /*                           GDALFlushCache()                           */  | 
594  |  | /************************************************************************/  | 
595  |  |  | 
596  |  | /**  | 
597  |  |  * \brief Flush all write cached data to disk.  | 
598  |  |  *  | 
599  |  |  * @see GDALDataset::FlushCache().  | 
600  |  |  * @return CE_None in case of success (note: return value added in GDAL 3.7)  | 
601  |  |  */  | 
602  |  |  | 
603  |  | CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)  | 
604  |  |  | 
605  | 0  | { | 
606  | 0  |     VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);  | 
607  |  |  | 
608  | 0  |     return GDALDataset::FromHandle(hDS)->FlushCache(false);  | 
609  | 0  | }  | 
610  |  |  | 
611  |  | /************************************************************************/  | 
612  |  | /*                             DropCache()                              */  | 
613  |  | /************************************************************************/  | 
614  |  |  | 
615  |  | /**  | 
616  |  | * \brief Drop all write cached data  | 
617  |  | *  | 
618  |  | * This method is the same as the C function GDALDropCache().  | 
619  |  | *  | 
620  |  | * @return CE_None in case of success  | 
621  |  | * @since 3.9  | 
622  |  | */  | 
623  |  |  | 
624  |  | CPLErr GDALDataset::DropCache()  | 
625  |  |  | 
626  | 0  | { | 
627  | 0  |     CPLErr eErr = CE_None;  | 
628  |  | 
  | 
629  | 0  |     if (papoBands)  | 
630  | 0  |     { | 
631  | 0  |         for (int i = 0; i < nBands; ++i)  | 
632  | 0  |         { | 
633  | 0  |             if (papoBands[i])  | 
634  | 0  |             { | 
635  | 0  |                 if (papoBands[i]->DropCache() != CE_None)  | 
636  | 0  |                     eErr = CE_Failure;  | 
637  | 0  |             }  | 
638  | 0  |         }  | 
639  | 0  |     }  | 
640  |  | 
  | 
641  | 0  |     return eErr;  | 
642  | 0  | }  | 
643  |  |  | 
644  |  | /************************************************************************/  | 
645  |  | /*                           GDALDropCache()                           */  | 
646  |  | /************************************************************************/  | 
647  |  |  | 
648  |  | /**  | 
649  |  | * \brief Drop all write cached data  | 
650  |  | *  | 
651  |  | * @see GDALDataset::DropCache().  | 
652  |  | * @return CE_None in case of success  | 
653  |  | * @since 3.9  | 
654  |  | */  | 
655  |  |  | 
656  |  | CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS)  | 
657  |  |  | 
658  | 0  | { | 
659  | 0  |     VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure);  | 
660  |  |  | 
661  | 0  |     return GDALDataset::FromHandle(hDS)->DropCache();  | 
662  | 0  | }  | 
663  |  |  | 
664  |  | /************************************************************************/  | 
665  |  | /*                      GetEstimatedRAMUsage()                          */  | 
666  |  | /************************************************************************/  | 
667  |  |  | 
668  |  | /**  | 
669  |  |  * \brief Return the intrinsic RAM usage of this dataset.  | 
670  |  |  *  | 
671  |  |  * The returned value should take into account caches in the underlying driver  | 
672  |  |  * and decoding library, but not the usage related to the GDAL block cache.  | 
673  |  |  *  | 
674  |  |  * At time of writing, this method is only implemented in the JP2OpenJPEG  | 
675  |  |  * driver. For single-tiled JPEG2000 images, the decoding of the image,  | 
676  |  |  * even partially, involves allocating at least  | 
677  |  |  * width * height * number_of_bands * sizeof(uint32_t) bytes inside the libopenjp2  | 
678  |  |  * library.  | 
679  |  |  *  | 
680  |  |  * This method is used by the GDALDatasetPool class, itself used by the GDAL VRT  | 
681  |  |  * driver, to determine how long a dataset in the pool must be kept open, given  | 
682  |  |  * the RAM usage of the dataset with respect to the usable total RAM.  | 
683  |  |  *  | 
684  |  |  * @since GDAL 3.7  | 
685  |  |  * @return RAM usage in bytes, or -1 if unknown (the default implementation  | 
686  |  |  * returns -1)  | 
687  |  |  */  | 
688  |  |  | 
689  |  | GIntBig GDALDataset::GetEstimatedRAMUsage()  | 
690  | 0  | { | 
691  | 0  |     return -1;  | 
692  | 0  | }  | 
693  |  |  | 
694  |  | /************************************************************************/  | 
695  |  | /*                        BlockBasedFlushCache()                        */  | 
696  |  | /*                                                                      */  | 
697  |  | /*      This helper method can be called by the                         */  | 
698  |  | /*      GDALDataset::FlushCache() for particular drivers to ensure      */  | 
699  |  | /*      that buffers will be flushed in a manner suitable for pixel     */  | 
700  |  | /*      interleaved (by block) IO.  That is, if all the bands have      */  | 
701  |  | /*      the same size blocks then a given block will be flushed for     */  | 
702  |  | /*      all bands before proceeding to the next block.                  */  | 
703  |  | /************************************************************************/  | 
704  |  |  | 
705  |  | //! @cond Doxygen_Suppress  | 
706  |  | CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)  | 
707  |  |  | 
708  | 0  | { | 
709  | 0  |     GDALRasterBand *poBand1 = GetRasterBand(1);  | 
710  | 0  |     if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))  | 
711  | 0  |     { | 
712  | 0  |         return GDALDataset::FlushCache(bAtClosing);  | 
713  | 0  |     }  | 
714  |  |  | 
715  | 0  |     int nBlockXSize = 0;  | 
716  | 0  |     int nBlockYSize = 0;  | 
717  | 0  |     poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);  | 
718  |  |  | 
719  |  |     /* -------------------------------------------------------------------- */  | 
720  |  |     /*      Verify that all bands match.                                    */  | 
721  |  |     /* -------------------------------------------------------------------- */  | 
722  | 0  |     for (int iBand = 1; iBand < nBands; ++iBand)  | 
723  | 0  |     { | 
724  | 0  |         GDALRasterBand *poBand = GetRasterBand(iBand + 1);  | 
725  |  | 
  | 
726  | 0  |         int nThisBlockXSize, nThisBlockYSize;  | 
727  | 0  |         poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);  | 
728  | 0  |         if (nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize)  | 
729  | 0  |         { | 
730  | 0  |             return GDALDataset::FlushCache(bAtClosing);  | 
731  | 0  |         }  | 
732  | 0  |     }  | 
733  |  |  | 
734  |  |     /* -------------------------------------------------------------------- */  | 
735  |  |     /*      Now flush writable data.                                        */  | 
736  |  |     /* -------------------------------------------------------------------- */  | 
737  | 0  |     for (int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY)  | 
738  | 0  |     { | 
739  | 0  |         for (int iX = 0; iX < poBand1->nBlocksPerRow; ++iX)  | 
740  | 0  |         { | 
741  | 0  |             for (int iBand = 0; iBand < nBands; ++iBand)  | 
742  | 0  |             { | 
743  | 0  |                 const CPLErr eErr = papoBands[iBand]->FlushBlock(iX, iY);  | 
744  |  | 
  | 
745  | 0  |                 if (eErr != CE_None)  | 
746  | 0  |                     return CE_Failure;  | 
747  | 0  |             }  | 
748  | 0  |         }  | 
749  | 0  |     }  | 
750  | 0  |     return CE_None;  | 
751  | 0  | }  | 
752  |  |  | 
753  |  | /************************************************************************/  | 
754  |  | /*                          RasterInitialize()                          */  | 
755  |  | /*                                                                      */  | 
756  |  | /*      Initialize raster size                                          */  | 
757  |  | /************************************************************************/  | 
758  |  |  | 
759  |  | void GDALDataset::RasterInitialize(int nXSize, int nYSize)  | 
760  |  |  | 
761  | 0  | { | 
762  | 0  |     CPLAssert(nXSize > 0 && nYSize > 0);  | 
763  |  |  | 
764  | 0  |     nRasterXSize = nXSize;  | 
765  | 0  |     nRasterYSize = nYSize;  | 
766  | 0  | }  | 
767  |  |  | 
768  |  | //! @endcond  | 
769  |  |  | 
770  |  | /************************************************************************/  | 
771  |  | /*                              AddBand()                               */  | 
772  |  | /************************************************************************/  | 
773  |  |  | 
774  |  | /**  | 
775  |  |  * \fn GDALDataset::AddBand(GDALDataType, char**)  | 
776  |  |  * \brief Add a band to a dataset.  | 
777  |  |  *  | 
778  |  |  * This method will add a new band to the dataset if the underlying format  | 
779  |  |  * supports this action.  Most formats do not.  | 
780  |  |  *  | 
781  |  |  * Note that the new GDALRasterBand is not returned.  It may be fetched  | 
782  |  |  * after successful completion of the method by calling  | 
783  |  |  * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest  | 
784  |  |  * band will always be the last band.  | 
785  |  |  *  | 
786  |  |  * @param eType the data type of the pixels in the new band.  | 
787  |  |  *  | 
788  |  |  * @param papszOptions a list of NAME=VALUE option strings.  The supported  | 
789  |  |  * options are format specific.  NULL may be passed by default.  | 
790  |  |  *  | 
791  |  |  * @return CE_None on success or CE_Failure on failure.  | 
792  |  |  */  | 
793  |  |  | 
794  |  | CPLErr GDALDataset::AddBand(CPL_UNUSED GDALDataType eType,  | 
795  |  |                             CPL_UNUSED char **papszOptions)  | 
796  |  |  | 
797  | 0  | { | 
798  | 0  |     ReportError(CE_Failure, CPLE_NotSupported,  | 
799  | 0  |                 "Dataset does not support the AddBand() method.");  | 
800  |  | 
  | 
801  | 0  |     return CE_Failure;  | 
802  | 0  | }  | 
803  |  |  | 
804  |  | /************************************************************************/  | 
805  |  | /*                            GDALAddBand()                             */  | 
806  |  | /************************************************************************/  | 
807  |  |  | 
808  |  | /**  | 
809  |  |  * \brief Add a band to a dataset.  | 
810  |  |  *  | 
811  |  |  * @see GDALDataset::AddBand().  | 
812  |  |  */  | 
813  |  |  | 
814  |  | CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,  | 
815  |  |                                CSLConstList papszOptions)  | 
816  |  |  | 
817  | 0  | { | 
818  | 0  |     VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);  | 
819  |  |  | 
820  | 0  |     return GDALDataset::FromHandle(hDataset)->AddBand(  | 
821  | 0  |         eType, const_cast<char **>(papszOptions));  | 
822  | 0  | }  | 
823  |  |  | 
824  |  | /************************************************************************/  | 
825  |  | /*                              SetBand()                               */  | 
826  |  | /************************************************************************/  | 
827  |  |  | 
828  |  | //! @cond Doxygen_Suppress  | 
829  |  | /**  Set a band in the band array, updating the band count, and array size  | 
830  |  |  * appropriately.  | 
831  |  |  *  | 
832  |  |  * @param nNewBand new band number (indexing starts at 1)  | 
833  |  |  * @param poBand band object.  | 
834  |  |  */  | 
835  |  |  | 
836  |  | void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)  | 
837  |  |  | 
838  | 0  | { | 
839  |  |     /* -------------------------------------------------------------------- */  | 
840  |  |     /*      Do we need to grow the bands list?                              */  | 
841  |  |     /* -------------------------------------------------------------------- */  | 
842  | 0  |     if (nBands < nNewBand || papoBands == nullptr)  | 
843  | 0  |     { | 
844  | 0  |         GDALRasterBand **papoNewBands = nullptr;  | 
845  |  | 
  | 
846  | 0  |         if (papoBands == nullptr)  | 
847  | 0  |             papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(  | 
848  | 0  |                 sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));  | 
849  | 0  |         else  | 
850  | 0  |             papoNewBands = static_cast<GDALRasterBand **>(  | 
851  | 0  |                 VSIRealloc(papoBands, sizeof(GDALRasterBand *) *  | 
852  | 0  |                                           std::max(nNewBand, nBands)));  | 
853  | 0  |         if (papoNewBands == nullptr)  | 
854  | 0  |         { | 
855  | 0  |             ReportError(CE_Failure, CPLE_OutOfMemory,  | 
856  | 0  |                         "Cannot allocate band array");  | 
857  | 0  |             return;  | 
858  | 0  |         }  | 
859  |  |  | 
860  | 0  |         papoBands = papoNewBands;  | 
861  |  | 
  | 
862  | 0  |         for (int i = nBands; i < nNewBand; ++i)  | 
863  | 0  |             papoBands[i] = nullptr;  | 
864  |  | 
  | 
865  | 0  |         nBands = std::max(nBands, nNewBand);  | 
866  |  | 
  | 
867  | 0  |         if (m_poPrivate)  | 
868  | 0  |         { | 
869  | 0  |             for (int i = static_cast<int>(m_poPrivate->m_anBandMap.size());  | 
870  | 0  |                  i < nBands; ++i)  | 
871  | 0  |             { | 
872  | 0  |                 m_poPrivate->m_anBandMap.push_back(i + 1);  | 
873  | 0  |             }  | 
874  | 0  |         }  | 
875  | 0  |     }  | 
876  |  |  | 
877  |  |     /* -------------------------------------------------------------------- */  | 
878  |  |     /*      Set the band.  Resetting the band is currently not permitted.   */  | 
879  |  |     /* -------------------------------------------------------------------- */  | 
880  | 0  |     if (papoBands[nNewBand - 1] != nullptr)  | 
881  | 0  |     { | 
882  | 0  |         ReportError(CE_Failure, CPLE_NotSupported,  | 
883  | 0  |                     "Cannot set band %d as it is already set", nNewBand);  | 
884  | 0  |         return;  | 
885  | 0  |     }  | 
886  |  |  | 
887  | 0  |     papoBands[nNewBand - 1] = poBand;  | 
888  |  |  | 
889  |  |     /* -------------------------------------------------------------------- */  | 
890  |  |     /*      Set back reference information on the raster band.  Note        */  | 
891  |  |     /*      that the GDALDataset is a friend of the GDALRasterBand          */  | 
892  |  |     /*      specifically to allow this.                                     */  | 
893  |  |     /* -------------------------------------------------------------------- */  | 
894  | 0  |     poBand->nBand = nNewBand;  | 
895  | 0  |     poBand->poDS = this;  | 
896  | 0  |     poBand->nRasterXSize = nRasterXSize;  | 
897  | 0  |     poBand->nRasterYSize = nRasterYSize;  | 
898  | 0  |     poBand->eAccess = eAccess;  // Default access to be same as dataset.  | 
899  | 0  | }  | 
900  |  |  | 
901  |  | //! @endcond  | 
902  |  |  | 
903  |  | /************************************************************************/  | 
904  |  | /*                              SetBand()                               */  | 
905  |  | /************************************************************************/  | 
906  |  |  | 
907  |  | //! @cond Doxygen_Suppress  | 
908  |  | /**  Set a band in the band array, updating the band count, and array size  | 
909  |  |  * appropriately.  | 
910  |  |  *  | 
911  |  |  * @param nNewBand new band number (indexing starts at 1)  | 
912  |  |  * @param poBand band object.  | 
913  |  |  */  | 
914  |  |  | 
915  |  | void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)  | 
916  | 0  | { | 
917  | 0  |     SetBand(nNewBand, poBand.release());  | 
918  | 0  | }  | 
919  |  |  | 
920  |  | //! @endcond  | 
921  |  |  | 
922  |  | /************************************************************************/  | 
923  |  | /*                           GetRasterXSize()                           */  | 
924  |  | /************************************************************************/  | 
925  |  |  | 
926  |  | /**  | 
927  |  |  | 
928  |  |  \brief Fetch raster width in pixels.  | 
929  |  |  | 
930  |  |  Equivalent of the C function GDALGetRasterXSize().  | 
931  |  |  | 
932  |  |  @return the width in pixels of raster bands in this GDALDataset.  | 
933  |  |  | 
934  |  | */  | 
935  |  |  | 
936  |  | int GDALDataset::GetRasterXSize() const  | 
937  | 0  | { | 
938  | 0  |     return nRasterXSize;  | 
939  | 0  | }  | 
940  |  |  | 
941  |  | /************************************************************************/  | 
942  |  | /*                         GDALGetRasterXSize()                         */  | 
943  |  | /************************************************************************/  | 
944  |  |  | 
945  |  | /**  | 
946  |  |  * \brief Fetch raster width in pixels.  | 
947  |  |  *  | 
948  |  |  * @see GDALDataset::GetRasterXSize().  | 
949  |  |  */  | 
950  |  |  | 
951  |  | int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)  | 
952  |  |  | 
953  | 0  | { | 
954  | 0  |     VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);  | 
955  |  |  | 
956  | 0  |     return GDALDataset::FromHandle(hDataset)->GetRasterXSize();  | 
957  | 0  | }  | 
958  |  |  | 
959  |  | /************************************************************************/  | 
960  |  | /*                           GetRasterYSize()                           */  | 
961  |  | /************************************************************************/  | 
962  |  |  | 
963  |  | /**  | 
964  |  |  | 
965  |  |  \brief Fetch raster height in pixels.  | 
966  |  |  | 
967  |  |  Equivalent of the C function GDALGetRasterYSize().  | 
968  |  |  | 
969  |  |  @return the height in pixels of raster bands in this GDALDataset.  | 
970  |  |  | 
971  |  | */  | 
972  |  |  | 
973  |  | int GDALDataset::GetRasterYSize() const  | 
974  | 0  | { | 
975  | 0  |     return nRasterYSize;  | 
976  | 0  | }  | 
977  |  |  | 
978  |  | /************************************************************************/  | 
979  |  | /*                         GDALGetRasterYSize()                         */  | 
980  |  | /************************************************************************/  | 
981  |  |  | 
982  |  | /**  | 
983  |  |  * \brief Fetch raster height in pixels.  | 
984  |  |  *  | 
985  |  |  * @see GDALDataset::GetRasterYSize().  | 
986  |  |  */  | 
987  |  |  | 
988  |  | int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)  | 
989  |  |  | 
990  | 0  | { | 
991  | 0  |     VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);  | 
992  |  |  | 
993  | 0  |     return GDALDataset::FromHandle(hDataset)->GetRasterYSize();  | 
994  | 0  | }  | 
995  |  |  | 
996  |  | /************************************************************************/  | 
997  |  | /*                           GetRasterBand()                            */  | 
998  |  | /************************************************************************/  | 
999  |  |  | 
1000  |  | /**  | 
1001  |  |  | 
1002  |  |  \brief Fetch a band object for a dataset.  | 
1003  |  |  | 
1004  |  |  See GetBands() for a C++ iterator version of this method.  | 
1005  |  |  | 
1006  |  |  Equivalent of the C function GDALGetRasterBand().  | 
1007  |  |  | 
1008  |  |  @param nBandId the index number of the band to fetch, from 1 to  | 
1009  |  |                 GetRasterCount().  | 
1010  |  |  | 
1011  |  |  @return the nBandId th band object  | 
1012  |  |  | 
1013  |  | */  | 
1014  |  |  | 
1015  |  | GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)  | 
1016  |  |  | 
1017  | 0  | { | 
1018  | 0  |     if (papoBands)  | 
1019  | 0  |     { | 
1020  | 0  |         if (nBandId < 1 || nBandId > nBands)  | 
1021  | 0  |         { | 
1022  | 0  |             ReportError(CE_Failure, CPLE_IllegalArg,  | 
1023  | 0  |                         "GDALDataset::GetRasterBand(%d) - Illegal band #\n",  | 
1024  | 0  |                         nBandId);  | 
1025  | 0  |             return nullptr;  | 
1026  | 0  |         }  | 
1027  |  |  | 
1028  | 0  |         return papoBands[nBandId - 1];  | 
1029  | 0  |     }  | 
1030  | 0  |     return nullptr;  | 
1031  | 0  | }  | 
1032  |  |  | 
1033  |  | /************************************************************************/  | 
1034  |  | /*                           GetRasterBand()                            */  | 
1035  |  | /************************************************************************/  | 
1036  |  |  | 
1037  |  | /**  | 
1038  |  |  | 
1039  |  |  \brief Fetch a band object for a dataset.  | 
1040  |  |  | 
1041  |  |  See GetBands() for a C++ iterator version of this method.  | 
1042  |  |  | 
1043  |  |  Equivalent of the C function GDALGetRasterBand().  | 
1044  |  |  | 
1045  |  |  @param nBandId the index number of the band to fetch, from 1 to  | 
1046  |  |                 GetRasterCount().  | 
1047  |  |  | 
1048  |  |  @return the nBandId th band object  | 
1049  |  |  | 
1050  |  | */  | 
1051  |  |  | 
1052  |  | const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const  | 
1053  |  |  | 
1054  | 0  | { | 
1055  | 0  |     if (papoBands)  | 
1056  | 0  |     { | 
1057  | 0  |         if (nBandId < 1 || nBandId > nBands)  | 
1058  | 0  |         { | 
1059  | 0  |             ReportError(CE_Failure, CPLE_IllegalArg,  | 
1060  | 0  |                         "GDALDataset::GetRasterBand(%d) - Illegal band #\n",  | 
1061  | 0  |                         nBandId);  | 
1062  | 0  |             return nullptr;  | 
1063  | 0  |         }  | 
1064  |  |  | 
1065  | 0  |         return papoBands[nBandId - 1];  | 
1066  | 0  |     }  | 
1067  | 0  |     return nullptr;  | 
1068  | 0  | }  | 
1069  |  |  | 
1070  |  | /************************************************************************/  | 
1071  |  | /*                         GDALGetRasterBand()                          */  | 
1072  |  | /************************************************************************/  | 
1073  |  |  | 
1074  |  | /**  | 
1075  |  |  * \brief Fetch a band object for a dataset.  | 
1076  |  |  * @see GDALDataset::GetRasterBand().  | 
1077  |  |  */  | 
1078  |  |  | 
1079  |  | GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)  | 
1080  |  |  | 
1081  | 0  | { | 
1082  | 0  |     VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);  | 
1083  |  |  | 
1084  | 0  |     return GDALRasterBand::ToHandle(  | 
1085  | 0  |         GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));  | 
1086  | 0  | }  | 
1087  |  |  | 
1088  |  | /************************************************************************/  | 
1089  |  | /*                           GetRasterCount()                           */  | 
1090  |  | /************************************************************************/  | 
1091  |  |  | 
1092  |  | /**  | 
1093  |  |  * \brief Fetch the number of raster bands on this dataset.  | 
1094  |  |  *  | 
1095  |  |  * Same as the C function GDALGetRasterCount().  | 
1096  |  |  *  | 
1097  |  |  * @return the number of raster bands.  | 
1098  |  |  */  | 
1099  |  |  | 
1100  |  | int GDALDataset::GetRasterCount() const  | 
1101  | 0  | { | 
1102  | 0  |     return papoBands ? nBands : 0;  | 
1103  | 0  | }  | 
1104  |  |  | 
1105  |  | /************************************************************************/  | 
1106  |  | /*                         GDALGetRasterCount()                         */  | 
1107  |  | /************************************************************************/  | 
1108  |  |  | 
1109  |  | /**  | 
1110  |  |  * \brief Fetch the number of raster bands on this dataset.  | 
1111  |  |  *  | 
1112  |  |  * @see GDALDataset::GetRasterCount().  | 
1113  |  |  */  | 
1114  |  |  | 
1115  |  | int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)  | 
1116  |  |  | 
1117  | 0  | { | 
1118  | 0  |     VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);  | 
1119  |  |  | 
1120  | 0  |     return GDALDataset::FromHandle(hDS)->GetRasterCount();  | 
1121  | 0  | }  | 
1122  |  |  | 
1123  |  | /************************************************************************/  | 
1124  |  | /*                          GetProjectionRef()                          */  | 
1125  |  | /************************************************************************/  | 
1126  |  |  | 
1127  |  | /**  | 
1128  |  |  * \brief Fetch the projection definition string for this dataset.  | 
1129  |  |  *  | 
1130  |  |  * Same as the C function GDALGetProjectionRef().  | 
1131  |  |  *  | 
1132  |  |  * The returned string defines the projection coordinate system of the  | 
1133  |  |  * image in OpenGIS WKT format.  It should be suitable for use with the  | 
1134  |  |  * OGRSpatialReference class.  | 
1135  |  |  *  | 
1136  |  |  * When a projection definition is not available an empty (but not NULL)  | 
1137  |  |  * string is returned.  | 
1138  |  |  *  | 
1139  |  |  * \note Starting with GDAL 3.0, this is a compatibility layer around  | 
1140  |  |  * GetSpatialRef()  | 
1141  |  |  *  | 
1142  |  |  * @return a pointer to an internal projection reference string.  It should  | 
1143  |  |  * not be altered, freed or expected to last for long.  | 
1144  |  |  *  | 
1145  |  |  * @see https://gdal.org/tutorials/osr_api_tut.html  | 
1146  |  |  */  | 
1147  |  |  | 
1148  |  | const char *GDALDataset::GetProjectionRef() const  | 
1149  | 0  | { | 
1150  | 0  |     const auto poSRS = GetSpatialRef();  | 
1151  | 0  |     if (!poSRS || !m_poPrivate)  | 
1152  | 0  |     { | 
1153  | 0  |         return "";  | 
1154  | 0  |     }  | 
1155  | 0  |     char *pszWKT = nullptr;  | 
1156  | 0  |     poSRS->exportToWkt(&pszWKT);  | 
1157  | 0  |     if (!pszWKT)  | 
1158  | 0  |     { | 
1159  | 0  |         return "";  | 
1160  | 0  |     }  | 
1161  |  |  | 
1162  |  |     // If called on a thread-safe dataset, we might be called by several  | 
1163  |  |     // threads, so make sure our accesses to m_pszWKTCached are protected  | 
1164  |  |     // by a mutex.  | 
1165  | 0  |     std::lock_guard oLock(m_poPrivate->m_oMutexWKT);  | 
1166  | 0  |     if (m_poPrivate->m_pszWKTCached &&  | 
1167  | 0  |         strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)  | 
1168  | 0  |     { | 
1169  | 0  |         CPLFree(pszWKT);  | 
1170  | 0  |         return m_poPrivate->m_pszWKTCached;  | 
1171  | 0  |     }  | 
1172  | 0  |     CPLFree(m_poPrivate->m_pszWKTCached);  | 
1173  | 0  |     m_poPrivate->m_pszWKTCached = pszWKT;  | 
1174  | 0  |     return m_poPrivate->m_pszWKTCached;  | 
1175  | 0  | }  | 
1176  |  |  | 
1177  |  | /************************************************************************/  | 
1178  |  | /*                           GetSpatialRef()                            */  | 
1179  |  | /************************************************************************/  | 
1180  |  |  | 
1181  |  | /**  | 
1182  |  |  * \brief Fetch the spatial reference for this dataset.  | 
1183  |  |  *  | 
1184  |  |  * Same as the C function GDALGetSpatialRef().  | 
1185  |  |  *  | 
1186  |  |  * When a projection definition is not available, null is returned. If used on  | 
1187  |  |  * a dataset where there are GCPs and not a geotransform, this method returns  | 
1188  |  |  * null. Use GetGCPSpatialRef() instead.  | 
1189  |  |  *  | 
1190  |  |  * @since GDAL 3.0  | 
1191  |  |  *  | 
1192  |  |  * @return a pointer to an internal object. It should not be altered or freed.  | 
1193  |  |  * Its lifetime will be the one of the dataset object, or until the next  | 
1194  |  |  * call to this method.  | 
1195  |  |  *  | 
1196  |  |  * @see https://gdal.org/tutorials/osr_api_tut.html  | 
1197  |  |  */  | 
1198  |  |  | 
1199  |  | const OGRSpatialReference *GDALDataset::GetSpatialRef() const  | 
1200  | 0  | { | 
1201  | 0  |     return nullptr;  | 
1202  | 0  | }  | 
1203  |  |  | 
1204  |  | /************************************************************************/  | 
1205  |  | /*                        GDALGetSpatialRef()                           */  | 
1206  |  | /************************************************************************/  | 
1207  |  |  | 
1208  |  | /**  | 
1209  |  |  * \brief Fetch the spatial reference for this dataset.  | 
1210  |  |  *  | 
1211  |  |  * @since GDAL 3.0  | 
1212  |  |  *  | 
1213  |  |  * @see GDALDataset::GetSpatialRef()  | 
1214  |  |  */  | 
1215  |  |  | 
1216  |  | OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)  | 
1217  |  |  | 
1218  | 0  | { | 
1219  | 0  |     VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);  | 
1220  |  |  | 
1221  | 0  |     return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(  | 
1222  | 0  |         GDALDataset::FromHandle(hDS)->GetSpatialRef()));  | 
1223  | 0  | }  | 
1224  |  |  | 
1225  |  | /************************************************************************/  | 
1226  |  | /*                        GDALGetProjectionRef()                        */  | 
1227  |  | /************************************************************************/  | 
1228  |  |  | 
1229  |  | /**  | 
1230  |  |  * \brief Fetch the projection definition string for this dataset.  | 
1231  |  |  *  | 
1232  |  |  * @see GDALDataset::GetProjectionRef()  | 
1233  |  |  */  | 
1234  |  |  | 
1235  |  | const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)  | 
1236  |  |  | 
1237  | 0  | { | 
1238  | 0  |     VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);  | 
1239  |  |  | 
1240  | 0  |     return GDALDataset::FromHandle(hDS)->GetProjectionRef();  | 
1241  | 0  | }  | 
1242  |  |  | 
1243  |  | /************************************************************************/  | 
1244  |  | /*                           SetProjection()                            */  | 
1245  |  | /************************************************************************/  | 
1246  |  |  | 
1247  |  | /**  | 
1248  |  |  * \brief Set the projection reference string for this dataset.  | 
1249  |  |  *  | 
1250  |  |  * The string should be in OGC WKT or PROJ.4 format.  An error may occur  | 
1251  |  |  * because of incorrectly specified projection strings, because the dataset  | 
1252  |  |  * is not writable, or because the dataset does not support the indicated  | 
1253  |  |  * projection.  Many formats do not support writing projections.  | 
1254  |  |  *  | 
1255  |  |  * This method is the same as the C GDALSetProjection() function.  | 
1256  |  |  *  | 
1257  |  |  * \note Startig with GDAL 3.0, this is a compatibility layer around  | 
1258  |  |  * SetSpatialRef()  | 
1259  |  |  | 
1260  |  |  * @param pszProjection projection reference string.  | 
1261  |  |  *  | 
1262  |  |  * @return CE_Failure if an error occurs, otherwise CE_None.  | 
1263  |  |  */  | 
1264  |  |  | 
1265  |  | CPLErr GDALDataset::SetProjection(const char *pszProjection)  | 
1266  | 0  | { | 
1267  | 0  |     if (pszProjection && pszProjection[0] != '\0')  | 
1268  | 0  |     { | 
1269  | 0  |         OGRSpatialReference oSRS;  | 
1270  | 0  |         oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);  | 
1271  | 0  |         if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)  | 
1272  | 0  |         { | 
1273  | 0  |             return CE_Failure;  | 
1274  | 0  |         }  | 
1275  | 0  |         return SetSpatialRef(&oSRS);  | 
1276  | 0  |     }  | 
1277  | 0  |     else  | 
1278  | 0  |     { | 
1279  | 0  |         return SetSpatialRef(nullptr);  | 
1280  | 0  |     }  | 
1281  | 0  | }  | 
1282  |  |  | 
1283  |  | /************************************************************************/  | 
1284  |  | /*                           SetSpatialRef()                            */  | 
1285  |  | /************************************************************************/  | 
1286  |  |  | 
1287  |  | /**  | 
1288  |  |  * \brief Set the spatial reference system for this dataset.  | 
1289  |  |  *  | 
1290  |  |  * An error may occur because the dataset  | 
1291  |  |  * is not writable, or because the dataset does not support the indicated  | 
1292  |  |  * projection. Many formats do not support writing projections.  | 
1293  |  |  *  | 
1294  |  |  * This method is the same as the C GDALSetSpatialRef() function.  | 
1295  |  |  *  | 
1296  |  |  * @since GDAL 3.0  | 
1297  |  |  | 
1298  |  |  * @param poSRS spatial reference system object. nullptr can potentially be  | 
1299  |  |  * passed for drivers that support unsetting the SRS.  | 
1300  |  |  *  | 
1301  |  |  * @return CE_Failure if an error occurs, otherwise CE_None.  | 
1302  |  |  */  | 
1303  |  |  | 
1304  |  | CPLErr GDALDataset::SetSpatialRef(CPL_UNUSED const OGRSpatialReference *poSRS)  | 
1305  | 0  | { | 
1306  | 0  |     if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))  | 
1307  | 0  |         ReportError(CE_Failure, CPLE_NotSupported,  | 
1308  | 0  |                     "Dataset does not support the SetSpatialRef() method.");  | 
1309  | 0  |     return CE_Failure;  | 
1310  | 0  | }  | 
1311  |  |  | 
1312  |  | /************************************************************************/  | 
1313  |  | /*                         GDALSetSpatialRef()                          */  | 
1314  |  | /************************************************************************/  | 
1315  |  |  | 
1316  |  | /**  | 
1317  |  |  * \brief Set the spatial reference system for this dataset.  | 
1318  |  |  *  | 
1319  |  |  * @since GDAL 3.0  | 
1320  |  |  *  | 
1321  |  |  * @see GDALDataset::SetSpatialRef()  | 
1322  |  |  */  | 
1323  |  |  | 
1324  |  | CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)  | 
1325  |  |  | 
1326  | 0  | { | 
1327  | 0  |     VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);  | 
1328  |  |  | 
1329  | 0  |     return GDALDataset::FromHandle(hDS)->SetSpatialRef(  | 
1330  | 0  |         OGRSpatialReference::FromHandle(hSRS));  | 
1331  | 0  | }  | 
1332  |  |  | 
1333  |  | /************************************************************************/  | 
1334  |  | /*                         GDALSetProjection()                          */  | 
1335  |  | /************************************************************************/  | 
1336  |  |  | 
1337  |  | /**  | 
1338  |  |  * \brief Set the projection reference string for this dataset.  | 
1339  |  |  *  | 
1340  |  |  * @see GDALDataset::SetProjection()  | 
1341  |  |  */  | 
1342  |  |  | 
1343  |  | CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,  | 
1344  |  |                                      const char *pszProjection)  | 
1345  |  |  | 
1346  | 0  | { | 
1347  | 0  |     VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);  | 
1348  |  |  | 
1349  | 0  |     return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);  | 
1350  | 0  | }  | 
1351  |  |  | 
1352  |  | /************************************************************************/  | 
1353  |  | /*                          GetGeoTransform()                           */  | 
1354  |  | /************************************************************************/  | 
1355  |  |  | 
1356  |  | /**  | 
1357  |  |  * \brief Fetch the affine transformation coefficients.  | 
1358  |  |  *  | 
1359  |  |  * Fetches the coefficients for transforming between pixel/line (P,L) raster  | 
1360  |  |  * space, and projection coordinates (Xp,Yp) space.  | 
1361  |  |  *  | 
1362  |  |  * \code  | 
1363  |  |  *   Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];  | 
1364  |  |  *   Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];  | 
1365  |  |  * \endcode  | 
1366  |  |  *  | 
1367  |  |  * In a north up image, padfTransform[1] is the pixel width, and  | 
1368  |  |  * padfTransform[5] is the pixel height.  The upper left corner of the  | 
1369  |  |  * upper left pixel is at position (padfTransform[0],padfTransform[3]).  | 
1370  |  |  *  | 
1371  |  |  * The default transform is (0,1,0,0,0,1) and should be returned even when  | 
1372  |  |  * a CE_Failure error is returned, such as for formats that don't support  | 
1373  |  |  * transformation to projection coordinates.  | 
1374  |  |  *  | 
1375  |  |  * This method does the same thing as the C GDALGetGeoTransform() function.  | 
1376  |  |  *  | 
1377  |  |  * @param padfTransform an existing six double buffer into which the  | 
1378  |  |  * transformation will be placed.  | 
1379  |  |  *  | 
1380  |  |  * @return CE_None on success, or CE_Failure if no transform can be fetched.  | 
1381  |  |  */  | 
1382  |  |  | 
1383  |  | CPLErr GDALDataset::GetGeoTransform(double *padfTransform)  | 
1384  |  |  | 
1385  | 0  | { | 
1386  | 0  |     CPLAssert(padfTransform != nullptr);  | 
1387  |  |  | 
1388  | 0  |     padfTransform[0] = 0.0;  // X Origin (top left corner)  | 
1389  | 0  |     padfTransform[1] = 1.0;  // X Pixel size */  | 
1390  | 0  |     padfTransform[2] = 0.0;  | 
1391  |  | 
  | 
1392  | 0  |     padfTransform[3] = 0.0;  // Y Origin (top left corner)  | 
1393  | 0  |     padfTransform[4] = 0.0;  | 
1394  | 0  |     padfTransform[5] = 1.0;  // Y Pixel Size  | 
1395  |  | 
  | 
1396  | 0  |     return CE_Failure;  | 
1397  | 0  | }  | 
1398  |  |  | 
1399  |  | /************************************************************************/  | 
1400  |  | /*                        GDALGetGeoTransform()                         */  | 
1401  |  | /************************************************************************/  | 
1402  |  |  | 
1403  |  | /**  | 
1404  |  |  * \brief Fetch the affine transformation coefficients.  | 
1405  |  |  *  | 
1406  |  |  * @see GDALDataset::GetGeoTransform()  | 
1407  |  |  */  | 
1408  |  |  | 
1409  |  | CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)  | 
1410  |  |  | 
1411  | 0  | { | 
1412  | 0  |     VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);  | 
1413  |  |  | 
1414  | 0  |     return GDALDataset::FromHandle(hDS)->GetGeoTransform(padfTransform);  | 
1415  | 0  | }  | 
1416  |  |  | 
1417  |  | /************************************************************************/  | 
1418  |  | /*                          SetGeoTransform()                           */  | 
1419  |  | /************************************************************************/  | 
1420  |  |  | 
1421  |  | /**  | 
1422  |  |  * \fn GDALDataset::SetGeoTransform(double*)  | 
1423  |  |  * \brief Set the affine transformation coefficients.  | 
1424  |  |  *  | 
1425  |  |  * See GetGeoTransform() for details on the meaning of the padfTransform  | 
1426  |  |  * coefficients.  | 
1427  |  |  *  | 
1428  |  |  * This method does the same thing as the C GDALSetGeoTransform() function.  | 
1429  |  |  *  | 
1430  |  |  * @param padfTransform a six double buffer containing the transformation  | 
1431  |  |  * coefficients to be written with the dataset.  | 
1432  |  |  *  | 
1433  |  |  * @return CE_None on success, or CE_Failure if this transform cannot be  | 
1434  |  |  * written.  | 
1435  |  |  */  | 
1436  |  |  | 
1437  |  | CPLErr GDALDataset::SetGeoTransform(CPL_UNUSED double *padfTransform)  | 
1438  |  |  | 
1439  | 0  | { | 
1440  | 0  |     if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))  | 
1441  | 0  |         ReportError(CE_Failure, CPLE_NotSupported,  | 
1442  | 0  |                     "SetGeoTransform() not supported for this dataset.");  | 
1443  |  | 
  | 
1444  | 0  |     return CE_Failure;  | 
1445  | 0  | }  | 
1446  |  |  | 
1447  |  | /************************************************************************/  | 
1448  |  | /*                        GDALSetGeoTransform()                         */  | 
1449  |  | /************************************************************************/  | 
1450  |  |  | 
1451  |  | /**  | 
1452  |  |  * \brief Set the affine transformation coefficients.  | 
1453  |  |  *  | 
1454  |  |  * @see GDALDataset::SetGeoTransform()  | 
1455  |  |  */  | 
1456  |  |  | 
1457  |  | CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS, double *padfTransform)  | 
1458  |  |  | 
1459  | 0  | { | 
1460  | 0  |     VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);  | 
1461  |  |  | 
1462  | 0  |     return GDALDataset::FromHandle(hDS)->SetGeoTransform(padfTransform);  | 
1463  | 0  | }  | 
1464  |  |  | 
1465  |  | /************************************************************************/  | 
1466  |  | /*                         GetInternalHandle()                          */  | 
1467  |  | /************************************************************************/  | 
1468  |  |  | 
1469  |  | /**  | 
1470  |  |  * \fn GDALDataset::GetInternalHandle(const char*)  | 
1471  |  |  * \brief Fetch a format specific internally meaningful handle.  | 
1472  |  |  *  | 
1473  |  |  * This method is the same as the C GDALGetInternalHandle() method.  | 
1474  |  |  *  | 
1475  |  |  * @param pszHandleName the handle name desired.  The meaningful names  | 
1476  |  |  * will be specific to the file format.  | 
1477  |  |  *  | 
1478  |  |  * @return the desired handle value, or NULL if not recognized/supported.  | 
1479  |  |  */  | 
1480  |  |  | 
1481  |  | void *GDALDataset::GetInternalHandle(CPL_UNUSED const char *pszHandleName)  | 
1482  |  |  | 
1483  | 0  | { | 
1484  | 0  |     return nullptr;  | 
1485  | 0  | }  | 
1486  |  |  | 
1487  |  | /************************************************************************/  | 
1488  |  | /*                       GDALGetInternalHandle()                        */  | 
1489  |  | /************************************************************************/  | 
1490  |  |  | 
1491  |  | /**  | 
1492  |  |  * \brief Fetch a format specific internally meaningful handle.  | 
1493  |  |  *  | 
1494  |  |  * @see GDALDataset::GetInternalHandle()  | 
1495  |  |  */  | 
1496  |  |  | 
1497  |  | void *CPL_STDCALL GDALGetInternalHandle(GDALDatasetH hDS,  | 
1498  |  |                                         const char *pszRequest)  | 
1499  |  |  | 
1500  | 0  | { | 
1501  | 0  |     VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);  | 
1502  |  |  | 
1503  | 0  |     return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);  | 
1504  | 0  | }  | 
1505  |  |  | 
1506  |  | /************************************************************************/  | 
1507  |  | /*                             GetDriver()                              */  | 
1508  |  | /************************************************************************/  | 
1509  |  |  | 
1510  |  | /**  | 
1511  |  |  * \brief Fetch the driver to which this dataset relates.  | 
1512  |  |  *  | 
1513  |  |  * This method is the same as the C GDALGetDatasetDriver() function.  | 
1514  |  |  *  | 
1515  |  |  * @return the driver on which the dataset was created with GDALOpen() or  | 
1516  |  |  * GDALCreate().  | 
1517  |  |  */  | 
1518  |  |  | 
1519  |  | GDALDriver *GDALDataset::GetDriver()  | 
1520  | 0  | { | 
1521  | 0  |     return poDriver;  | 
1522  | 0  | }  | 
1523  |  |  | 
1524  |  | /************************************************************************/  | 
1525  |  | /*                        GDALGetDatasetDriver()                        */  | 
1526  |  | /************************************************************************/  | 
1527  |  |  | 
1528  |  | /**  | 
1529  |  |  * \brief Fetch the driver to which this dataset relates.  | 
1530  |  |  *  | 
1531  |  |  * @see GDALDataset::GetDriver()  | 
1532  |  |  */  | 
1533  |  |  | 
1534  |  | GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)  | 
1535  |  |  | 
1536  | 0  | { | 
1537  | 0  |     VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);  | 
1538  |  |  | 
1539  | 0  |     return static_cast<GDALDriverH>(  | 
1540  | 0  |         GDALDataset::FromHandle(hDataset)->GetDriver());  | 
1541  | 0  | }  | 
1542  |  |  | 
1543  |  | /************************************************************************/  | 
1544  |  | /*                             Reference()                              */  | 
1545  |  | /************************************************************************/  | 
1546  |  |  | 
1547  |  | /**  | 
1548  |  |  * \brief Add one to dataset reference count.  | 
1549  |  |  *  | 
1550  |  |  * The reference is one after instantiation.  | 
1551  |  |  *  | 
1552  |  |  * This method is the same as the C GDALReferenceDataset() function.  | 
1553  |  |  *  | 
1554  |  |  * @return the post-increment reference count.  | 
1555  |  |  */  | 
1556  |  |  | 
1557  |  | int GDALDataset::Reference()  | 
1558  | 0  | { | 
1559  | 0  |     return ++nRefCount;  | 
1560  | 0  | }  | 
1561  |  |  | 
1562  |  | /************************************************************************/  | 
1563  |  | /*                        GDALReferenceDataset()                        */  | 
1564  |  | /************************************************************************/  | 
1565  |  |  | 
1566  |  | /**  | 
1567  |  |  * \brief Add one to dataset reference count.  | 
1568  |  |  *  | 
1569  |  |  * @see GDALDataset::Reference()  | 
1570  |  |  */  | 
1571  |  |  | 
1572  |  | int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)  | 
1573  |  |  | 
1574  | 0  | { | 
1575  | 0  |     VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);  | 
1576  |  |  | 
1577  | 0  |     return GDALDataset::FromHandle(hDataset)->Reference();  | 
1578  | 0  | }  | 
1579  |  |  | 
1580  |  | /************************************************************************/  | 
1581  |  | /*                            Dereference()                             */  | 
1582  |  | /************************************************************************/  | 
1583  |  |  | 
1584  |  | /**  | 
1585  |  |  * \brief Subtract one from dataset reference count.  | 
1586  |  |  *  | 
1587  |  |  * The reference is one after instantiation.  Generally when the reference  | 
1588  |  |  * count has dropped to zero the dataset may be safely deleted (closed).  | 
1589  |  |  *  | 
1590  |  |  * This method is the same as the C GDALDereferenceDataset() function.  | 
1591  |  |  *  | 
1592  |  |  * @return the post-decrement reference count.  | 
1593  |  |  */  | 
1594  |  |  | 
1595  |  | int GDALDataset::Dereference()  | 
1596  | 0  | { | 
1597  | 0  |     return --nRefCount;  | 
1598  | 0  | }  | 
1599  |  |  | 
1600  |  | /************************************************************************/  | 
1601  |  | /*                       GDALDereferenceDataset()                       */  | 
1602  |  | /************************************************************************/  | 
1603  |  |  | 
1604  |  | /**  | 
1605  |  |  * \brief Subtract one from dataset reference count.  | 
1606  |  |  *  | 
1607  |  |  * @see GDALDataset::Dereference()  | 
1608  |  |  */  | 
1609  |  |  | 
1610  |  | int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)  | 
1611  |  |  | 
1612  | 0  | { | 
1613  | 0  |     VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);  | 
1614  |  |  | 
1615  | 0  |     return GDALDataset::FromHandle(hDataset)->Dereference();  | 
1616  | 0  | }  | 
1617  |  |  | 
1618  |  | /************************************************************************/  | 
1619  |  | /*                            ReleaseRef()                              */  | 
1620  |  | /************************************************************************/  | 
1621  |  |  | 
1622  |  | /**  | 
1623  |  |  * \brief Drop a reference to this object, and destroy if no longer referenced.  | 
1624  |  |  * @return TRUE if the object has been destroyed.  | 
1625  |  |  * @since GDAL 2.2  | 
1626  |  |  */  | 
1627  |  |  | 
1628  |  | int GDALDataset::ReleaseRef()  | 
1629  |  |  | 
1630  | 0  | { | 
1631  | 0  |     if (Dereference() <= 0)  | 
1632  | 0  |     { | 
1633  | 0  |         nRefCount = 1;  | 
1634  | 0  |         delete this;  | 
1635  | 0  |         return TRUE;  | 
1636  | 0  |     }  | 
1637  | 0  |     return FALSE;  | 
1638  | 0  | }  | 
1639  |  |  | 
1640  |  | /************************************************************************/  | 
1641  |  | /*                        GDALReleaseDataset()                          */  | 
1642  |  | /************************************************************************/  | 
1643  |  |  | 
1644  |  | /**  | 
1645  |  |  * \brief Drop a reference to this object, and destroy if no longer referenced.  | 
1646  |  |  *  | 
1647  |  |  * @see GDALDataset::ReleaseRef()  | 
1648  |  |  * @since GDAL 2.2  | 
1649  |  |  */  | 
1650  |  |  | 
1651  |  | int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)  | 
1652  |  |  | 
1653  | 0  | { | 
1654  | 0  |     VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);  | 
1655  |  |  | 
1656  | 0  |     return GDALDataset::FromHandle(hDataset)->ReleaseRef();  | 
1657  | 0  | }  | 
1658  |  |  | 
1659  |  | /************************************************************************/  | 
1660  |  | /*                             GetShared()                              */  | 
1661  |  | /************************************************************************/  | 
1662  |  |  | 
1663  |  | /**  | 
1664  |  |  * \brief Returns shared flag.  | 
1665  |  |  *  | 
1666  |  |  * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.  | 
1667  |  |  */  | 
1668  |  |  | 
1669  |  | int GDALDataset::GetShared() const  | 
1670  | 0  | { | 
1671  | 0  |     return bShared;  | 
1672  | 0  | }  | 
1673  |  |  | 
1674  |  | /************************************************************************/  | 
1675  |  | /*                            MarkAsShared()                            */  | 
1676  |  | /************************************************************************/  | 
1677  |  |  | 
1678  |  | /**  | 
1679  |  |  * \brief Mark this dataset as available for sharing.  | 
1680  |  |  */  | 
1681  |  |  | 
1682  |  | void GDALDataset::MarkAsShared()  | 
1683  |  |  | 
1684  | 0  | { | 
1685  | 0  |     CPLAssert(!bShared);  | 
1686  |  |  | 
1687  | 0  |     bShared = true;  | 
1688  | 0  |     if (bIsInternal)  | 
1689  | 0  |         return;  | 
1690  |  |  | 
1691  | 0  |     GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();  | 
1692  |  |  | 
1693  |  |     // Insert the dataset in the set of shared opened datasets.  | 
1694  | 0  |     CPLMutexHolderD(&hDLMutex);  | 
1695  | 0  |     if (phSharedDatasetSet == nullptr)  | 
1696  | 0  |         phSharedDatasetSet =  | 
1697  | 0  |             CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,  | 
1698  | 0  |                           GDALSharedDatasetFreeFunc);  | 
1699  |  | 
  | 
1700  | 0  |     SharedDatasetCtxt *psStruct =  | 
1701  | 0  |         static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));  | 
1702  | 0  |     psStruct->poDS = this;  | 
1703  | 0  |     psStruct->nPID = nPID;  | 
1704  | 0  |     psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;  | 
1705  | 0  |     psStruct->pszDescription = CPLStrdup(GetDescription());  | 
1706  | 0  |     std::string osConcatenatedOpenOptions =  | 
1707  | 0  |         GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);  | 
1708  | 0  |     psStruct->pszConcatenatedOpenOptions =  | 
1709  | 0  |         CPLStrdup(osConcatenatedOpenOptions.c_str());  | 
1710  | 0  |     if (CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)  | 
1711  | 0  |     { | 
1712  | 0  |         GDALSharedDatasetFreeFunc(psStruct);  | 
1713  | 0  |         ReportError(CE_Failure, CPLE_AppDefined,  | 
1714  | 0  |                     "An existing shared dataset already has this description. "  | 
1715  | 0  |                     "This should not happen.");  | 
1716  | 0  |     }  | 
1717  | 0  |     else  | 
1718  | 0  |     { | 
1719  | 0  |         CPLHashSetInsert(phSharedDatasetSet, psStruct);  | 
1720  |  | 
  | 
1721  | 0  |         (*poAllDatasetMap)[this] = nPID;  | 
1722  | 0  |     }  | 
1723  | 0  | }  | 
1724  |  |  | 
1725  |  | /************************************************************************/  | 
1726  |  | /*                        MarkSuppressOnClose()                         */  | 
1727  |  | /************************************************************************/  | 
1728  |  |  | 
1729  |  | /** Set that the dataset must be deleted on close. */  | 
1730  |  | void GDALDataset::MarkSuppressOnClose()  | 
1731  | 0  | { | 
1732  | 0  |     bSuppressOnClose = true;  | 
1733  | 0  | }  | 
1734  |  |  | 
1735  |  | /************************************************************************/  | 
1736  |  | /*                       UnMarkSuppressOnClose()                        */  | 
1737  |  | /************************************************************************/  | 
1738  |  |  | 
1739  |  | /** Remove the flag requesting the dataset to be deleted on close. */  | 
1740  |  | void GDALDataset::UnMarkSuppressOnClose()  | 
1741  | 0  | { | 
1742  | 0  |     bSuppressOnClose = false;  | 
1743  | 0  | }  | 
1744  |  |  | 
1745  |  | /************************************************************************/  | 
1746  |  | /*                        CleanupPostFileClosing()                      */  | 
1747  |  | /************************************************************************/  | 
1748  |  |  | 
1749  |  | /** This method should be called by driver implementations in their destructor,  | 
1750  |  |  * after having closed all files, but before having freed resources that  | 
1751  |  |  * are needed for their GetFileList() implementation.  | 
1752  |  |  * This is used to implement MarkSuppressOnClose behavior.  | 
1753  |  |  */  | 
1754  |  | void GDALDataset::CleanupPostFileClosing()  | 
1755  | 0  | { | 
1756  | 0  |     if (IsMarkedSuppressOnClose())  | 
1757  | 0  |     { | 
1758  | 0  |         char **papszFileList = GetFileList();  | 
1759  | 0  |         for (int i = 0; papszFileList && papszFileList[i]; ++i)  | 
1760  | 0  |             VSIUnlink(papszFileList[i]);  | 
1761  | 0  |         CSLDestroy(papszFileList);  | 
1762  | 0  |     }  | 
1763  | 0  | }  | 
1764  |  |  | 
1765  |  | /************************************************************************/  | 
1766  |  | /*                            GetGCPCount()                             */  | 
1767  |  | /************************************************************************/  | 
1768  |  |  | 
1769  |  | /**  | 
1770  |  |  * \brief Get number of GCPs.  | 
1771  |  |  *  | 
1772  |  |  * This method is the same as the C function GDALGetGCPCount().  | 
1773  |  |  *  | 
1774  |  |  * @return number of GCPs for this dataset.  Zero if there are none.  | 
1775  |  |  */  | 
1776  |  |  | 
1777  |  | int GDALDataset::GetGCPCount()  | 
1778  | 0  | { | 
1779  | 0  |     return 0;  | 
1780  | 0  | }  | 
1781  |  |  | 
1782  |  | /************************************************************************/  | 
1783  |  | /*                          GDALGetGCPCount()                           */  | 
1784  |  | /************************************************************************/  | 
1785  |  |  | 
1786  |  | /**  | 
1787  |  |  * \brief Get number of GCPs.  | 
1788  |  |  *  | 
1789  |  |  * @see GDALDataset::GetGCPCount()  | 
1790  |  |  */  | 
1791  |  |  | 
1792  |  | int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)  | 
1793  |  |  | 
1794  | 0  | { | 
1795  | 0  |     VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);  | 
1796  |  |  | 
1797  | 0  |     return GDALDataset::FromHandle(hDS)->GetGCPCount();  | 
1798  | 0  | }  | 
1799  |  |  | 
1800  |  | /************************************************************************/  | 
1801  |  | /*                          GetGCPProjection()                          */  | 
1802  |  | /************************************************************************/  | 
1803  |  |  | 
1804  |  | /**  | 
1805  |  |  * \brief Get output projection for GCPs.  | 
1806  |  |  *  | 
1807  |  |  * This method is the same as the C function GDALGetGCPProjection().  | 
1808  |  |  *  | 
1809  |  |  * The projection string follows the normal rules from GetProjectionRef().  | 
1810  |  |  *  | 
1811  |  |  * \note Starting with GDAL 3.0, this is a compatibility layer around  | 
1812  |  |  * GetGCPSpatialRef()  | 
1813  |  |  *  | 
1814  |  |  * @return internal projection string or "" if there are no GCPs.  | 
1815  |  |  *  It should not be altered, freed or expected to last for long.  | 
1816  |  |  */  | 
1817  |  |  | 
1818  |  | const char *GDALDataset::GetGCPProjection()  | 
1819  | 0  | { | 
1820  | 0  |     const auto poSRS = GetGCPSpatialRef();  | 
1821  | 0  |     if (!poSRS || !m_poPrivate)  | 
1822  | 0  |     { | 
1823  | 0  |         return "";  | 
1824  | 0  |     }  | 
1825  | 0  |     char *pszWKT = nullptr;  | 
1826  | 0  |     poSRS->exportToWkt(&pszWKT);  | 
1827  | 0  |     if (!pszWKT)  | 
1828  | 0  |     { | 
1829  | 0  |         return "";  | 
1830  | 0  |     }  | 
1831  |  |  | 
1832  |  |     // If called on a thread-safe dataset, we might be called by several  | 
1833  |  |     // threads, so make sure our accesses to m_pszWKTCached are protected  | 
1834  |  |     // by a mutex.  | 
1835  | 0  |     std::lock_guard oLock(m_poPrivate->m_oMutexWKT);  | 
1836  | 0  |     if (m_poPrivate->m_pszWKTGCPCached &&  | 
1837  | 0  |         strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0)  | 
1838  | 0  |     { | 
1839  | 0  |         CPLFree(pszWKT);  | 
1840  | 0  |         return m_poPrivate->m_pszWKTGCPCached;  | 
1841  | 0  |     }  | 
1842  | 0  |     CPLFree(m_poPrivate->m_pszWKTGCPCached);  | 
1843  | 0  |     m_poPrivate->m_pszWKTGCPCached = pszWKT;  | 
1844  | 0  |     return m_poPrivate->m_pszWKTGCPCached;  | 
1845  | 0  | }  | 
1846  |  |  | 
1847  |  | /************************************************************************/  | 
1848  |  | /*                          GetGCPSpatialRef()                          */  | 
1849  |  | /************************************************************************/  | 
1850  |  |  | 
1851  |  | /**  | 
1852  |  |  * \brief Get output spatial reference system for GCPs.  | 
1853  |  |  *  | 
1854  |  |  * Same as the C function GDALGetGCPSpatialRef().  | 
1855  |  |  *  | 
1856  |  |  * When a SRS is not available, null is returned. If used on  | 
1857  |  |  * a dataset where there is a geotransform, and not GCPs, this method returns  | 
1858  |  |  * null. Use GetSpatialRef() instead.  | 
1859  |  |  *  | 
1860  |  |  * @since GDAL 3.0  | 
1861  |  |  *  | 
1862  |  |  * @return a pointer to an internal object. It should not be altered or freed.  | 
1863  |  |  * Its lifetime will be the one of the dataset object, or until the next  | 
1864  |  |  * call to this method.  | 
1865  |  |  */  | 
1866  |  |  | 
1867  |  | const OGRSpatialReference *GDALDataset::GetGCPSpatialRef() const  | 
1868  | 0  | { | 
1869  | 0  |     return nullptr;  | 
1870  | 0  | }  | 
1871  |  |  | 
1872  |  | /************************************************************************/  | 
1873  |  | /*                       GDALGetGCPSpatialRef()                         */  | 
1874  |  | /************************************************************************/  | 
1875  |  |  | 
1876  |  | /**  | 
1877  |  |  * \brief Get output spatial reference system for GCPs.  | 
1878  |  |  *  | 
1879  |  |  * @since GDAL 3.0  | 
1880  |  |  *  | 
1881  |  |  * @see GDALDataset::GetGCPSpatialRef()  | 
1882  |  |  */  | 
1883  |  |  | 
1884  |  | OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)  | 
1885  |  |  | 
1886  | 0  | { | 
1887  | 0  |     VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);  | 
1888  |  |  | 
1889  | 0  |     return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(  | 
1890  | 0  |         GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));  | 
1891  | 0  | }  | 
1892  |  |  | 
1893  |  | /************************************************************************/  | 
1894  |  | /*                        GDALGetGCPProjection()                        */  | 
1895  |  | /************************************************************************/  | 
1896  |  |  | 
1897  |  | /**  | 
1898  |  |  * \brief Get output projection for GCPs.  | 
1899  |  |  *  | 
1900  |  |  * @see GDALDataset::GetGCPProjection()  | 
1901  |  |  */  | 
1902  |  |  | 
1903  |  | const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)  | 
1904  |  |  | 
1905  | 0  | { | 
1906  | 0  |     VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);  | 
1907  |  |  | 
1908  | 0  |     return GDALDataset::FromHandle(hDS)->GetGCPProjection();  | 
1909  | 0  | }  | 
1910  |  |  | 
1911  |  | /************************************************************************/  | 
1912  |  | /*                               GetGCPs()                              */  | 
1913  |  | /************************************************************************/  | 
1914  |  |  | 
1915  |  | /**  | 
1916  |  |  * \brief Fetch GCPs.  | 
1917  |  |  *  | 
1918  |  |  * This method is the same as the C function GDALGetGCPs().  | 
1919  |  |  *  | 
1920  |  |  * @return pointer to internal GCP structure list.  It should not be modified,  | 
1921  |  |  * and may change on the next GDAL call.  | 
1922  |  |  */  | 
1923  |  |  | 
1924  |  | const GDAL_GCP *GDALDataset::GetGCPs()  | 
1925  | 0  | { | 
1926  | 0  |     return nullptr;  | 
1927  | 0  | }  | 
1928  |  |  | 
1929  |  | /************************************************************************/  | 
1930  |  | /*                            GDALGetGCPs()                             */  | 
1931  |  | /************************************************************************/  | 
1932  |  |  | 
1933  |  | /**  | 
1934  |  |  * \brief Fetch GCPs.  | 
1935  |  |  *  | 
1936  |  |  * @see GDALDataset::GetGCPs()  | 
1937  |  |  */  | 
1938  |  |  | 
1939  |  | const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)  | 
1940  |  |  | 
1941  | 0  | { | 
1942  | 0  |     VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);  | 
1943  |  |  | 
1944  | 0  |     return GDALDataset::FromHandle(hDS)->GetGCPs();  | 
1945  | 0  | }  | 
1946  |  |  | 
1947  |  | /************************************************************************/  | 
1948  |  | /*                              SetGCPs()                               */  | 
1949  |  | /************************************************************************/  | 
1950  |  |  | 
1951  |  | /**  | 
1952  |  |  * \brief Assign GCPs.  | 
1953  |  |  *  | 
1954  |  |  * This method is the same as the C function GDALSetGCPs().  | 
1955  |  |  *  | 
1956  |  |  * This method assigns the passed set of GCPs to this dataset, as well as  | 
1957  |  |  * setting their coordinate system.  Internally copies are made of the  | 
1958  |  |  * coordinate system and list of points, so the caller remains responsible for  | 
1959  |  |  * deallocating these arguments if appropriate.  | 
1960  |  |  *  | 
1961  |  |  * Most formats do not support setting of GCPs, even formats that can  | 
1962  |  |  * handle GCPs.  These formats will return CE_Failure.  | 
1963  |  |  *  | 
1964  |  |  * \note Startig with GDAL 3.0, this is a compatibility layer around  | 
1965  |  |  * SetGCPs(int, const GDAL_GCP*, const char*)  | 
1966  |  |  *  | 
1967  |  |  * @param nGCPCount number of GCPs being assigned.  | 
1968  |  |  *  | 
1969  |  |  * @param pasGCPList array of GCP structures being assign (nGCPCount in array).  | 
1970  |  |  *  | 
1971  |  |  * @param pszGCPProjection the new OGC WKT coordinate system to assign for the  | 
1972  |  |  * GCP output coordinates.  This parameter should be "" if no output coordinate  | 
1973  |  |  * system is known.  | 
1974  |  |  *  | 
1975  |  |  * @return CE_None on success, CE_Failure on failure (including if action is  | 
1976  |  |  * not supported for this format).  | 
1977  |  |  */  | 
1978  |  |  | 
1979  |  | CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,  | 
1980  |  |                             const char *pszGCPProjection)  | 
1981  |  |  | 
1982  | 0  | { | 
1983  | 0  |     if (pszGCPProjection && pszGCPProjection[0] != '\0')  | 
1984  | 0  |     { | 
1985  | 0  |         OGRSpatialReference oSRS;  | 
1986  | 0  |         oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);  | 
1987  | 0  |         if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)  | 
1988  | 0  |         { | 
1989  | 0  |             return CE_Failure;  | 
1990  | 0  |         }  | 
1991  | 0  |         return SetGCPs(nGCPCount, pasGCPList, &oSRS);  | 
1992  | 0  |     }  | 
1993  | 0  |     else  | 
1994  | 0  |     { | 
1995  | 0  |         return SetGCPs(nGCPCount, pasGCPList,  | 
1996  | 0  |                        static_cast<const OGRSpatialReference *>(nullptr));  | 
1997  | 0  |     }  | 
1998  | 0  | }  | 
1999  |  |  | 
2000  |  | /************************************************************************/  | 
2001  |  | /*                              SetGCPs()                               */  | 
2002  |  | /************************************************************************/  | 
2003  |  |  | 
2004  |  | /**  | 
2005  |  |  * \brief Assign GCPs.  | 
2006  |  |  *  | 
2007  |  |  * This method is the same as the C function GDALSetGCPs().  | 
2008  |  |  *  | 
2009  |  |  * This method assigns the passed set of GCPs to this dataset, as well as  | 
2010  |  |  * setting their coordinate system.  Internally copies are made of the  | 
2011  |  |  * coordinate system and list of points, so the caller remains responsible for  | 
2012  |  |  * deallocating these arguments if appropriate.  | 
2013  |  |  *  | 
2014  |  |  * Most formats do not support setting of GCPs, even formats that can  | 
2015  |  |  * handle GCPs.  These formats will return CE_Failure.  | 
2016  |  |  *  | 
2017  |  |  * @since GDAL 3.0  | 
2018  |  |  *  | 
2019  |  |  * @param nGCPCount number of GCPs being assigned.  | 
2020  |  |  *  | 
2021  |  |  * @param pasGCPList array of GCP structures being assign (nGCPCount in array).  | 
2022  |  |  *  | 
2023  |  |  * @param poGCP_SRS the new coordinate reference system to assign for the  | 
2024  |  |  * GCP output coordinates.  This parameter should be null if no output  | 
2025  |  |  * coordinate system is known.  | 
2026  |  |  *  | 
2027  |  |  * @return CE_None on success, CE_Failure on failure (including if action is  | 
2028  |  |  * not supported for this format).  | 
2029  |  |  */  | 
2030  |  |  | 
2031  |  | CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,  | 
2032  |  |                             CPL_UNUSED const GDAL_GCP *pasGCPList,  | 
2033  |  |                             CPL_UNUSED const OGRSpatialReference *poGCP_SRS)  | 
2034  |  |  | 
2035  | 0  | { | 
2036  | 0  |     if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))  | 
2037  | 0  |         ReportError(CE_Failure, CPLE_NotSupported,  | 
2038  | 0  |                     "Dataset does not support the SetGCPs() method.");  | 
2039  |  | 
  | 
2040  | 0  |     return CE_Failure;  | 
2041  | 0  | }  | 
2042  |  |  | 
2043  |  | /************************************************************************/  | 
2044  |  | /*                            GDALSetGCPs()                             */  | 
2045  |  | /************************************************************************/  | 
2046  |  |  | 
2047  |  | /**  | 
2048  |  |  * \brief Assign GCPs.  | 
2049  |  |  *  | 
2050  |  |  * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)  | 
2051  |  |  */  | 
2052  |  |  | 
2053  |  | CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,  | 
2054  |  |                                const GDAL_GCP *pasGCPList,  | 
2055  |  |                                const char *pszGCPProjection)  | 
2056  |  |  | 
2057  | 0  | { | 
2058  | 0  |     VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);  | 
2059  |  |  | 
2060  | 0  |     return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,  | 
2061  | 0  |                                                  pszGCPProjection);  | 
2062  | 0  | }  | 
2063  |  |  | 
2064  |  | /************************************************************************/  | 
2065  |  | /*                           GDALSetGCPs2()                             */  | 
2066  |  | /************************************************************************/  | 
2067  |  |  | 
2068  |  | /**  | 
2069  |  |  * \brief Assign GCPs.  | 
2070  |  |  *  | 
2071  |  |  * @since GDAL 3.0  | 
2072  |  |  * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)  | 
2073  |  |  */  | 
2074  |  |  | 
2075  |  | CPLErr GDALSetGCPs2(GDALDatasetH hDS, int nGCPCount, const GDAL_GCP *pasGCPList,  | 
2076  |  |                     OGRSpatialReferenceH hSRS)  | 
2077  |  |  | 
2078  | 0  | { | 
2079  | 0  |     VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);  | 
2080  |  |  | 
2081  | 0  |     return GDALDataset::FromHandle(hDS)->SetGCPs(  | 
2082  | 0  |         nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));  | 
2083  | 0  | }  | 
2084  |  |  | 
2085  |  | /************************************************************************/  | 
2086  |  | /*                           BuildOverviews()                           */  | 
2087  |  | /************************************************************************/  | 
2088  |  |  | 
2089  |  | /**  | 
2090  |  |  * \brief Build raster overview(s)  | 
2091  |  |  *  | 
2092  |  |  * If the operation is unsupported for the indicated dataset, then  | 
2093  |  |  * CE_Failure is returned, and CPLGetLastErrorNo() will return  | 
2094  |  |  * CPLE_NotSupported.  | 
2095  |  |  *  | 
2096  |  |  * Depending on the actual file format, all overviews level can be also  | 
2097  |  |  * deleted by specifying nOverviews == 0. This works at least for external  | 
2098  |  |  * overviews (.ovr), TIFF internal overviews, etc.  | 
2099  |  |  *  | 
2100  |  |  * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set  | 
2101  |  |  * to "ALL_CPUS" or a integer value to specify the number of threads to use for  | 
2102  |  |  * overview computation.  | 
2103  |  |  *  | 
2104  |  |  * This method is the same as the C function GDALBuildOverviewsEx().  | 
2105  |  |  *  | 
2106  |  |  * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",  | 
2107  |  |  * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",  | 
2108  |  |  * or "NONE" controlling the downsampling method applied.  | 
2109  |  |  * @param nOverviews number of overviews to build, or 0 to clean overviews.  | 
2110  |  |  * @param panOverviewList the list of overview decimation factors (positive  | 
2111  |  |  *                        integers, normally larger or equal to 2) to build, or  | 
2112  |  |  *                        NULL if nOverviews == 0.  | 
2113  |  |  * @param nListBands number of bands to build overviews for in panBandList.  | 
2114  |  |  * Build for all bands if this is 0.  | 
2115  |  |  * @param panBandList list of band numbers.  | 
2116  |  |  * @param pfnProgress a function to call to report progress, or NULL.  | 
2117  |  |  * @param pProgressData application data to pass to the progress function.  | 
2118  |  |  * @param papszOptions (GDAL >= 3.6) NULL terminated list of options as  | 
2119  |  |  *                     key=value pairs, or NULL  | 
2120  |  |  *  | 
2121  |  |  * @return CE_None on success or CE_Failure if the operation doesn't work.  | 
2122  |  |  *  | 
2123  |  |  * For example, to build overview level 2, 4 and 8 on all bands the following  | 
2124  |  |  * call could be made:  | 
2125  |  |  * \code{.cpp} | 
2126  |  |  *   int       anOverviewList[3] = { 2, 4, 8 }; | 
2127  |  |  *  | 
2128  |  |  *   poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,  | 
2129  |  |  *                              GDALDummyProgress, nullptr );  | 
2130  |  |  * \endcode  | 
2131  |  |  *  | 
2132  |  |  * @see GDALRegenerateOverviewsEx()  | 
2133  |  |  */  | 
2134  |  |  | 
2135  |  | CPLErr GDALDataset::BuildOverviews(const char *pszResampling, int nOverviews,  | 
2136  |  |                                    const int *panOverviewList, int nListBands,  | 
2137  |  |                                    const int *panBandList,  | 
2138  |  |                                    GDALProgressFunc pfnProgress,  | 
2139  |  |                                    void *pProgressData,  | 
2140  |  |                                    CSLConstList papszOptions)  | 
2141  | 0  | { | 
2142  | 0  |     int *panAllBandList = nullptr;  | 
2143  |  | 
  | 
2144  | 0  |     if (nListBands == 0)  | 
2145  | 0  |     { | 
2146  | 0  |         nListBands = GetRasterCount();  | 
2147  | 0  |         panAllBandList =  | 
2148  | 0  |             static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));  | 
2149  | 0  |         for (int i = 0; i < nListBands; ++i)  | 
2150  | 0  |             panAllBandList[i] = i + 1;  | 
2151  |  | 
  | 
2152  | 0  |         panBandList = panAllBandList;  | 
2153  | 0  |     }  | 
2154  |  | 
  | 
2155  | 0  |     if (pfnProgress == nullptr)  | 
2156  | 0  |         pfnProgress = GDALDummyProgress;  | 
2157  |  | 
  | 
2158  | 0  |     for (int i = 0; i < nOverviews; ++i)  | 
2159  | 0  |     { | 
2160  | 0  |         if (panOverviewList[i] <= 0)  | 
2161  | 0  |         { | 
2162  | 0  |             CPLError(CE_Failure, CPLE_IllegalArg,  | 
2163  | 0  |                      "panOverviewList[%d] = %d is invalid. It must be a "  | 
2164  | 0  |                      "positive value",  | 
2165  | 0  |                      i, panOverviewList[i]);  | 
2166  | 0  |             CPLFree(panAllBandList);  | 
2167  | 0  |             return CE_Failure;  | 
2168  | 0  |         }  | 
2169  | 0  |     }  | 
2170  |  |  | 
2171  |  |     // At time of writing, all overview generation options are actually  | 
2172  |  |     // expected to be passed as configuration options.  | 
2173  | 0  |     std::vector<std::unique_ptr<CPLConfigOptionSetter>> apoConfigOptionSetter;  | 
2174  | 0  |     for (const auto &[pszKey, pszValue] : cpl::IterateNameValue(papszOptions))  | 
2175  | 0  |     { | 
2176  | 0  |         apoConfigOptionSetter.emplace_back(  | 
2177  | 0  |             std::make_unique<CPLConfigOptionSetter>(pszKey, pszValue, false));  | 
2178  | 0  |     }  | 
2179  |  | 
  | 
2180  | 0  |     const CPLErr eErr =  | 
2181  | 0  |         IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,  | 
2182  | 0  |                         panBandList, pfnProgress, pProgressData, papszOptions);  | 
2183  |  | 
  | 
2184  | 0  |     if (panAllBandList != nullptr)  | 
2185  | 0  |         CPLFree(panAllBandList);  | 
2186  |  | 
  | 
2187  | 0  |     return eErr;  | 
2188  | 0  | }  | 
2189  |  |  | 
2190  |  | /************************************************************************/  | 
2191  |  | /*                         GDALBuildOverviews()                         */  | 
2192  |  | /************************************************************************/  | 
2193  |  |  | 
2194  |  | /**  | 
2195  |  |  * \brief Build raster overview(s)  | 
2196  |  |  *  | 
2197  |  |  * @see GDALDataset::BuildOverviews() and GDALBuildOverviews()  | 
2198  |  |  */  | 
2199  |  |  | 
2200  |  | CPLErr CPL_STDCALL GDALBuildOverviews(GDALDatasetH hDataset,  | 
2201  |  |                                       const char *pszResampling, int nOverviews,  | 
2202  |  |                                       const int *panOverviewList,  | 
2203  |  |                                       int nListBands, const int *panBandList,  | 
2204  |  |                                       GDALProgressFunc pfnProgress,  | 
2205  |  |                                       void *pProgressData)  | 
2206  |  |  | 
2207  | 0  | { | 
2208  | 0  |     VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);  | 
2209  |  |  | 
2210  | 0  |     return GDALDataset::FromHandle(hDataset)->BuildOverviews(  | 
2211  | 0  |         pszResampling, nOverviews, panOverviewList, nListBands, panBandList,  | 
2212  | 0  |         pfnProgress, pProgressData, nullptr);  | 
2213  | 0  | }  | 
2214  |  |  | 
2215  |  | /************************************************************************/  | 
2216  |  | /*                         GDALBuildOverviews()                         */  | 
2217  |  | /************************************************************************/  | 
2218  |  |  | 
2219  |  | /**  | 
2220  |  |  * \brief Build raster overview(s)  | 
2221  |  |  *  | 
2222  |  |  * @see GDALDataset::BuildOverviews()  | 
2223  |  |  * @since GDAL 3.6  | 
2224  |  |  */  | 
2225  |  |  | 
2226  |  | CPLErr CPL_STDCALL  | 
2227  |  | GDALBuildOverviewsEx(GDALDatasetH hDataset, const char *pszResampling,  | 
2228  |  |                      int nOverviews, const int *panOverviewList, int nListBands,  | 
2229  |  |                      const int *panBandList, GDALProgressFunc pfnProgress,  | 
2230  |  |                      void *pProgressData, CSLConstList papszOptions)  | 
2231  |  |  | 
2232  | 0  | { | 
2233  | 0  |     VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);  | 
2234  |  |  | 
2235  | 0  |     return GDALDataset::FromHandle(hDataset)->BuildOverviews(  | 
2236  | 0  |         pszResampling, nOverviews, panOverviewList, nListBands, panBandList,  | 
2237  | 0  |         pfnProgress, pProgressData, papszOptions);  | 
2238  | 0  | }  | 
2239  |  |  | 
2240  |  | /************************************************************************/  | 
2241  |  | /*                          IBuildOverviews()                           */  | 
2242  |  | /*                                                                      */  | 
2243  |  | /*      Default implementation.                                         */  | 
2244  |  | /************************************************************************/  | 
2245  |  |  | 
2246  |  | //! @cond Doxygen_Suppress  | 
2247  |  | CPLErr GDALDataset::IBuildOverviews(const char *pszResampling, int nOverviews,  | 
2248  |  |                                     const int *panOverviewList, int nListBands,  | 
2249  |  |                                     const int *panBandList,  | 
2250  |  |                                     GDALProgressFunc pfnProgress,  | 
2251  |  |                                     void *pProgressData,  | 
2252  |  |                                     CSLConstList papszOptions)  | 
2253  |  |  | 
2254  | 0  | { | 
2255  | 0  |     if (oOvManager.IsInitialized())  | 
2256  | 0  |         return oOvManager.BuildOverviews(  | 
2257  | 0  |             nullptr, pszResampling, nOverviews, panOverviewList, nListBands,  | 
2258  | 0  |             panBandList, pfnProgress, pProgressData, papszOptions);  | 
2259  | 0  |     else  | 
2260  | 0  |     { | 
2261  | 0  |         ReportError(CE_Failure, CPLE_NotSupported,  | 
2262  | 0  |                     "BuildOverviews() not supported for this dataset.");  | 
2263  |  | 
  | 
2264  | 0  |         return CE_Failure;  | 
2265  | 0  |     }  | 
2266  | 0  | }  | 
2267  |  |  | 
2268  |  | //! @endcond  | 
2269  |  |  | 
2270  |  | /************************************************************************/  | 
2271  |  | /*                             IRasterIO()                              */  | 
2272  |  | /*                                                                      */  | 
2273  |  | /*      The default implementation of IRasterIO() is, in the general    */  | 
2274  |  | /*      case to pass the request off to each band objects rasterio      */  | 
2275  |  | /*      methods with appropriate arguments. In some cases, it might     */  | 
2276  |  | /*      choose instead the BlockBasedRasterIO() implementation.         */  | 
2277  |  | /************************************************************************/  | 
2278  |  |  | 
2279  |  | //! @cond Doxygen_Suppress  | 
2280  |  | CPLErr GDALDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,  | 
2281  |  |                               int nXSize, int nYSize, void *pData,  | 
2282  |  |                               int nBufXSize, int nBufYSize,  | 
2283  |  |                               GDALDataType eBufType, int nBandCount,  | 
2284  |  |                               BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,  | 
2285  |  |                               GSpacing nLineSpace, GSpacing nBandSpace,  | 
2286  |  |                               GDALRasterIOExtraArg *psExtraArg)  | 
2287  |  |  | 
2288  | 0  | { | 
2289  | 0  |     const char *pszInterleave = nullptr;  | 
2290  |  | 
  | 
2291  | 0  |     CPLAssert(nullptr != pData);  | 
2292  |  |  | 
2293  | 0  |     const bool bHasSubpixelShift =  | 
2294  | 0  |         psExtraArg->bFloatingPointWindowValidity &&  | 
2295  | 0  |         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&  | 
2296  | 0  |         (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);  | 
2297  |  | 
  | 
2298  | 0  |     if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&  | 
2299  | 0  |         nBandCount > 1 &&  | 
2300  | 0  |         (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) != | 
2301  | 0  |             nullptr &&  | 
2302  | 0  |         EQUAL(pszInterleave, "PIXEL"))  | 
2303  | 0  |     { | 
2304  | 0  |         return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,  | 
2305  | 0  |                                   nBufXSize, nBufYSize, eBufType, nBandCount,  | 
2306  | 0  |                                   panBandMap, nPixelSpace, nLineSpace,  | 
2307  | 0  |                                   nBandSpace, psExtraArg);  | 
2308  | 0  |     }  | 
2309  |  |  | 
2310  | 0  |     if (eRWFlag == GF_Read &&  | 
2311  | 0  |         (psExtraArg->eResampleAlg == GRIORA_Cubic ||  | 
2312  | 0  |          psExtraArg->eResampleAlg == GRIORA_CubicSpline ||  | 
2313  | 0  |          psExtraArg->eResampleAlg == GRIORA_Bilinear ||  | 
2314  | 0  |          psExtraArg->eResampleAlg == GRIORA_Lanczos) &&  | 
2315  | 0  |         !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)  | 
2316  | 0  |     { | 
2317  | 0  |         if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())  | 
2318  | 0  |         { | 
2319  | 0  |             int bTried = FALSE;  | 
2320  | 0  |             const CPLErr eErr = TryOverviewRasterIO(  | 
2321  | 0  |                 eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,  | 
2322  | 0  |                 nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,  | 
2323  | 0  |                 nLineSpace, nBandSpace, psExtraArg, &bTried);  | 
2324  | 0  |             if (bTried)  | 
2325  | 0  |                 return eErr;  | 
2326  | 0  |         }  | 
2327  |  |  | 
2328  | 0  |         GDALDataType eFirstBandDT = GDT_Unknown;  | 
2329  | 0  |         int nFirstMaskFlags = 0;  | 
2330  | 0  |         GDALRasterBand *poFirstMaskBand = nullptr;  | 
2331  | 0  |         int nOKBands = 0;  | 
2332  |  |  | 
2333  |  |         // Check if bands share the same mask band  | 
2334  | 0  |         for (int i = 0; i < nBandCount; ++i)  | 
2335  | 0  |         { | 
2336  | 0  |             GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);  | 
2337  | 0  |             if ((nBufXSize < nXSize || nBufYSize < nYSize) &&  | 
2338  | 0  |                 poBand->GetOverviewCount())  | 
2339  | 0  |             { | 
2340  |  |                 // Could be improved to select the appropriate overview.  | 
2341  | 0  |                 break;  | 
2342  | 0  |             }  | 
2343  | 0  |             if (poBand->GetColorTable() != nullptr)  | 
2344  | 0  |             { | 
2345  | 0  |                 break;  | 
2346  | 0  |             }  | 
2347  | 0  |             const GDALDataType eDT = poBand->GetRasterDataType();  | 
2348  | 0  |             if (GDALDataTypeIsComplex(eDT))  | 
2349  | 0  |             { | 
2350  | 0  |                 break;  | 
2351  | 0  |             }  | 
2352  | 0  |             if (i == 0)  | 
2353  | 0  |             { | 
2354  | 0  |                 eFirstBandDT = eDT;  | 
2355  | 0  |                 nFirstMaskFlags = poBand->GetMaskFlags();  | 
2356  | 0  |                 if (nFirstMaskFlags == GMF_NODATA)  | 
2357  | 0  |                 { | 
2358  |  |                     // The dataset-level resampling code is not ready for nodata  | 
2359  |  |                     // Fallback to band-level resampling  | 
2360  | 0  |                     break;  | 
2361  | 0  |                 }  | 
2362  | 0  |                 poFirstMaskBand = poBand->GetMaskBand();  | 
2363  | 0  |             }  | 
2364  | 0  |             else  | 
2365  | 0  |             { | 
2366  | 0  |                 if (eDT != eFirstBandDT)  | 
2367  | 0  |                 { | 
2368  | 0  |                     break;  | 
2369  | 0  |                 }  | 
2370  | 0  |                 int nMaskFlags = poBand->GetMaskFlags();  | 
2371  | 0  |                 if (nMaskFlags == GMF_NODATA)  | 
2372  | 0  |                 { | 
2373  |  |                     // The dataset-level resampling code is not ready for nodata  | 
2374  |  |                     // Fallback to band-level resampling  | 
2375  | 0  |                     break;  | 
2376  | 0  |                 }  | 
2377  | 0  |                 GDALRasterBand *poMaskBand = poBand->GetMaskBand();  | 
2378  | 0  |                 if (nFirstMaskFlags == GMF_ALL_VALID &&  | 
2379  | 0  |                     nMaskFlags == GMF_ALL_VALID)  | 
2380  | 0  |                 { | 
2381  |  |                     // Ok.  | 
2382  | 0  |                 }  | 
2383  | 0  |                 else if (poFirstMaskBand == poMaskBand)  | 
2384  | 0  |                 { | 
2385  |  |                     // Ok.  | 
2386  | 0  |                 }  | 
2387  | 0  |                 else  | 
2388  | 0  |                 { | 
2389  | 0  |                     break;  | 
2390  | 0  |                 }  | 
2391  | 0  |             }  | 
2392  |  |  | 
2393  | 0  |             ++nOKBands;  | 
2394  | 0  |         }  | 
2395  |  | 
  | 
2396  | 0  |         GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;  | 
2397  | 0  |         void *pProgressDataGlobal = psExtraArg->pProgressData;  | 
2398  |  | 
  | 
2399  | 0  |         CPLErr eErr = CE_None;  | 
2400  | 0  |         if (nOKBands > 0)  | 
2401  | 0  |         { | 
2402  | 0  |             if (nOKBands < nBandCount)  | 
2403  | 0  |             { | 
2404  | 0  |                 psExtraArg->pfnProgress = GDALScaledProgress;  | 
2405  | 0  |                 psExtraArg->pProgressData = GDALCreateScaledProgress(  | 
2406  | 0  |                     0.0, static_cast<double>(nOKBands) / nBandCount,  | 
2407  | 0  |                     pfnProgressGlobal, pProgressDataGlobal);  | 
2408  | 0  |                 if (psExtraArg->pProgressData == nullptr)  | 
2409  | 0  |                     psExtraArg->pfnProgress = nullptr;  | 
2410  | 0  |             }  | 
2411  |  | 
  | 
2412  | 0  |             eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,  | 
2413  | 0  |                                      pData, nBufXSize, nBufYSize, eBufType,  | 
2414  | 0  |                                      nOKBands, panBandMap, nPixelSpace,  | 
2415  | 0  |                                      nLineSpace, nBandSpace, psExtraArg);  | 
2416  |  | 
  | 
2417  | 0  |             if (nOKBands < nBandCount)  | 
2418  | 0  |             { | 
2419  | 0  |                 GDALDestroyScaledProgress(psExtraArg->pProgressData);  | 
2420  | 0  |             }  | 
2421  | 0  |         }  | 
2422  | 0  |         if (eErr == CE_None && nOKBands < nBandCount)  | 
2423  | 0  |         { | 
2424  | 0  |             if (nOKBands > 0)  | 
2425  | 0  |             { | 
2426  | 0  |                 psExtraArg->pfnProgress = GDALScaledProgress;  | 
2427  | 0  |                 psExtraArg->pProgressData = GDALCreateScaledProgress(  | 
2428  | 0  |                     static_cast<double>(nOKBands) / nBandCount, 1.0,  | 
2429  | 0  |                     pfnProgressGlobal, pProgressDataGlobal);  | 
2430  | 0  |                 if (psExtraArg->pProgressData == nullptr)  | 
2431  | 0  |                     psExtraArg->pfnProgress = nullptr;  | 
2432  | 0  |             }  | 
2433  | 0  |             eErr = BandBasedRasterIO(  | 
2434  | 0  |                 eRWFlag, nXOff, nYOff, nXSize, nYSize,  | 
2435  | 0  |                 static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,  | 
2436  | 0  |                 nBufYSize, eBufType, nBandCount - nOKBands,  | 
2437  | 0  |                 panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,  | 
2438  | 0  |                 psExtraArg);  | 
2439  | 0  |             if (nOKBands > 0)  | 
2440  | 0  |             { | 
2441  | 0  |                 GDALDestroyScaledProgress(psExtraArg->pProgressData);  | 
2442  | 0  |             }  | 
2443  | 0  |         }  | 
2444  |  | 
  | 
2445  | 0  |         psExtraArg->pfnProgress = pfnProgressGlobal;  | 
2446  | 0  |         psExtraArg->pProgressData = pProgressDataGlobal;  | 
2447  |  | 
  | 
2448  | 0  |         return eErr;  | 
2449  | 0  |     }  | 
2450  |  |  | 
2451  | 0  |     return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,  | 
2452  | 0  |                              nBufXSize, nBufYSize, eBufType, nBandCount,  | 
2453  | 0  |                              panBandMap, nPixelSpace, nLineSpace, nBandSpace,  | 
2454  | 0  |                              psExtraArg);  | 
2455  | 0  | }  | 
2456  |  |  | 
2457  |  | //! @endcond  | 
2458  |  |  | 
2459  |  | /************************************************************************/  | 
2460  |  | /*                         BandBasedRasterIO()                          */  | 
2461  |  | /*                                                                      */  | 
2462  |  | /*      Pass the request off to each band objects rasterio methods with */  | 
2463  |  | /*      appropriate arguments.                                          */  | 
2464  |  | /************************************************************************/  | 
2465  |  |  | 
2466  |  | //! @cond Doxygen_Suppress  | 
2467  |  | CPLErr GDALDataset::BandBasedRasterIO(  | 
2468  |  |     GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,  | 
2469  |  |     void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,  | 
2470  |  |     int nBandCount, const int *panBandMap, GSpacing nPixelSpace,  | 
2471  |  |     GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)  | 
2472  |  |  | 
2473  | 0  | { | 
2474  | 0  |     int iBandIndex;  | 
2475  | 0  |     CPLErr eErr = CE_None;  | 
2476  |  | 
  | 
2477  | 0  |     GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;  | 
2478  | 0  |     void *pProgressDataGlobal = psExtraArg->pProgressData;  | 
2479  |  | 
  | 
2480  | 0  |     for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;  | 
2481  | 0  |          ++iBandIndex)  | 
2482  | 0  |     { | 
2483  | 0  |         GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);  | 
2484  |  | 
  | 
2485  | 0  |         if (poBand == nullptr)  | 
2486  | 0  |         { | 
2487  | 0  |             eErr = CE_Failure;  | 
2488  | 0  |             break;  | 
2489  | 0  |         }  | 
2490  |  |  | 
2491  | 0  |         GByte *pabyBandData =  | 
2492  | 0  |             static_cast<GByte *>(pData) + iBandIndex * nBandSpace;  | 
2493  |  | 
  | 
2494  | 0  |         if (nBandCount > 1)  | 
2495  | 0  |         { | 
2496  | 0  |             psExtraArg->pfnProgress = GDALScaledProgress;  | 
2497  | 0  |             psExtraArg->pProgressData = GDALCreateScaledProgress(  | 
2498  | 0  |                 1.0 * iBandIndex / nBandCount,  | 
2499  | 0  |                 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,  | 
2500  | 0  |                 pProgressDataGlobal);  | 
2501  | 0  |             if (psExtraArg->pProgressData == nullptr)  | 
2502  | 0  |                 psExtraArg->pfnProgress = nullptr;  | 
2503  | 0  |         }  | 
2504  |  | 
  | 
2505  | 0  |         eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,  | 
2506  | 0  |                                  pabyBandData, nBufXSize, nBufYSize, eBufType,  | 
2507  | 0  |                                  nPixelSpace, nLineSpace, psExtraArg);  | 
2508  |  | 
  | 
2509  | 0  |         if (nBandCount > 1)  | 
2510  | 0  |             GDALDestroyScaledProgress(psExtraArg->pProgressData);  | 
2511  | 0  |     }  | 
2512  |  | 
  | 
2513  | 0  |     psExtraArg->pfnProgress = pfnProgressGlobal;  | 
2514  | 0  |     psExtraArg->pProgressData = pProgressDataGlobal;  | 
2515  |  | 
  | 
2516  | 0  |     return eErr;  | 
2517  | 0  | }  | 
2518  |  |  | 
2519  |  | //! @endcond  | 
2520  |  |  | 
2521  |  | /************************************************************************/  | 
2522  |  | /*               ValidateRasterIOOrAdviseReadParameters()               */  | 
2523  |  | /************************************************************************/  | 
2524  |  |  | 
2525  |  | //! @cond Doxygen_Suppress  | 
2526  |  | CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(  | 
2527  |  |     const char *pszCallingFunc, int *pbStopProcessingOnCENone, int nXOff,  | 
2528  |  |     int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize,  | 
2529  |  |     int nBandCount, const int *panBandMap)  | 
2530  | 0  | { | 
2531  |  |  | 
2532  |  |     /* -------------------------------------------------------------------- */  | 
2533  |  |     /*      Some size values are "noop".  Lets just return to avoid         */  | 
2534  |  |     /*      stressing lower level functions.                                */  | 
2535  |  |     /* -------------------------------------------------------------------- */  | 
2536  | 0  |     if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)  | 
2537  | 0  |     { | 
2538  | 0  |         CPLDebug("GDAL", | 
2539  | 0  |                  "%s skipped for odd window or buffer size.\n"  | 
2540  | 0  |                  "  Window = (%d,%d)x%dx%d\n"  | 
2541  | 0  |                  "  Buffer = %dx%d",  | 
2542  | 0  |                  pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nBufXSize,  | 
2543  | 0  |                  nBufYSize);  | 
2544  |  | 
  | 
2545  | 0  |         *pbStopProcessingOnCENone = TRUE;  | 
2546  | 0  |         return CE_None;  | 
2547  | 0  |     }  | 
2548  |  |  | 
2549  | 0  |     CPLErr eErr = CE_None;  | 
2550  | 0  |     *pbStopProcessingOnCENone = FALSE;  | 
2551  |  | 
  | 
2552  | 0  |     if (nXOff < 0 || nXOff > INT_MAX - nXSize ||  | 
2553  | 0  |         nXOff + nXSize > nRasterXSize || nYOff < 0 ||  | 
2554  | 0  |         nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)  | 
2555  | 0  |     { | 
2556  | 0  |         ReportError(CE_Failure, CPLE_IllegalArg,  | 
2557  | 0  |                     "Access window out of range in %s.  Requested "  | 
2558  | 0  |                     "(%d,%d) of size %dx%d on raster of %dx%d.",  | 
2559  | 0  |                     pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,  | 
2560  | 0  |                     nRasterYSize);  | 
2561  | 0  |         eErr = CE_Failure;  | 
2562  | 0  |     }  | 
2563  |  | 
  | 
2564  | 0  |     if (panBandMap == nullptr && nBandCount > GetRasterCount())  | 
2565  | 0  |     { | 
2566  | 0  |         ReportError(CE_Failure, CPLE_IllegalArg,  | 
2567  | 0  |                     "%s: nBandCount cannot be greater than %d", pszCallingFunc,  | 
2568  | 0  |                     GetRasterCount());  | 
2569  | 0  |         eErr = CE_Failure;  | 
2570  | 0  |     }  | 
2571  |  | 
  | 
2572  | 0  |     for (int i = 0; i < nBandCount && eErr == CE_None; ++i)  | 
2573  | 0  |     { | 
2574  | 0  |         int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;  | 
2575  | 0  |         if (iBand < 1 || iBand > GetRasterCount())  | 
2576  | 0  |         { | 
2577  | 0  |             ReportError(  | 
2578  | 0  |                 CE_Failure, CPLE_IllegalArg,  | 
2579  | 0  |                 "%s: panBandMap[%d] = %d, this band does not exist on dataset.",  | 
2580  | 0  |                 pszCallingFunc, i, iBand);  | 
2581  | 0  |             eErr = CE_Failure;  | 
2582  | 0  |         }  | 
2583  |  | 
  | 
2584  | 0  |         if (eErr == CE_None && GetRasterBand(iBand) == nullptr)  | 
2585  | 0  |         { | 
2586  | 0  |             ReportError(  | 
2587  | 0  |                 CE_Failure, CPLE_IllegalArg,  | 
2588  | 0  |                 "%s: panBandMap[%d]=%d, this band should exist but is NULL!",  | 
2589  | 0  |                 pszCallingFunc, i, iBand);  | 
2590  | 0  |             eErr = CE_Failure;  | 
2591  | 0  |         }  | 
2592  | 0  |     }  | 
2593  |  | 
  | 
2594  | 0  |     return eErr;  | 
2595  | 0  | }  | 
2596  |  |  | 
2597  |  | //! @endcond  | 
2598  |  |  | 
2599  |  | /************************************************************************/  | 
2600  |  | /*                              RasterIO()                              */  | 
2601  |  | /************************************************************************/  | 
2602  |  |  | 
2603  |  | /**  | 
2604  |  |  * \brief Read/write a region of image data from multiple bands.  | 
2605  |  |  *  | 
2606  |  |  * This method allows reading a region of one or more GDALRasterBands from  | 
2607  |  |  * this dataset into a buffer,  or writing data from a buffer into a region  | 
2608  |  |  * of the GDALRasterBands.  It automatically takes care of data type  | 
2609  |  |  * translation if the data type (eBufType) of the buffer is different than  | 
2610  |  |  * that of the GDALRasterBand.  | 
2611  |  |  * The method also takes care of image decimation / replication if the  | 
2612  |  |  * buffer size (nBufXSize x nBufYSize) is different than the size of the  | 
2613  |  |  * region being accessed (nXSize x nYSize).  | 
2614  |  |  *  | 
2615  |  |  * The window of interest expressed by (nXOff, nYOff, nXSize, nYSize) should be  | 
2616  |  |  * fully within the raster space, that is nXOff >= 0, nYOff >= 0,  | 
2617  |  |  * nXOff + nXSize <= GetRasterXSize() and nYOff + nYSize <= GetRasterYSize().  | 
2618  |  |  * If reads larger than the raster space are wished, GDALTranslate() might be used.  | 
2619  |  |  * Or use nLineSpace and a possibly shifted pData value.  | 
2620  |  |  *  | 
2621  |  |  * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or  | 
2622  |  |  * writing from various organization of buffers.  | 
2623  |  |  *  | 
2624  |  |  * Some formats may efficiently implement decimation into a buffer by  | 
2625  |  |  * reading from lower resolution overview images. The logic of the default  | 
2626  |  |  * implementation in the base class GDALRasterBand is the following one. It  | 
2627  |  |  * computes a target_downscaling_factor from the window of interest and buffer  | 
2628  |  |  * size which is min(nXSize/nBufXSize, nYSize/nBufYSize).  | 
2629  |  |  * It then walks through overviews and will select the first one whose  | 
2630  |  |  * downscaling factor is greater than target_downscaling_factor / 1.2.  | 
2631  |  |  *  | 
2632  |  |  * Let's assume we have overviews at downscaling factors 2, 4 and 8.  | 
2633  |  |  * The relationship between target_downscaling_factor and the select overview  | 
2634  |  |  * level is the following one:  | 
2635  |  |  *  | 
2636  |  |  * target_downscaling_factor  | selected_overview  | 
2637  |  |  * -------------------------  | -----------------  | 
2638  |  |  * ]0,       2 / 1.2]         | full resolution band  | 
2639  |  |  * ]2 / 1.2, 4 / 1.2]         | 2x downsampled band  | 
2640  |  |  * ]4 / 1.2, 8 / 1.2]         | 4x downsampled band  | 
2641  |  |  * ]8 / 1.2, infinity[        | 8x downsampled band  | 
2642  |  |  *  | 
2643  |  |  * Note that starting with GDAL 3.9, this 1.2 oversampling factor can be  | 
2644  |  |  * modified by setting the GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD configuration  | 
2645  |  |  * option. Also note that starting with GDAL 3.9, when the resampling algorithm  | 
2646  |  |  * specified in psExtraArg->eResampleAlg is different from GRIORA_NearestNeighbour,  | 
2647  |  |  * this oversampling threshold defaults to 1. Consequently if there are overviews  | 
2648  |  |  * of downscaling factor 2, 4 and 8, and the desired downscaling factor is  | 
2649  |  |  * 7.99, the overview of factor 4 will be selected for a non nearest resampling.  | 
2650  |  |  *  | 
2651  |  |  * For highest performance full resolution data access, read and write  | 
2652  |  |  * on "block boundaries" as returned by GetBlockSize(), or use the  | 
2653  |  |  * ReadBlock() and WriteBlock() methods.  | 
2654  |  |  *  | 
2655  |  |  * This method is the same as the C GDALDatasetRasterIO() or  | 
2656  |  |  * GDALDatasetRasterIOEx() functions.  | 
2657  |  |  *  | 
2658  |  |  * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to  | 
2659  |  |  * write a region of data.  | 
2660  |  |  *  | 
2661  |  |  * @param nXOff The pixel offset to the top left corner of the region  | 
2662  |  |  * of the band to be accessed.  This would be zero to start from the left side.  | 
2663  |  |  *  | 
2664  |  |  * @param nYOff The line offset to the top left corner of the region  | 
2665  |  |  * of the band to be accessed.  This would be zero to start from the top.  | 
2666  |  |  *  | 
2667  |  |  * @param nXSize The width of the region of the band to be accessed in pixels.  | 
2668  |  |  *  | 
2669  |  |  * @param nYSize The height of the region of the band to be accessed in lines.  | 
2670  |  |  *  | 
2671  |  |  * @param pData The buffer into which the data should be read, or from which  | 
2672  |  |  * it should be written.  This buffer must contain at least  | 
2673  |  |  * nBufXSize * nBufYSize * nBandCount words of type eBufType.  It is organized  | 
2674  |  |  * in left to right,top to bottom pixel order.  Spacing is controlled by the  | 
2675  |  |  * nPixelSpace, and nLineSpace parameters.  | 
2676  |  |  * Note that even with eRWFlag==GF_Write, the content of the buffer might be  | 
2677  |  |  * temporarily modified during the execution of this method (and eventually  | 
2678  |  |  * restored back to its original content), so it is not safe to use a buffer  | 
2679  |  |  * stored in a read-only section of the calling program.  | 
2680  |  |  *  | 
2681  |  |  * @param nBufXSize the width of the buffer image into which the desired region  | 
2682  |  |  * is to be read, or from which it is to be written.  | 
2683  |  |  *  | 
2684  |  |  * @param nBufYSize the height of the buffer image into which the desired  | 
2685  |  |  * region is to be read, or from which it is to be written.  | 
2686  |  |  *  | 
2687  |  |  * @param eBufType the type of the pixel values in the pData data buffer. The  | 
2688  |  |  * pixel values will automatically be translated to/from the GDALRasterBand  | 
2689  |  |  * data type as needed. Most driver implementations will use GDALCopyWords64()  | 
2690  |  |  * to perform data type translation.  | 
2691  |  |  *  | 
2692  |  |  * @param nBandCount the number of bands being read or written.  | 
2693  |  |  *  | 
2694  |  |  * @param panBandMap the list of nBandCount band numbers being read/written.  | 
2695  |  |  * Note band numbers are 1 based. This may be NULL to select the first  | 
2696  |  |  * nBandCount bands. (Note: before GDAL 3.10, argument type was "int*", and  | 
2697  |  |  * not "const int*")  | 
2698  |  |  *  | 
2699  |  |  * @param nPixelSpace The byte offset from the start of one pixel value in  | 
2700  |  |  * pData to the start of the next pixel value within a scanline. If defaulted  | 
2701  |  |  * (0) the size of the datatype eBufType is used.  | 
2702  |  |  *  | 
2703  |  |  * @param nLineSpace The byte offset from the start of one scanline in  | 
2704  |  |  * pData to the start of the next. If defaulted (0) the size of the datatype  | 
2705  |  |  * eBufType * nBufXSize is used.  | 
2706  |  |  *  | 
2707  |  |  * @param nBandSpace the byte offset from the start of one bands data to the  | 
2708  |  |  * start of the next. If defaulted (0) the value will be  | 
2709  |  |  * nLineSpace * nBufYSize implying band sequential organization  | 
2710  |  |  * of the data buffer.  | 
2711  |  |  *  | 
2712  |  |  * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg  | 
2713  |  |  * structure with additional arguments to specify resampling and progress  | 
2714  |  |  * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING  | 
2715  |  |  * configuration option can also be defined to override the default resampling  | 
2716  |  |  * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.  | 
2717  |  |  *  | 
2718  |  |  * @return CE_Failure if the access fails, otherwise CE_None.  | 
2719  |  |  */  | 
2720  |  |  | 
2721  |  | CPLErr GDALDataset::RasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,  | 
2722  |  |                              int nXSize, int nYSize, void *pData, int nBufXSize,  | 
2723  |  |                              int nBufYSize, GDALDataType eBufType,  | 
2724  |  |                              int nBandCount, const int *panBandMap,  | 
2725  |  |                              GSpacing nPixelSpace, GSpacing nLineSpace,  | 
2726  |  |                              GSpacing nBandSpace,  | 
2727  |  |                              GDALRasterIOExtraArg *psExtraArg)  | 
2728  |  |  | 
2729  | 0  | { | 
2730  | 0  |     GDALRasterIOExtraArg sExtraArg;  | 
2731  | 0  |     if (psExtraArg == nullptr)  | 
2732  | 0  |     { | 
2733  | 0  |         INIT_RASTERIO_EXTRA_ARG(sExtraArg);  | 
2734  |  |  | 
2735  |  |         // 4 below inits are not strictly needed but make Coverity Scan  | 
2736  |  |         // happy  | 
2737  | 0  |         sExtraArg.dfXOff = nXOff;  | 
2738  | 0  |         sExtraArg.dfYOff = nYOff;  | 
2739  | 0  |         sExtraArg.dfXSize = nXSize;  | 
2740  | 0  |         sExtraArg.dfYSize = nYSize;  | 
2741  |  | 
  | 
2742  | 0  |         psExtraArg = &sExtraArg;  | 
2743  | 0  |     }  | 
2744  | 0  |     else if (CPL_UNLIKELY(psExtraArg->nVersion >  | 
2745  | 0  |                           RASTERIO_EXTRA_ARG_CURRENT_VERSION))  | 
2746  | 0  |     { | 
2747  | 0  |         ReportError(CE_Failure, CPLE_AppDefined,  | 
2748  | 0  |                     "Unhandled version of GDALRasterIOExtraArg");  | 
2749  | 0  |         return CE_Failure;  | 
2750  | 0  |     }  | 
2751  |  |  | 
2752  | 0  |     GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,  | 
2753  | 0  |                                        nBufYSize);  | 
2754  |  | 
  | 
2755  | 0  |     if (CPL_UNLIKELY(nullptr == pData))  | 
2756  | 0  |     { | 
2757  | 0  |         ReportError(CE_Failure, CPLE_AppDefined,  | 
2758  | 0  |                     "The buffer into which the data should be read is null");  | 
2759  | 0  |         return CE_Failure;  | 
2760  | 0  |     }  | 
2761  |  |  | 
2762  |  |     /* -------------------------------------------------------------------- */  | 
2763  |  |     /*      Do some validation of parameters.                               */  | 
2764  |  |     /* -------------------------------------------------------------------- */  | 
2765  |  |  | 
2766  | 0  |     if (CPL_UNLIKELY(eRWFlag != GF_Read && eRWFlag != GF_Write))  | 
2767  | 0  |     { | 
2768  | 0  |         ReportError(  | 
2769  | 0  |             CE_Failure, CPLE_IllegalArg,  | 
2770  | 0  |             "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",  | 
2771  | 0  |             eRWFlag);  | 
2772  | 0  |         return CE_Failure;  | 
2773  | 0  |     }  | 
2774  |  |  | 
2775  | 0  |     if (eRWFlag == GF_Write)  | 
2776  | 0  |     { | 
2777  | 0  |         if (CPL_UNLIKELY(eAccess != GA_Update))  | 
2778  | 0  |         { | 
2779  | 0  |             ReportError(CE_Failure, CPLE_AppDefined,  | 
2780  | 0  |                         "Write operation not permitted on dataset opened "  | 
2781  | 0  |                         "in read-only mode");  | 
2782  | 0  |             return CE_Failure;  | 
2783  | 0  |         }  | 
2784  | 0  |     }  | 
2785  |  |  | 
2786  | 0  |     int bStopProcessing = FALSE;  | 
2787  | 0  |     CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(  | 
2788  | 0  |         "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,  | 
2789  | 0  |         nBufYSize, nBandCount, panBandMap);  | 
2790  | 0  |     if (eErr != CE_None || bStopProcessing)  | 
2791  | 0  |         return eErr;  | 
2792  | 0  |     if (CPL_UNLIKELY(eBufType == GDT_Unknown || eBufType == GDT_TypeCount))  | 
2793  | 0  |     { | 
2794  | 0  |         ReportError(CE_Failure, CPLE_AppDefined,  | 
2795  | 0  |                     "Illegal GDT_Unknown/GDT_TypeCount argument");  | 
2796  | 0  |         return CE_Failure;  | 
2797  | 0  |     }  | 
2798  |  |  | 
2799  |  |     /* -------------------------------------------------------------------- */  | 
2800  |  |     /*      If pixel and line spacing are defaulted assign reasonable      */  | 
2801  |  |     /*      value assuming a packed buffer.                                 */  | 
2802  |  |     /* -------------------------------------------------------------------- */  | 
2803  | 0  |     if (nPixelSpace == 0)  | 
2804  | 0  |         nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);  | 
2805  |  | 
  | 
2806  | 0  |     if (nLineSpace == 0)  | 
2807  | 0  |     { | 
2808  | 0  |         nLineSpace = nPixelSpace * nBufXSize;  | 
2809  | 0  |     }  | 
2810  |  | 
  | 
2811  | 0  |     if (nBandSpace == 0 && nBandCount > 1)  | 
2812  | 0  |     { | 
2813  | 0  |         nBandSpace = nLineSpace * nBufYSize;  | 
2814  | 0  |     }  | 
2815  |  | 
  | 
2816  | 0  |     if (panBandMap == nullptr)  | 
2817  | 0  |     { | 
2818  | 0  |         if (!m_poPrivate)  | 
2819  | 0  |             return CE_Failure;  | 
2820  | 0  |         CPLAssert(static_cast<int>(m_poPrivate->m_anBandMap.size()) == nBands);  | 
2821  | 0  |         panBandMap = m_poPrivate->m_anBandMap.data();  | 
2822  | 0  |     }  | 
2823  |  |  | 
2824  | 0  |     int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);  | 
2825  |  |  | 
2826  |  |     /* -------------------------------------------------------------------- */  | 
2827  |  |     /*      We are being forced to use cached IO instead of a driver        */  | 
2828  |  |     /*      specific implementation.                                        */  | 
2829  |  |     /* -------------------------------------------------------------------- */  | 
2830  | 0  |     if (bForceCachedIO)  | 
2831  | 0  |     { | 
2832  | 0  |         eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,  | 
2833  | 0  |                                   nBufXSize, nBufYSize, eBufType, nBandCount,  | 
2834  | 0  |                                   panBandMap, nPixelSpace, nLineSpace,  | 
2835  | 0  |                                   nBandSpace, psExtraArg);  | 
2836  | 0  |     }  | 
2837  |  |  | 
2838  |  |     /* -------------------------------------------------------------------- */  | 
2839  |  |     /*      Call the format specific function.                              */  | 
2840  |  |     /* -------------------------------------------------------------------- */  | 
2841  | 0  |     else  | 
2842  | 0  |     { | 
2843  | 0  |         eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,  | 
2844  | 0  |                          nBufXSize, nBufYSize, eBufType, nBandCount,  | 
2845  |  |                          // TODO: remove this const_cast once IRasterIO()  | 
2846  |  |                          // takes a const int*  | 
2847  | 0  |                          const_cast<int *>(panBandMap), nPixelSpace, nLineSpace,  | 
2848  | 0  |                          nBandSpace, psExtraArg);  | 
2849  | 0  |     }  | 
2850  |  | 
  | 
2851  | 0  |     if (bCallLeaveReadWrite)  | 
2852  | 0  |         LeaveReadWrite();  | 
2853  |  | 
  | 
2854  | 0  |     return eErr;  | 
2855  | 0  | }  | 
2856  |  |  | 
2857  |  | /************************************************************************/  | 
2858  |  | /*                        GDALDatasetRasterIO()                         */  | 
2859  |  | /************************************************************************/  | 
2860  |  |  | 
2861  |  | /**  | 
2862  |  |  * \brief Read/write a region of image data from multiple bands.  | 
2863  |  |  *  | 
2864  |  |  * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling  | 
2865  |  |  * resolution, progress callback, etc. are needed)  | 
2866  |  |  *  | 
2867  |  |  * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"  | 
2868  |  |  *  | 
2869  |  |  * @see GDALDataset::RasterIO()  | 
2870  |  |  */  | 
2871  |  |  | 
2872  |  | CPLErr CPL_STDCALL GDALDatasetRasterIO(GDALDatasetH hDS, GDALRWFlag eRWFlag,  | 
2873  |  |                                        int nXOff, int nYOff, int nXSize,  | 
2874  |  |                                        int nYSize, void *pData, int nBufXSize,  | 
2875  |  |                                        int nBufYSize, GDALDataType eBufType,  | 
2876  |  |                                        int nBandCount, const int *panBandMap,  | 
2877  |  |                                        int nPixelSpace, int nLineSpace,  | 
2878  |  |                                        int nBandSpace)  | 
2879  |  |  | 
2880  | 0  | { | 
2881  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);  | 
2882  |  |  | 
2883  | 0  |     GDALDataset *poDS = GDALDataset::FromHandle(hDS);  | 
2884  |  | 
  | 
2885  | 0  |     return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,  | 
2886  | 0  |                           nBufXSize, nBufYSize, eBufType, nBandCount,  | 
2887  | 0  |                           panBandMap, nPixelSpace, nLineSpace, nBandSpace,  | 
2888  | 0  |                           nullptr);  | 
2889  | 0  | }  | 
2890  |  |  | 
2891  |  | /************************************************************************/  | 
2892  |  | /*                       GDALDatasetRasterIOEx()                        */  | 
2893  |  | /************************************************************************/  | 
2894  |  |  | 
2895  |  | /**  | 
2896  |  |  * \brief Read/write a region of image data from multiple bands.  | 
2897  |  |  *  | 
2898  |  |  * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"  | 
2899  |  |  *  | 
2900  |  |  * @see GDALDataset::RasterIO()  | 
2901  |  |  * @since GDAL 2.0  | 
2902  |  |  */  | 
2903  |  |  | 
2904  |  | CPLErr CPL_STDCALL GDALDatasetRasterIOEx(  | 
2905  |  |     GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,  | 
2906  |  |     int nYSize, void *pData, int nBufXSize, int nBufYSize,  | 
2907  |  |     GDALDataType eBufType, int nBandCount, const int *panBandMap,  | 
2908  |  |     GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,  | 
2909  |  |     GDALRasterIOExtraArg *psExtraArg)  | 
2910  |  |  | 
2911  | 0  | { | 
2912  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);  | 
2913  |  |  | 
2914  | 0  |     GDALDataset *poDS = GDALDataset::FromHandle(hDS);  | 
2915  |  | 
  | 
2916  | 0  |     return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,  | 
2917  | 0  |                           nBufXSize, nBufYSize, eBufType, nBandCount,  | 
2918  | 0  |                           panBandMap, nPixelSpace, nLineSpace, nBandSpace,  | 
2919  | 0  |                           psExtraArg);  | 
2920  | 0  | }  | 
2921  |  |  | 
2922  |  | /************************************************************************/  | 
2923  |  | /*                          GetOpenDatasets()                           */  | 
2924  |  | /************************************************************************/  | 
2925  |  |  | 
2926  |  | /**  | 
2927  |  |  * \brief Fetch all open GDAL dataset handles.  | 
2928  |  |  *  | 
2929  |  |  * This method is the same as the C function GDALGetOpenDatasets().  | 
2930  |  |  *  | 
2931  |  |  * NOTE: This method is not thread safe.  The returned list may change  | 
2932  |  |  * at any time and it should not be freed.  | 
2933  |  |  *  | 
2934  |  |  * @param pnCount integer into which to place the count of dataset pointers  | 
2935  |  |  * being returned.  | 
2936  |  |  *  | 
2937  |  |  * @return a pointer to an array of dataset handles.  | 
2938  |  |  */  | 
2939  |  |  | 
2940  |  | GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)  | 
2941  |  |  | 
2942  | 0  | { | 
2943  | 0  |     CPLMutexHolderD(&hDLMutex);  | 
2944  |  | 
  | 
2945  | 0  |     if (poAllDatasetMap == nullptr)  | 
2946  | 0  |     { | 
2947  | 0  |         *pnCount = 0;  | 
2948  | 0  |         return nullptr;  | 
2949  | 0  |     }  | 
2950  |  |  | 
2951  | 0  |     *pnCount = static_cast<int>(poAllDatasetMap->size());  | 
2952  | 0  |     ppDatasets = static_cast<GDALDataset **>(  | 
2953  | 0  |         CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));  | 
2954  | 0  |     std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();  | 
2955  | 0  |     for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)  | 
2956  | 0  |         ppDatasets[i] = oIter->first;  | 
2957  | 0  |     return ppDatasets;  | 
2958  | 0  | }  | 
2959  |  |  | 
2960  |  | /************************************************************************/  | 
2961  |  | /*                        GDALGetOpenDatasets()                         */  | 
2962  |  | /************************************************************************/  | 
2963  |  |  | 
2964  |  | /**  | 
2965  |  |  * \brief Fetch all open GDAL dataset handles.  | 
2966  |  |  *  | 
2967  |  |  * @see GDALDataset::GetOpenDatasets()  | 
2968  |  |  */  | 
2969  |  |  | 
2970  |  | void CPL_STDCALL GDALGetOpenDatasets(GDALDatasetH **ppahDSList, int *pnCount)  | 
2971  |  |  | 
2972  | 0  | { | 
2973  | 0  |     VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");  | 
2974  | 0  |     VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");  | 
2975  |  |  | 
2976  | 0  |     *ppahDSList =  | 
2977  | 0  |         reinterpret_cast<GDALDatasetH *>(GDALDataset::GetOpenDatasets(pnCount));  | 
2978  | 0  | }  | 
2979  |  |  | 
2980  |  | /************************************************************************/  | 
2981  |  | /*                        GDALCleanOpenDatasetsList()                   */  | 
2982  |  | /************************************************************************/  | 
2983  |  |  | 
2984  |  | // Useful when called from the child of a fork(), to avoid closing  | 
2985  |  | // the datasets of the parent at the child termination.  | 
2986  |  | void GDALNullifyOpenDatasetsList()  | 
2987  | 0  | { | 
2988  | 0  |     poAllDatasetMap = nullptr;  | 
2989  | 0  |     phSharedDatasetSet = nullptr;  | 
2990  | 0  |     ppDatasets = nullptr;  | 
2991  | 0  |     hDLMutex = nullptr;  | 
2992  | 0  | }  | 
2993  |  |  | 
2994  |  | /************************************************************************/  | 
2995  |  | /*                             GDALGetAccess()                          */  | 
2996  |  | /************************************************************************/  | 
2997  |  |  | 
2998  |  | /**  | 
2999  |  |  * \brief Return access flag  | 
3000  |  |  *  | 
3001  |  |  * @see GDALDataset::GetAccess()  | 
3002  |  |  */  | 
3003  |  |  | 
3004  |  | int CPL_STDCALL GDALGetAccess(GDALDatasetH hDS)  | 
3005  | 0  | { | 
3006  | 0  |     VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);  | 
3007  |  |  | 
3008  | 0  |     return GDALDataset::FromHandle(hDS)->GetAccess();  | 
3009  | 0  | }  | 
3010  |  |  | 
3011  |  | /************************************************************************/  | 
3012  |  | /*                             AdviseRead()                             */  | 
3013  |  | /************************************************************************/  | 
3014  |  |  | 
3015  |  | /**  | 
3016  |  |  * \brief Advise driver of upcoming read requests.  | 
3017  |  |  *  | 
3018  |  |  * Some GDAL drivers operate more efficiently if they know in advance what  | 
3019  |  |  * set of upcoming read requests will be made.  The AdviseRead() method allows  | 
3020  |  |  * an application to notify the driver of the region and bands of interest,  | 
3021  |  |  * and at what resolution the region will be read.  | 
3022  |  |  *  | 
3023  |  |  * Many drivers just ignore the AdviseRead() call, but it can dramatically  | 
3024  |  |  * accelerate access via some drivers.  | 
3025  |  |  *  | 
3026  |  |  * Depending on call paths, drivers might receive several calls to  | 
3027  |  |  * AdviseRead() with the same parameters.  | 
3028  |  |  *  | 
3029  |  |  * @param nXOff The pixel offset to the top left corner of the region  | 
3030  |  |  * of the band to be accessed.  This would be zero to start from the left side.  | 
3031  |  |  *  | 
3032  |  |  * @param nYOff The line offset to the top left corner of the region  | 
3033  |  |  * of the band to be accessed.  This would be zero to start from the top.  | 
3034  |  |  *  | 
3035  |  |  * @param nXSize The width of the region of the band to be accessed in pixels.  | 
3036  |  |  *  | 
3037  |  |  * @param nYSize The height of the region of the band to be accessed in lines.  | 
3038  |  |  *  | 
3039  |  |  * @param nBufXSize the width of the buffer image into which the desired region  | 
3040  |  |  * is to be read, or from which it is to be written.  | 
3041  |  |  *  | 
3042  |  |  * @param nBufYSize the height of the buffer image into which the desired  | 
3043  |  |  * region is to be read, or from which it is to be written.  | 
3044  |  |  *  | 
3045  |  |  * @param eBufType the type of the pixel values in the pData data buffer.  The  | 
3046  |  |  * pixel values will automatically be translated to/from the GDALRasterBand  | 
3047  |  |  * data type as needed.  | 
3048  |  |  *  | 
3049  |  |  * @param nBandCount the number of bands being read or written.  | 
3050  |  |  *  | 
3051  |  |  * @param panBandMap the list of nBandCount band numbers being read/written.  | 
3052  |  |  * Note band numbers are 1 based.   This may be NULL to select the first  | 
3053  |  |  * nBandCount bands.  | 
3054  |  |  *  | 
3055  |  |  * @param papszOptions a list of name=value strings with special control  | 
3056  |  |  * options.  Normally this is NULL.  | 
3057  |  |  *  | 
3058  |  |  * @return CE_Failure if the request is invalid and CE_None if it works or  | 
3059  |  |  * is ignored.  | 
3060  |  |  */  | 
3061  |  |  | 
3062  |  | CPLErr GDALDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,  | 
3063  |  |                                int nBufXSize, int nBufYSize,  | 
3064  |  |                                GDALDataType eBufType, int nBandCount,  | 
3065  |  |                                int *panBandMap, char **papszOptions)  | 
3066  |  |  | 
3067  | 0  | { | 
3068  |  |     /* -------------------------------------------------------------------- */  | 
3069  |  |     /*      Do some validation of parameters.                               */  | 
3070  |  |     /* -------------------------------------------------------------------- */  | 
3071  | 0  |     int bStopProcessing = FALSE;  | 
3072  | 0  |     CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(  | 
3073  | 0  |         "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,  | 
3074  | 0  |         nBufXSize, nBufYSize, nBandCount, panBandMap);  | 
3075  | 0  |     if (eErr != CE_None || bStopProcessing)  | 
3076  | 0  |         return eErr;  | 
3077  |  |  | 
3078  | 0  |     for (int iBand = 0; iBand < nBandCount; ++iBand)  | 
3079  | 0  |     { | 
3080  | 0  |         GDALRasterBand *poBand = nullptr;  | 
3081  |  | 
  | 
3082  | 0  |         if (panBandMap == nullptr)  | 
3083  | 0  |             poBand = GetRasterBand(iBand + 1);  | 
3084  | 0  |         else  | 
3085  | 0  |             poBand = GetRasterBand(panBandMap[iBand]);  | 
3086  |  | 
  | 
3087  | 0  |         if (poBand == nullptr)  | 
3088  | 0  |             return CE_Failure;  | 
3089  |  |  | 
3090  | 0  |         eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,  | 
3091  | 0  |                                   nBufYSize, eBufType, papszOptions);  | 
3092  |  | 
  | 
3093  | 0  |         if (eErr != CE_None)  | 
3094  | 0  |             return eErr;  | 
3095  | 0  |     }  | 
3096  |  |  | 
3097  | 0  |     return CE_None;  | 
3098  | 0  | }  | 
3099  |  |  | 
3100  |  | /************************************************************************/  | 
3101  |  | /*                       GDALDatasetAdviseRead()                        */  | 
3102  |  | /************************************************************************/  | 
3103  |  |  | 
3104  |  | /**  | 
3105  |  |  * \brief Advise driver of upcoming read requests.  | 
3106  |  |  *  | 
3107  |  |  * @see GDALDataset::AdviseRead()  | 
3108  |  |  */  | 
3109  |  | CPLErr CPL_STDCALL GDALDatasetAdviseRead(GDALDatasetH hDS, int nXOff, int nYOff,  | 
3110  |  |                                          int nXSize, int nYSize, int nBufXSize,  | 
3111  |  |                                          int nBufYSize, GDALDataType eDT,  | 
3112  |  |                                          int nBandCount, int *panBandMap,  | 
3113  |  |                                          CSLConstList papszOptions)  | 
3114  |  |  | 
3115  | 0  | { | 
3116  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);  | 
3117  |  |  | 
3118  | 0  |     return GDALDataset::FromHandle(hDS)->AdviseRead(  | 
3119  | 0  |         nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount,  | 
3120  | 0  |         panBandMap, const_cast<char **>(papszOptions));  | 
3121  | 0  | }  | 
3122  |  |  | 
3123  |  | /************************************************************************/  | 
3124  |  | /*                         GDALAntiRecursionStruct                      */  | 
3125  |  | /************************************************************************/  | 
3126  |  |  | 
3127  |  | // Prevent infinite recursion.  | 
3128  |  | struct GDALAntiRecursionStruct  | 
3129  |  | { | 
3130  |  |     struct DatasetContext  | 
3131  |  |     { | 
3132  |  |         std::string osFilename;  | 
3133  |  |         int nOpenFlags;  | 
3134  |  |         std::string osAllowedDrivers;  | 
3135  |  |  | 
3136  |  |         DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,  | 
3137  |  |                        const std::string &osAllowedDriversIn)  | 
3138  | 0  |             : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),  | 
3139  | 0  |               osAllowedDrivers(osAllowedDriversIn)  | 
3140  | 0  |         { | 
3141  | 0  |         }  | 
3142  |  |     };  | 
3143  |  |  | 
3144  |  |     struct DatasetContextCompare  | 
3145  |  |     { | 
3146  |  |         bool operator()(const DatasetContext &lhs,  | 
3147  |  |                         const DatasetContext &rhs) const  | 
3148  | 0  |         { | 
3149  | 0  |             return lhs.osFilename < rhs.osFilename ||  | 
3150  | 0  |                    (lhs.osFilename == rhs.osFilename &&  | 
3151  | 0  |                     (lhs.nOpenFlags < rhs.nOpenFlags ||  | 
3152  | 0  |                      (lhs.nOpenFlags == rhs.nOpenFlags &&  | 
3153  | 0  |                       lhs.osAllowedDrivers < rhs.osAllowedDrivers)));  | 
3154  | 0  |         }  | 
3155  |  |     };  | 
3156  |  |  | 
3157  |  |     std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{}; | 
3158  |  |     int nRecLevel = 0;  | 
3159  |  |     std::map<std::string, int> m_oMapDepth{}; | 
3160  |  | };  | 
3161  |  |  | 
3162  |  | #ifdef _WIN32  | 
3163  |  | // Currently thread_local and C++ objects don't work well with DLL on Windows  | 
3164  |  | static void FreeAntiRecursionOpen(void *pData)  | 
3165  |  | { | 
3166  |  |     delete static_cast<GDALAntiRecursionStruct *>(pData);  | 
3167  |  | }  | 
3168  |  |  | 
3169  |  | static GDALAntiRecursionStruct &GetAntiRecursionOpen()  | 
3170  |  | { | 
3171  |  |     static GDALAntiRecursionStruct dummy;  | 
3172  |  |     int bMemoryErrorOccurred = false;  | 
3173  |  |     void *pData =  | 
3174  |  |         CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);  | 
3175  |  |     if (bMemoryErrorOccurred)  | 
3176  |  |     { | 
3177  |  |         return dummy;  | 
3178  |  |     }  | 
3179  |  |     if (pData == nullptr)  | 
3180  |  |     { | 
3181  |  |         auto pAntiRecursion = new GDALAntiRecursionStruct();  | 
3182  |  |         CPLSetTLSWithFreeFuncEx(CTLS_GDALOPEN_ANTIRECURSION, pAntiRecursion,  | 
3183  |  |                                 FreeAntiRecursionOpen, &bMemoryErrorOccurred);  | 
3184  |  |         if (bMemoryErrorOccurred)  | 
3185  |  |         { | 
3186  |  |             delete pAntiRecursion;  | 
3187  |  |             return dummy;  | 
3188  |  |         }  | 
3189  |  |         return *pAntiRecursion;  | 
3190  |  |     }  | 
3191  |  |     return *static_cast<GDALAntiRecursionStruct *>(pData);  | 
3192  |  | }  | 
3193  |  | #else  | 
3194  |  | static thread_local GDALAntiRecursionStruct g_tls_antiRecursion;  | 
3195  |  |  | 
3196  |  | static GDALAntiRecursionStruct &GetAntiRecursionOpen()  | 
3197  | 0  | { | 
3198  | 0  |     return g_tls_antiRecursion;  | 
3199  | 0  | }  | 
3200  |  | #endif  | 
3201  |  |  | 
3202  |  | //! @cond Doxygen_Suppress  | 
3203  |  | GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)  | 
3204  | 0  |     : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),  | 
3205  | 0  |       m_osIdentifier(osIdentifier),  | 
3206  | 0  |       m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])  | 
3207  | 0  | { | 
3208  | 0  |     CPLAssert(!osIdentifier.empty());  | 
3209  | 0  | }  | 
3210  |  |  | 
3211  |  | GDALAntiRecursionGuard::GDALAntiRecursionGuard(  | 
3212  |  |     const GDALAntiRecursionGuard &other, const std::string &osIdentifier)  | 
3213  | 0  |     : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),  | 
3214  | 0  |       m_osIdentifier(osIdentifier.empty()  | 
3215  | 0  |                          ? osIdentifier  | 
3216  | 0  |                          : other.m_osIdentifier + osIdentifier),  | 
3217  | 0  |       m_nDepth(m_osIdentifier.empty()  | 
3218  | 0  |                    ? 0  | 
3219  | 0  |                    : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])  | 
3220  | 0  | { | 
3221  | 0  | }  | 
3222  |  |  | 
3223  |  | GDALAntiRecursionGuard::~GDALAntiRecursionGuard()  | 
3224  | 0  | { | 
3225  | 0  |     if (!m_osIdentifier.empty())  | 
3226  | 0  |     { | 
3227  | 0  |         --m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier];  | 
3228  | 0  |     }  | 
3229  | 0  | }  | 
3230  |  |  | 
3231  |  | //! @endcond  | 
3232  |  |  | 
3233  |  | /************************************************************************/  | 
3234  |  | /*                            GetFileList()                             */  | 
3235  |  | /************************************************************************/  | 
3236  |  |  | 
3237  |  | /**  | 
3238  |  |  * \brief Fetch files forming dataset.  | 
3239  |  |  *  | 
3240  |  |  * Returns a list of files believed to be part of this dataset.  If it returns  | 
3241  |  |  * an empty list of files it means there is believed to be no local file  | 
3242  |  |  * system files associated with the dataset (for instance a virtual dataset).  | 
3243  |  |  * The returned file list is owned by the caller and should be deallocated  | 
3244  |  |  * with CSLDestroy().  | 
3245  |  |  *  | 
3246  |  |  * The returned filenames will normally be relative or absolute paths  | 
3247  |  |  * depending on the path used to originally open the dataset.  The strings  | 
3248  |  |  * will be UTF-8 encoded.  | 
3249  |  |  *  | 
3250  |  |  * This method is the same as the C GDALGetFileList() function.  | 
3251  |  |  *  | 
3252  |  |  * @return NULL or a NULL terminated array of file names.  | 
3253  |  |  */  | 
3254  |  |  | 
3255  |  | char **GDALDataset::GetFileList()  | 
3256  |  |  | 
3257  | 0  | { | 
3258  | 0  |     CPLString osMainFilename = GetDescription();  | 
3259  | 0  |     VSIStatBufL sStat;  | 
3260  |  | 
  | 
3261  | 0  |     GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();  | 
3262  | 0  |     GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,  | 
3263  | 0  |                                                         std::string());  | 
3264  | 0  |     auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;  | 
3265  | 0  |     if (cpl::contains(aosDatasetList, datasetCtxt))  | 
3266  | 0  |         return nullptr;  | 
3267  |  |  | 
3268  |  |     /* -------------------------------------------------------------------- */  | 
3269  |  |     /*      Is the main filename even a real filesystem object?             */  | 
3270  |  |     /* -------------------------------------------------------------------- */  | 
3271  | 0  |     int bMainFileReal =  | 
3272  | 0  |         VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;  | 
3273  |  |  | 
3274  |  |     /* -------------------------------------------------------------------- */  | 
3275  |  |     /*      Form new list.                                                  */  | 
3276  |  |     /* -------------------------------------------------------------------- */  | 
3277  | 0  |     char **papszList = nullptr;  | 
3278  |  | 
  | 
3279  | 0  |     if (bMainFileReal)  | 
3280  | 0  |         papszList = CSLAddString(papszList, osMainFilename);  | 
3281  |  | 
  | 
3282  | 0  |     if (sAntiRecursion.nRecLevel == 100)  | 
3283  | 0  |     { | 
3284  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
3285  | 0  |                  "GetFileList() called with too many recursion levels");  | 
3286  | 0  |         return papszList;  | 
3287  | 0  |     }  | 
3288  | 0  |     ++sAntiRecursion.nRecLevel;  | 
3289  |  |  | 
3290  |  |     /* -------------------------------------------------------------------- */  | 
3291  |  |     /*      Do we have a known overview file?                               */  | 
3292  |  |     /* -------------------------------------------------------------------- */  | 
3293  | 0  |     if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)  | 
3294  | 0  |     { | 
3295  | 0  |         auto iter = aosDatasetList.insert(datasetCtxt).first;  | 
3296  | 0  |         char **papszOvrList = oOvManager.poODS->GetFileList();  | 
3297  | 0  |         papszList = CSLInsertStrings(papszList, -1, papszOvrList);  | 
3298  | 0  |         CSLDestroy(papszOvrList);  | 
3299  | 0  |         aosDatasetList.erase(iter);  | 
3300  | 0  |     }  | 
3301  |  |  | 
3302  |  |     /* -------------------------------------------------------------------- */  | 
3303  |  |     /*      Do we have a known mask file?                                   */  | 
3304  |  |     /* -------------------------------------------------------------------- */  | 
3305  | 0  |     if (oOvManager.HaveMaskFile())  | 
3306  | 0  |     { | 
3307  | 0  |         auto iter = aosDatasetList.insert(std::move(datasetCtxt)).first;  | 
3308  | 0  |         for (const char *pszFile :  | 
3309  | 0  |              CPLStringList(oOvManager.poMaskDS->GetFileList()))  | 
3310  | 0  |         { | 
3311  | 0  |             if (CSLFindString(papszList, pszFile) < 0)  | 
3312  | 0  |                 papszList = CSLAddString(papszList, pszFile);  | 
3313  | 0  |         }  | 
3314  | 0  |         aosDatasetList.erase(iter);  | 
3315  | 0  |     }  | 
3316  |  | 
  | 
3317  | 0  |     --sAntiRecursion.nRecLevel;  | 
3318  |  | 
  | 
3319  | 0  |     return papszList;  | 
3320  | 0  | }  | 
3321  |  |  | 
3322  |  | /************************************************************************/  | 
3323  |  | /*                          GDALGetFileList()                           */  | 
3324  |  | /************************************************************************/  | 
3325  |  |  | 
3326  |  | /**  | 
3327  |  |  * \brief Fetch files forming dataset.  | 
3328  |  |  *  | 
3329  |  |  * @see GDALDataset::GetFileList()  | 
3330  |  |  */  | 
3331  |  |  | 
3332  |  | char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)  | 
3333  |  |  | 
3334  | 0  | { | 
3335  | 0  |     VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);  | 
3336  |  |  | 
3337  | 0  |     return GDALDataset::FromHandle(hDS)->GetFileList();  | 
3338  | 0  | }  | 
3339  |  |  | 
3340  |  | /************************************************************************/  | 
3341  |  | /*                           CreateMaskBand()                           */  | 
3342  |  | /************************************************************************/  | 
3343  |  |  | 
3344  |  | /**  | 
3345  |  |  * \brief Adds a mask band to the dataset  | 
3346  |  |  *  | 
3347  |  |  * The default implementation of the CreateMaskBand() method is implemented  | 
3348  |  |  * based on similar rules to the .ovr handling implemented using the  | 
3349  |  |  * GDALDefaultOverviews object. A TIFF file with the extension .msk will  | 
3350  |  |  * be created with the same basename as the original file, and it will have  | 
3351  |  |  * one band.  | 
3352  |  |  * The mask images will be deflate compressed tiled images with the same  | 
3353  |  |  * block size as the original image if possible.  | 
3354  |  |  * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset  | 
3355  |  |  * level, where xx matches the band number of a band of the main dataset. The  | 
3356  |  |  * value of those items will be the one of the nFlagsIn parameter.  | 
3357  |  |  *  | 
3358  |  |  * Note that if you got a mask band with a previous call to GetMaskBand(), it  | 
3359  |  |  * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()  | 
3360  |  |  * again.  | 
3361  |  |  *  | 
3362  |  |  * @since GDAL 1.5.0  | 
3363  |  |  *  | 
3364  |  |  * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.  | 
3365  |  |  *                 GMF_PER_DATASET will be always set, even if not explicitly  | 
3366  |  |  *                 specified.  | 
3367  |  |  * @return CE_None on success or CE_Failure on an error.  | 
3368  |  |  *  | 
3369  |  |  * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html  | 
3370  |  |  * @see GDALRasterBand::CreateMaskBand()  | 
3371  |  |  *  | 
3372  |  |  */  | 
3373  |  | CPLErr GDALDataset::CreateMaskBand(int nFlagsIn)  | 
3374  |  |  | 
3375  | 0  | { | 
3376  | 0  |     if (oOvManager.IsInitialized())  | 
3377  | 0  |     { | 
3378  | 0  |         CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);  | 
3379  | 0  |         if (eErr != CE_None)  | 
3380  | 0  |             return eErr;  | 
3381  |  |  | 
3382  |  |         // Invalidate existing raster band masks.  | 
3383  | 0  |         for (int i = 0; i < nBands; ++i)  | 
3384  | 0  |         { | 
3385  | 0  |             GDALRasterBand *poBand = papoBands[i];  | 
3386  | 0  |             poBand->poMask.reset();  | 
3387  | 0  |         }  | 
3388  |  | 
  | 
3389  | 0  |         return CE_None;  | 
3390  | 0  |     }  | 
3391  |  |  | 
3392  | 0  |     ReportError(CE_Failure, CPLE_NotSupported,  | 
3393  | 0  |                 "CreateMaskBand() not supported for this dataset.");  | 
3394  |  | 
  | 
3395  | 0  |     return CE_Failure;  | 
3396  | 0  | }  | 
3397  |  |  | 
3398  |  | /************************************************************************/  | 
3399  |  | /*                     GDALCreateDatasetMaskBand()                      */  | 
3400  |  | /************************************************************************/  | 
3401  |  |  | 
3402  |  | /**  | 
3403  |  |  * \brief Adds a mask band to the dataset  | 
3404  |  |  * @see GDALDataset::CreateMaskBand()  | 
3405  |  |  */  | 
3406  |  | CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)  | 
3407  |  |  | 
3408  | 0  | { | 
3409  | 0  |     VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);  | 
3410  |  |  | 
3411  | 0  |     return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);  | 
3412  | 0  | }  | 
3413  |  |  | 
3414  |  | /************************************************************************/  | 
3415  |  | /*                              GDALOpen()                              */  | 
3416  |  | /************************************************************************/  | 
3417  |  |  | 
3418  |  | /**  | 
3419  |  |  * \brief Open a raster file as a GDALDataset.  | 
3420  |  |  *  | 
3421  |  |  * This function will try to open the passed file, or virtual dataset  | 
3422  |  |  * name by invoking the Open method of each registered GDALDriver in turn.  | 
3423  |  |  * The first successful open will result in a returned dataset.  If all  | 
3424  |  |  * drivers fail then NULL is returned and an error is issued.  | 
3425  |  |  *  | 
3426  |  |  * Several recommendations :  | 
3427  |  |  * <ul>  | 
3428  |  |  * <li>If you open a dataset object with GA_Update access, it is not recommended  | 
3429  |  |  * to open a new dataset on the same underlying file.</li>  | 
3430  |  |  * <li>The returned dataset should only be accessed by one thread at a time. If  | 
3431  |  |  * you want to use it from different threads, you must add all necessary code  | 
3432  |  |  * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such  | 
3433  |  |  * as GeoTIFF, maintain internal state variables that are updated each time a  | 
3434  |  |  * new block is read, thus preventing concurrent use.) </li>  | 
3435  |  |  * </ul>  | 
3436  |  |  *  | 
3437  |  |  * For drivers supporting the VSI virtual file API, it is possible to open a  | 
3438  |  |  * file in a .zip archive (see VSIInstallZipFileHandler()), in a  | 
3439  |  |  * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP  | 
3440  |  |  * server (see VSIInstallCurlFileHandler())  | 
3441  |  |  *  | 
3442  |  |  * \sa GDALOpenShared()  | 
3443  |  |  * \sa GDALOpenEx()  | 
3444  |  |  *  | 
3445  |  |  * @param pszFilename the name of the file to access.  In the case of  | 
3446  |  |  * exotic drivers this may not refer to a physical file, but instead contain  | 
3447  |  |  * information for the driver on how to access a dataset.  It should be in UTF-8  | 
3448  |  |  * encoding.  | 
3449  |  |  *  | 
3450  |  |  * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many  | 
3451  |  |  * drivers support only read only access.  | 
3452  |  |  *  | 
3453  |  |  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications  | 
3454  |  |  * this handle can be cast to a GDALDataset *.  | 
3455  |  |  */  | 
3456  |  |  | 
3457  |  | GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)  | 
3458  |  |  | 
3459  | 0  | { | 
3460  | 0  |     const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;  | 
3461  | 0  |     const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;  | 
3462  | 0  |     GDALDatasetH hDataset =  | 
3463  | 0  |         GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);  | 
3464  | 0  |     return hDataset;  | 
3465  | 0  | }  | 
3466  |  |  | 
3467  |  | /************************************************************************/  | 
3468  |  | /*                             GetSharedDS()                            */  | 
3469  |  | /************************************************************************/  | 
3470  |  |  | 
3471  |  | static GDALDataset *GetSharedDS(const char *pszFilename,  | 
3472  |  |                                 unsigned int nOpenFlags,  | 
3473  |  |                                 const char *const *papszOpenOptions)  | 
3474  | 0  | { | 
3475  | 0  |     CPLMutexHolderD(&hDLMutex);  | 
3476  |  | 
  | 
3477  | 0  |     if (phSharedDatasetSet != nullptr)  | 
3478  | 0  |     { | 
3479  | 0  |         const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();  | 
3480  | 0  |         SharedDatasetCtxt sStruct;  | 
3481  |  | 
  | 
3482  | 0  |         sStruct.nPID = nThisPID;  | 
3483  | 0  |         sStruct.pszDescription = const_cast<char *>(pszFilename);  | 
3484  | 0  |         sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;  | 
3485  | 0  |         std::string osConcatenatedOpenOptions =  | 
3486  | 0  |             GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);  | 
3487  | 0  |         sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];  | 
3488  | 0  |         sStruct.poDS = nullptr;  | 
3489  | 0  |         SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(  | 
3490  | 0  |             CPLHashSetLookup(phSharedDatasetSet, &sStruct));  | 
3491  | 0  |         if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)  | 
3492  | 0  |         { | 
3493  | 0  |             sStruct.nOpenFlags |= GDAL_OF_UPDATE;  | 
3494  | 0  |             psStruct = static_cast<SharedDatasetCtxt *>(  | 
3495  | 0  |                 CPLHashSetLookup(phSharedDatasetSet, &sStruct));  | 
3496  | 0  |         }  | 
3497  | 0  |         if (psStruct)  | 
3498  | 0  |         { | 
3499  | 0  |             return psStruct->poDS;  | 
3500  | 0  |         }  | 
3501  | 0  |     }  | 
3502  | 0  |     return nullptr;  | 
3503  | 0  | }  | 
3504  |  |  | 
3505  |  | /************************************************************************/  | 
3506  |  | /*                             GDALOpenEx()                             */  | 
3507  |  | /************************************************************************/  | 
3508  |  |  | 
3509  |  | /**  | 
3510  |  |  * \brief Open a raster or vector file as a GDALDataset.  | 
3511  |  |  *  | 
3512  |  |  * This function will try to open the passed file, or virtual dataset  | 
3513  |  |  * name by invoking the Open method of each registered GDALDriver in turn.  | 
3514  |  |  * The first successful open will result in a returned dataset.  If all  | 
3515  |  |  * drivers fail then NULL is returned and an error is issued.  | 
3516  |  |  *  | 
3517  |  |  * Several recommendations :  | 
3518  |  |  * <ul>  | 
3519  |  |  * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not  | 
3520  |  |  * recommended to open a new dataset on the same underlying file.</li>  | 
3521  |  |  * <li>The returned dataset should only be accessed by one thread at a time. If  | 
3522  |  |  * you want to use it from different threads, you must add all necessary code  | 
3523  |  |  * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such  | 
3524  |  |  * as GeoTIFF, maintain internal state variables that are updated each time a  | 
3525  |  |  * new block is read, thus preventing concurrent use.) </li>  | 
3526  |  |  * </ul>  | 
3527  |  |  *  | 
3528  |  |  * For drivers supporting the VSI virtual file API, it is possible to open a  | 
3529  |  |  * file in a .zip archive (see VSIInstallZipFileHandler()), in a  | 
3530  |  |  * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP  | 
3531  |  |  * server (see VSIInstallCurlFileHandler())  | 
3532  |  |  *  | 
3533  |  |  * In order to reduce the need for searches through the operating system  | 
3534  |  |  * file system machinery, it is possible to give an optional list of files with  | 
3535  |  |  * the papszSiblingFiles parameter.  | 
3536  |  |  * This is the list of all files at the same level in the file system as the  | 
3537  |  |  * target file, including the target file. The filenames must not include any  | 
3538  |  |  * path components, are essentially just the output of VSIReadDir() on the  | 
3539  |  |  * parent directory. If the target object does not have filesystem semantics  | 
3540  |  |  * then the file list should be NULL.  | 
3541  |  |  *  | 
3542  |  |  * @param pszFilename the name of the file to access.  In the case of  | 
3543  |  |  * exotic drivers this may not refer to a physical file, but instead contain  | 
3544  |  |  * information for the driver on how to access a dataset.  It should be in UTF-8  | 
3545  |  |  * encoding.  | 
3546  |  |  *  | 
3547  |  |  * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined  | 
3548  |  |  * through logical or operator.  | 
3549  |  |  * <ul>  | 
3550  |  |  * <li>Driver kind:  | 
3551  |  |  *   <ul>  | 
3552  |  |  *     <li>GDAL_OF_RASTER for raster drivers,</li>  | 
3553  |  |  *     <li>GDAL_OF_MULTIDIM_RASTER for multidimensional raster drivers,</li>  | 
3554  |  |  *     <li>GDAL_OF_VECTOR for vector drivers,</li>  | 
3555  |  |  *     <li>GDAL_OF_GNM for Geographic Network Model drivers.</li>  | 
3556  |  |  *    </ul>  | 
3557  |  |  * GDAL_OF_RASTER and GDAL_OF_MULTIDIM_RASTER are generally mutually  | 
3558  |  |  * exclusive. If none of the value is specified, GDAL_OF_RASTER | GDAL_OF_VECTOR  | 
3559  |  |  * | GDAL_OF_GNM is implied.  | 
3560  |  |  * </li>  | 
3561  |  |  * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.  | 
3562  |  |  * </li>  | 
3563  |  |  * <li>Shared mode: GDAL_OF_SHARED. If set,  | 
3564  |  |  * it allows the sharing of GDALDataset handles for a dataset with other callers  | 
3565  |  |  * that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will first consult  | 
3566  |  |  * its list of currently open and shared GDALDataset's, and if the  | 
3567  |  |  * GetDescription() name for one exactly matches the pszFilename passed to  | 
3568  |  |  * GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called  | 
3569  |  |  * from the same thread.  | 
3570  |  |  * </li>  | 
3571  |  |  * <li>Thread safe mode: GDAL_OF_THREAD_SAFE (added in 3.10).  | 
3572  |  |  * This must be use in combination with GDAL_OF_RASTER, and is mutually  | 
3573  |  |  * exclusive with GDAL_OF_UPDATE, GDAL_OF_VECTOR, GDAL_OF_MULTIDIM_RASTER or  | 
3574  |  |  * GDAL_OF_GNM.  | 
3575  |  |  * </li>  | 
3576  |  |  * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set,  | 
3577  |  |  * a failed attempt to open the file will lead to an error message to be  | 
3578  |  |  * reported.  | 
3579  |  |  * </li>  | 
3580  |  |  * </ul>  | 
3581  |  |  *  | 
3582  |  |  * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL  | 
3583  |  |  * terminated list of strings with the driver short names that must be  | 
3584  |  |  * considered.  | 
3585  |  |  *  | 
3586  |  |  * @param papszOpenOptions NULL, or a NULL terminated list of strings with open  | 
3587  |  |  * options passed to candidate drivers. An option exists for all drivers,  | 
3588  |  |  * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.  | 
3589  |  |  * The level index starts at 0. The level number can be suffixed by "only" to  | 
3590  |  |  * specify that only this overview level must be visible, and not sub-levels.  | 
3591  |  |  * Open options are validated by default, and a warning is emitted in case the  | 
3592  |  |  * option is not recognized. In some scenarios, it might be not desirable (e.g.  | 
3593  |  |  * when not knowing which driver will open the file), so the special open option  | 
3594  |  |  * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,  | 
3595  |  |  * since GDAL 2.1, an option name can be preceded by the @ character to indicate  | 
3596  |  |  * that it may not cause a warning if the driver doesn't declare this option.  | 
3597  |  |  * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that  | 
3598  |  |  * no overviews should be exposed.  | 
3599  |  |  *  | 
3600  |  |  * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are  | 
3601  |  |  * filenames that are auxiliary to the main filename. If NULL is passed, a  | 
3602  |  |  * probing of the file system will be done.  | 
3603  |  |  *  | 
3604  |  |  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications  | 
3605  |  |  * this handle can be cast to a GDALDataset *.  | 
3606  |  |  *  | 
3607  |  |  * @since GDAL 2.0  | 
3608  |  |  */  | 
3609  |  |  | 
3610  |  | GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,  | 
3611  |  |                                     unsigned int nOpenFlags,  | 
3612  |  |                                     const char *const *papszAllowedDrivers,  | 
3613  |  |                                     const char *const *papszOpenOptions,  | 
3614  |  |                                     const char *const *papszSiblingFiles)  | 
3615  | 0  | { | 
3616  | 0  |     VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);  | 
3617  |  |  | 
3618  |  |     // Hack for the ZARR driver. We translate the CACHE_KERCHUNK_JSON  | 
3619  |  |     // into VSIKERCHUNK_USE_CACHE config option  | 
3620  | 0  |     std::unique_ptr<CPLConfigOptionSetter> poVSIKERCHUNK_USE_CACHESetter;  | 
3621  | 0  |     if (CPLFetchBool(papszOpenOptions, "CACHE_KERCHUNK_JSON", false))  | 
3622  | 0  |     { | 
3623  | 0  |         poVSIKERCHUNK_USE_CACHESetter = std::make_unique<CPLConfigOptionSetter>(  | 
3624  | 0  |             "VSIKERCHUNK_USE_CACHE", "YES", false);  | 
3625  | 0  |     }  | 
3626  |  |  | 
3627  |  |     // Do some sanity checks on incompatible flags with thread-safe mode.  | 
3628  | 0  |     if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)  | 
3629  | 0  |     { | 
3630  | 0  |         const struct  | 
3631  | 0  |         { | 
3632  | 0  |             int nFlag;  | 
3633  | 0  |             const char *pszFlagName;  | 
3634  | 0  |         } asFlags[] = { | 
3635  | 0  |             {GDAL_OF_UPDATE, "GDAL_OF_UPDATE"}, | 
3636  | 0  |             {GDAL_OF_VECTOR, "GDAL_OF_VECTOR"}, | 
3637  | 0  |             {GDAL_OF_MULTIDIM_RASTER, "GDAL_OF_MULTIDIM_RASTER"}, | 
3638  | 0  |             {GDAL_OF_GNM, "GDAL_OF_GNM"}, | 
3639  | 0  |         };  | 
3640  |  | 
  | 
3641  | 0  |         for (const auto &asFlag : asFlags)  | 
3642  | 0  |         { | 
3643  | 0  |             if ((nOpenFlags & asFlag.nFlag) != 0)  | 
3644  | 0  |             { | 
3645  | 0  |                 CPLError(CE_Failure, CPLE_IllegalArg,  | 
3646  | 0  |                          "GDAL_OF_THREAD_SAFE and %s are mutually "  | 
3647  | 0  |                          "exclusive",  | 
3648  | 0  |                          asFlag.pszFlagName);  | 
3649  | 0  |                 return nullptr;  | 
3650  | 0  |             }  | 
3651  | 0  |         }  | 
3652  | 0  |     }  | 
3653  |  |  | 
3654  |  |     // If no driver kind is specified, assume all are to be probed.  | 
3655  | 0  |     if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)  | 
3656  | 0  |         nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;  | 
3657  |  |  | 
3658  |  |     /* -------------------------------------------------------------------- */  | 
3659  |  |     /*      In case of shared dataset, first scan the existing list to see  */  | 
3660  |  |     /*      if it could already contain the requested dataset.              */  | 
3661  |  |     /* -------------------------------------------------------------------- */  | 
3662  | 0  |     if (nOpenFlags & GDAL_OF_SHARED)  | 
3663  | 0  |     { | 
3664  | 0  |         if (nOpenFlags & GDAL_OF_INTERNAL)  | 
3665  | 0  |         { | 
3666  | 0  |             CPLError(CE_Failure, CPLE_IllegalArg,  | 
3667  | 0  |                      "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");  | 
3668  | 0  |             return nullptr;  | 
3669  | 0  |         }  | 
3670  |  |  | 
3671  | 0  |         auto poSharedDS =  | 
3672  | 0  |             GetSharedDS(pszFilename, nOpenFlags, papszOpenOptions);  | 
3673  | 0  |         if (poSharedDS)  | 
3674  | 0  |         { | 
3675  | 0  |             poSharedDS->Reference();  | 
3676  | 0  |             return poSharedDS;  | 
3677  | 0  |         }  | 
3678  | 0  |     }  | 
3679  |  |  | 
3680  | 0  |     GDALDriverManager *poDM = GetGDALDriverManager();  | 
3681  |  |     // CPLLocaleC  oLocaleForcer;  | 
3682  |  | 
  | 
3683  | 0  |     CPLErrorReset();  | 
3684  | 0  |     VSIErrorReset();  | 
3685  | 0  |     CPLAssert(nullptr != poDM);  | 
3686  |  |  | 
3687  |  |     // Build GDALOpenInfo just now to avoid useless file stat'ing if a  | 
3688  |  |     // shared dataset was asked before.  | 
3689  | 0  |     GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,  | 
3690  | 0  |                            const_cast<char **>(papszSiblingFiles));  | 
3691  | 0  |     oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;  | 
3692  |  | 
  | 
3693  | 0  |     GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();  | 
3694  | 0  |     if (sAntiRecursion.nRecLevel == 100)  | 
3695  | 0  |     { | 
3696  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
3697  | 0  |                  "GDALOpen() called with too many recursion levels");  | 
3698  | 0  |         return nullptr;  | 
3699  | 0  |     }  | 
3700  |  |  | 
3701  | 0  |     std::string osAllowedDrivers;  | 
3702  | 0  |     for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))  | 
3703  | 0  |         osAllowedDrivers += pszDriverName;  | 
3704  | 0  |     auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(  | 
3705  | 0  |         std::string(pszFilename), nOpenFlags, osAllowedDrivers);  | 
3706  | 0  |     if (cpl::contains(sAntiRecursion.aosDatasetNamesWithFlags, dsCtxt))  | 
3707  | 0  |     { | 
3708  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
3709  | 0  |                  "GDALOpen() called on %s recursively", pszFilename);  | 
3710  | 0  |         return nullptr;  | 
3711  | 0  |     }  | 
3712  |  |  | 
3713  |  |     // Remove leading @ if present.  | 
3714  | 0  |     char **papszOpenOptionsCleaned =  | 
3715  | 0  |         CSLDuplicate(const_cast<char **>(papszOpenOptions));  | 
3716  | 0  |     for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;  | 
3717  | 0  |          ++papszIter)  | 
3718  | 0  |     { | 
3719  | 0  |         char *pszOption = *papszIter;  | 
3720  | 0  |         if (pszOption[0] == '@')  | 
3721  | 0  |             memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);  | 
3722  | 0  |     }  | 
3723  |  | 
  | 
3724  | 0  |     oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;  | 
3725  | 0  |     oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;  | 
3726  |  | 
  | 
3727  | 0  | #ifdef OGRAPISPY_ENABLED  | 
3728  | 0  |     const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;  | 
3729  | 0  |     const int iSnapshot =  | 
3730  | 0  |         (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0  | 
3731  | 0  |             ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)  | 
3732  | 0  |             : INT_MIN;  | 
3733  | 0  | #endif  | 
3734  |  | 
  | 
3735  | 0  |     const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);  | 
3736  | 0  |     GDALDriver *poMissingPluginDriver = nullptr;  | 
3737  | 0  |     std::vector<GDALDriver *> apoSecondPassDrivers;  | 
3738  |  |  | 
3739  |  |     // Lookup of matching driver for dataset can involve up to 2 passes:  | 
3740  |  |     // - in the first pass, all drivers that are compabile of the request mode  | 
3741  |  |     //   (raster/vector/etc.) are probed using their Identify() method if it  | 
3742  |  |     //   exists. If the Identify() method returns FALSE, the driver is skipped.  | 
3743  |  |     //   If the Identify() methods returns GDAL_IDENTIFY_UNKNOWN and that the  | 
3744  |  |     //   driver is a deferred-loading plugin, it is added to the  | 
3745  |  |     //   apoSecondPassDrivers list for potential later probing, and execution  | 
3746  |  |     //   continues to the next driver in the list.  | 
3747  |  |     //   Otherwise if Identify() returns non-FALSE, the Open() method is used.  | 
3748  |  |     //   If Open() returns a non-NULL dataset, the loop stops and it is  | 
3749  |  |     //   returned. Otherwise looping over remaining drivers continues.  | 
3750  |  |     // - the second pass is optional, only if at least one driver was added  | 
3751  |  |     //   into apoSecondPassDrivers during the first pass. It is similar  | 
3752  |  |     //   to the first pass except it runs only on apoSecondPassDrivers drivers.  | 
3753  |  |     //   And the Open() method of such drivers is used, causing them to be  | 
3754  |  |     //   loaded for real.  | 
3755  | 0  |     int iPass = 1;  | 
3756  | 0  | retry:  | 
3757  | 0  |     for (int iDriver = 0;  | 
3758  | 0  |          iDriver < (iPass == 1 ? nDriverCount  | 
3759  | 0  |                                : static_cast<int>(apoSecondPassDrivers.size()));  | 
3760  | 0  |          ++iDriver)  | 
3761  | 0  |     { | 
3762  | 0  |         GDALDriver *poDriver =  | 
3763  | 0  |             iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)  | 
3764  | 0  |                        : apoSecondPassDrivers[iDriver];  | 
3765  | 0  |         if (papszAllowedDrivers != nullptr &&  | 
3766  | 0  |             CSLFindString(papszAllowedDrivers,  | 
3767  | 0  |                           GDALGetDriverShortName(poDriver)) == -1)  | 
3768  | 0  |         { | 
3769  | 0  |             continue;  | 
3770  | 0  |         }  | 
3771  |  |  | 
3772  | 0  |         if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)  | 
3773  | 0  |             continue;  | 
3774  |  |  | 
3775  | 0  |         if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&  | 
3776  | 0  |             (nOpenFlags & GDAL_OF_VECTOR) == 0 &&  | 
3777  | 0  |             poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)  | 
3778  | 0  |             continue;  | 
3779  | 0  |         if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&  | 
3780  | 0  |             (nOpenFlags & GDAL_OF_RASTER) == 0 &&  | 
3781  | 0  |             poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)  | 
3782  | 0  |             continue;  | 
3783  | 0  |         if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&  | 
3784  | 0  |             (nOpenFlags & GDAL_OF_RASTER) == 0 &&  | 
3785  | 0  |             poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)  | 
3786  | 0  |             continue;  | 
3787  |  |  | 
3788  |  |         // Remove general OVERVIEW_LEVEL open options from list before passing  | 
3789  |  |         // it to the driver, if it isn't a driver specific option already.  | 
3790  | 0  |         char **papszTmpOpenOptions = nullptr;  | 
3791  | 0  |         char **papszTmpOpenOptionsToValidate = nullptr;  | 
3792  | 0  |         char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);  | 
3793  | 0  |         if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=  | 
3794  | 0  |                 nullptr &&  | 
3795  | 0  |             !poDriver->HasOpenOption("OVERVIEW_LEVEL")) | 
3796  | 0  |         { | 
3797  | 0  |             papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);  | 
3798  | 0  |             papszTmpOpenOptions =  | 
3799  | 0  |                 CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);  | 
3800  | 0  |             oOpenInfo.papszOpenOptions = papszTmpOpenOptions;  | 
3801  |  | 
  | 
3802  | 0  |             papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);  | 
3803  | 0  |             papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate,  | 
3804  | 0  |                                                      "OVERVIEW_LEVEL", nullptr);  | 
3805  | 0  |             papszTmpOpenOptionsToValidate = papszOptionsToValidate;  | 
3806  | 0  |         }  | 
3807  |  | 
  | 
3808  | 0  |         const int nIdentifyRes =  | 
3809  | 0  |             poDriver->pfnIdentifyEx  | 
3810  | 0  |                 ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)  | 
3811  | 0  |             : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)  | 
3812  | 0  |                                     : GDAL_IDENTIFY_UNKNOWN;  | 
3813  | 0  |         if (nIdentifyRes == FALSE)  | 
3814  | 0  |         { | 
3815  | 0  |             CSLDestroy(papszTmpOpenOptions);  | 
3816  | 0  |             CSLDestroy(papszTmpOpenOptionsToValidate);  | 
3817  | 0  |             oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;  | 
3818  | 0  |             continue;  | 
3819  | 0  |         }  | 
3820  | 0  |         else if (iPass == 1 && nIdentifyRes < 0 &&  | 
3821  | 0  |                  poDriver->pfnOpen == nullptr &&  | 
3822  | 0  |                  poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN")) | 
3823  | 0  |         { | 
3824  |  |             // Not loaded plugin  | 
3825  | 0  |             apoSecondPassDrivers.push_back(poDriver);  | 
3826  | 0  |             CSLDestroy(papszTmpOpenOptions);  | 
3827  | 0  |             CSLDestroy(papszTmpOpenOptionsToValidate);  | 
3828  | 0  |             oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;  | 
3829  | 0  |             continue;  | 
3830  | 0  |         }  | 
3831  |  |  | 
3832  | 0  |         const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;  | 
3833  | 0  |         if (bIdentifyRes)  | 
3834  | 0  |         { | 
3835  | 0  |             GDALValidateOpenOptions(poDriver, papszOptionsToValidate);  | 
3836  | 0  |         }  | 
3837  |  | 
  | 
3838  | 0  | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION  | 
3839  | 0  |         const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;  | 
3840  | 0  |         CPLErrorReset();  | 
3841  | 0  | #endif  | 
3842  |  | 
  | 
3843  | 0  |         sAntiRecursion.nRecLevel++;  | 
3844  | 0  |         sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);  | 
3845  |  | 
  | 
3846  | 0  |         GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);  | 
3847  |  | 
  | 
3848  | 0  |         sAntiRecursion.nRecLevel--;  | 
3849  | 0  |         sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);  | 
3850  |  | 
  | 
3851  | 0  |         if (poDriver->pfnOpen != nullptr)  | 
3852  | 0  |         { | 
3853  |  |             // If we couldn't determine for sure with Identify() (it returned  | 
3854  |  |             // -1), but Open() managed to open the file, post validate options.  | 
3855  | 0  |             if (poDS != nullptr &&  | 
3856  | 0  |                 (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&  | 
3857  | 0  |                 !bIdentifyRes)  | 
3858  | 0  |             { | 
3859  | 0  |                 GDALValidateOpenOptions(poDriver, papszOptionsToValidate);  | 
3860  | 0  |             }  | 
3861  | 0  |         }  | 
3862  | 0  |         else if (poDriver->pfnOpenWithDriverArg != nullptr)  | 
3863  | 0  |         { | 
3864  |  |             // do nothing  | 
3865  | 0  |         }  | 
3866  | 0  |         else if (bIdentifyRes &&  | 
3867  | 0  |                  poDriver->GetMetadataItem("MISSING_PLUGIN_FILENAME")) | 
3868  | 0  |         { | 
3869  | 0  |             if (!poMissingPluginDriver)  | 
3870  | 0  |             { | 
3871  | 0  |                 poMissingPluginDriver = poDriver;  | 
3872  | 0  |             }  | 
3873  | 0  |         }  | 
3874  | 0  |         else  | 
3875  | 0  |         { | 
3876  |  |             // should not happen given the GDAL_DCAP_OPEN check  | 
3877  | 0  |             CSLDestroy(papszTmpOpenOptions);  | 
3878  | 0  |             CSLDestroy(papszTmpOpenOptionsToValidate);  | 
3879  | 0  |             oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;  | 
3880  | 0  |             continue;  | 
3881  | 0  |         }  | 
3882  |  |  | 
3883  | 0  |         CSLDestroy(papszTmpOpenOptions);  | 
3884  | 0  |         CSLDestroy(papszTmpOpenOptionsToValidate);  | 
3885  | 0  |         oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;  | 
3886  |  | 
  | 
3887  | 0  |         if (poDS != nullptr)  | 
3888  | 0  |         { | 
3889  | 0  |             if (poDS->papszOpenOptions == nullptr)  | 
3890  | 0  |             { | 
3891  | 0  |                 poDS->papszOpenOptions = papszOpenOptionsCleaned;  | 
3892  | 0  |                 papszOpenOptionsCleaned = nullptr;  | 
3893  | 0  |             }  | 
3894  |  |  | 
3895  |  |             // Deal with generic OVERVIEW_LEVEL open option, unless it is  | 
3896  |  |             // driver specific.  | 
3897  | 0  |             if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=  | 
3898  | 0  |                     nullptr &&  | 
3899  | 0  |                 !poDriver->HasOpenOption("OVERVIEW_LEVEL")) | 
3900  | 0  |             { | 
3901  | 0  |                 CPLString osVal(  | 
3902  | 0  |                     CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));  | 
3903  | 0  |                 const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);  | 
3904  | 0  |                 const bool bThisLevelOnly =  | 
3905  | 0  |                     nOvrLevel == -1 || osVal.ifind("only") != std::string::npos; | 
3906  | 0  |                 GDALDataset *poOvrDS =  | 
3907  | 0  |                     GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly);  | 
3908  | 0  |                 if (poOvrDS && (nOpenFlags & GDAL_OF_SHARED) != 0)  | 
3909  | 0  |                 { | 
3910  | 0  |                     if (strcmp(pszFilename, poDS->GetDescription()) != 0)  | 
3911  | 0  |                     { | 
3912  | 0  |                         CPLError(  | 
3913  | 0  |                             CE_Warning, CPLE_NotSupported,  | 
3914  | 0  |                             "A dataset opened by GDALOpenShared should have "  | 
3915  | 0  |                             "the same filename (%s) "  | 
3916  | 0  |                             "and description (%s)",  | 
3917  | 0  |                             pszFilename, poDS->GetDescription());  | 
3918  | 0  |                     }  | 
3919  | 0  |                     else  | 
3920  | 0  |                     { | 
3921  | 0  |                         CSLDestroy(poDS->papszOpenOptions);  | 
3922  | 0  |                         poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);  | 
3923  | 0  |                         poDS->papszOpenOptions = CSLSetNameValue(  | 
3924  | 0  |                             poDS->papszOpenOptions, "OVERVIEW_LEVEL", nullptr);  | 
3925  | 0  |                     }  | 
3926  | 0  |                 }  | 
3927  | 0  |                 poDS->ReleaseRef();  | 
3928  | 0  |                 poDS = poOvrDS;  | 
3929  | 0  |                 if (poDS == nullptr)  | 
3930  | 0  |                 { | 
3931  | 0  |                     if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)  | 
3932  | 0  |                     { | 
3933  | 0  |                         CPLError(CE_Failure, CPLE_OpenFailed,  | 
3934  | 0  |                                  "Cannot open overview level %d of %s",  | 
3935  | 0  |                                  nOvrLevel, pszFilename);  | 
3936  | 0  |                     }  | 
3937  | 0  |                 }  | 
3938  | 0  |                 else  | 
3939  | 0  |                 { | 
3940  |  |                     // For thread-safe opening, currently poDS is what will be  | 
3941  |  |                     // the "master" dataset owned by the thread-safe dataset  | 
3942  |  |                     // returned to the user, hence we do not register it as a  | 
3943  |  |                     // visible one in the open dataset list, or mark it as shared.  | 
3944  | 0  |                     if (!(nOpenFlags & GDAL_OF_INTERNAL) &&  | 
3945  | 0  |                         !(nOpenFlags & GDAL_OF_THREAD_SAFE))  | 
3946  | 0  |                     { | 
3947  | 0  |                         poDS->AddToDatasetOpenList();  | 
3948  | 0  |                     }  | 
3949  | 0  |                     if (nOpenFlags & GDAL_OF_SHARED)  | 
3950  | 0  |                     { | 
3951  | 0  |                         CSLDestroy(poDS->papszOpenOptions);  | 
3952  | 0  |                         poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);  | 
3953  | 0  |                         poDS->nOpenFlags = nOpenFlags;  | 
3954  | 0  |                         if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))  | 
3955  | 0  |                             poDS->MarkAsShared();  | 
3956  | 0  |                     }  | 
3957  | 0  |                 }  | 
3958  | 0  |             }  | 
3959  | 0  |             else if (nOpenFlags & GDAL_OF_SHARED)  | 
3960  | 0  |             { | 
3961  | 0  |                 if (strcmp(pszFilename, poDS->GetDescription()) != 0)  | 
3962  | 0  |                 { | 
3963  | 0  |                     CPLError(CE_Warning, CPLE_NotSupported,  | 
3964  | 0  |                              "A dataset opened by GDALOpenShared should have "  | 
3965  | 0  |                              "the same filename (%s) "  | 
3966  | 0  |                              "and description (%s)",  | 
3967  | 0  |                              pszFilename, poDS->GetDescription());  | 
3968  | 0  |                 }  | 
3969  | 0  |                 else if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))  | 
3970  | 0  |                 { | 
3971  |  |                     // For thread-safe opening, currently poDS is what will be  | 
3972  |  |                     // the "master" dataset owned by the thread-safe dataset  | 
3973  |  |                     // returned to the user, hence we do not or mark it as shared.  | 
3974  | 0  |                     poDS->MarkAsShared();  | 
3975  | 0  |                 }  | 
3976  | 0  |             }  | 
3977  |  | 
  | 
3978  | 0  |             VSIErrorReset();  | 
3979  |  | 
  | 
3980  | 0  |             CSLDestroy(papszOpenOptionsCleaned);  | 
3981  |  | 
  | 
3982  | 0  | #ifdef OGRAPISPY_ENABLED  | 
3983  | 0  |             if (iSnapshot != INT_MIN)  | 
3984  | 0  |             { | 
3985  | 0  |                 GDALDatasetH hDS = GDALDataset::ToHandle(poDS);  | 
3986  | 0  |                 OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);  | 
3987  | 0  |                 poDS = GDALDataset::FromHandle(hDS);  | 
3988  | 0  |             }  | 
3989  | 0  | #endif  | 
3990  |  | 
  | 
3991  | 0  |             if (poDS)  | 
3992  | 0  |             { | 
3993  | 0  |                 poDS->m_bCanBeReopened = true;  | 
3994  |  | 
  | 
3995  | 0  |                 if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)  | 
3996  | 0  |                 { | 
3997  | 0  |                     poDS =  | 
3998  | 0  |                         GDALGetThreadSafeDataset(  | 
3999  | 0  |                             std::unique_ptr<GDALDataset>(poDS), GDAL_OF_RASTER)  | 
4000  | 0  |                             .release();  | 
4001  | 0  |                     if (poDS)  | 
4002  | 0  |                     { | 
4003  | 0  |                         poDS->m_bCanBeReopened = true;  | 
4004  | 0  |                         poDS->poDriver = poDriver;  | 
4005  | 0  |                         poDS->nOpenFlags = nOpenFlags;  | 
4006  | 0  |                         if (!(nOpenFlags & GDAL_OF_INTERNAL))  | 
4007  | 0  |                             poDS->AddToDatasetOpenList();  | 
4008  | 0  |                         if (nOpenFlags & GDAL_OF_SHARED)  | 
4009  | 0  |                             poDS->MarkAsShared();  | 
4010  | 0  |                     }  | 
4011  | 0  |                 }  | 
4012  | 0  |             }  | 
4013  |  | 
  | 
4014  | 0  |             return poDS;  | 
4015  | 0  |         }  | 
4016  |  |  | 
4017  | 0  | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION  | 
4018  | 0  |         if (bFpAvailableBefore && oOpenInfo.fpL == nullptr)  | 
4019  | 0  |         { | 
4020  |  |             // In case the file descriptor was "consumed" by a driver  | 
4021  |  |             // that ultimately failed, re-open it for next drivers.  | 
4022  | 0  |             oOpenInfo.fpL = VSIFOpenL(  | 
4023  | 0  |                 pszFilename, (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");  | 
4024  | 0  |         }  | 
4025  |  | #else  | 
4026  |  |         if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)  | 
4027  |  |         { | 
4028  |  |             CSLDestroy(papszOpenOptionsCleaned);  | 
4029  |  |  | 
4030  |  | #ifdef OGRAPISPY_ENABLED  | 
4031  |  |             if (iSnapshot != INT_MIN)  | 
4032  |  |             { | 
4033  |  |                 GDALDatasetH hDS = nullptr;  | 
4034  |  |                 OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);  | 
4035  |  |             }  | 
4036  |  | #endif  | 
4037  |  |             return nullptr;  | 
4038  |  |         }  | 
4039  |  | #endif  | 
4040  | 0  |     }  | 
4041  |  |  | 
4042  |  |     // cppcheck-suppress knownConditionTrueFalse  | 
4043  | 0  |     if (iPass == 1 && !apoSecondPassDrivers.empty())  | 
4044  | 0  |     { | 
4045  | 0  |         CPLDebugOnly("GDAL", "GDALOpen(): Second pass"); | 
4046  | 0  |         iPass = 2;  | 
4047  | 0  |         goto retry;  | 
4048  | 0  |     }  | 
4049  |  |  | 
4050  | 0  |     CSLDestroy(papszOpenOptionsCleaned);  | 
4051  |  | 
  | 
4052  | 0  | #ifdef OGRAPISPY_ENABLED  | 
4053  | 0  |     if (iSnapshot != INT_MIN)  | 
4054  | 0  |     { | 
4055  | 0  |         GDALDatasetH hDS = nullptr;  | 
4056  | 0  |         OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);  | 
4057  | 0  |     }  | 
4058  | 0  | #endif  | 
4059  |  | 
  | 
4060  | 0  |     if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)  | 
4061  | 0  |     { | 
4062  | 0  |         if (nDriverCount == 0)  | 
4063  | 0  |         { | 
4064  | 0  |             CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");  | 
4065  | 0  |         }  | 
4066  | 0  |         else if (poMissingPluginDriver)  | 
4067  | 0  |         { | 
4068  | 0  |             std::string osMsg("`"); | 
4069  | 0  |             osMsg += pszFilename;  | 
4070  | 0  |             osMsg += "' not recognized as being in a supported file format. "  | 
4071  | 0  |                      "It could have been recognized by driver ";  | 
4072  | 0  |             osMsg += poMissingPluginDriver->GetDescription();  | 
4073  | 0  |             osMsg += ", but plugin ";  | 
4074  | 0  |             osMsg +=  | 
4075  | 0  |                 GDALGetMessageAboutMissingPluginDriver(poMissingPluginDriver);  | 
4076  |  | 
  | 
4077  | 0  |             CPLError(CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str());  | 
4078  | 0  |         }  | 
4079  |  |         // Check to see if there was a filesystem error, and report it if so.  | 
4080  |  |         // If not, return a more generic error.  | 
4081  | 0  |         else if (!VSIToCPLError(CE_Failure, CPLE_OpenFailed))  | 
4082  | 0  |         { | 
4083  | 0  |             if (oOpenInfo.bStatOK)  | 
4084  | 0  |             { | 
4085  | 0  |                 CPLError(CE_Failure, CPLE_OpenFailed,  | 
4086  | 0  |                          "`%s' not recognized as being in a supported file "  | 
4087  | 0  |                          "format.",  | 
4088  | 0  |                          pszFilename);  | 
4089  | 0  |             }  | 
4090  | 0  |             else  | 
4091  | 0  |             { | 
4092  |  |                 // If Stat failed and no VSI error was set, assume it is because  | 
4093  |  |                 // the file did not exist on the filesystem.  | 
4094  | 0  |                 CPLError(CE_Failure, CPLE_OpenFailed,  | 
4095  | 0  |                          "`%s' does not exist in the file system, "  | 
4096  | 0  |                          "and is not recognized as a supported dataset name.",  | 
4097  | 0  |                          pszFilename);  | 
4098  | 0  |             }  | 
4099  | 0  |         }  | 
4100  | 0  |     }  | 
4101  |  | 
  | 
4102  | 0  |     return nullptr;  | 
4103  | 0  | }  | 
4104  |  |  | 
4105  |  | /************************************************************************/  | 
4106  |  | /*                           GDALOpenShared()                           */  | 
4107  |  | /************************************************************************/  | 
4108  |  |  | 
4109  |  | /**  | 
4110  |  |  * \brief Open a raster file as a GDALDataset.  | 
4111  |  |  *  | 
4112  |  |  * This function works the same as GDALOpen(), but allows the sharing of  | 
4113  |  |  * GDALDataset handles for a dataset with other callers to GDALOpenShared().  | 
4114  |  |  *  | 
4115  |  |  * In particular, GDALOpenShared() will first consult its list of currently  | 
4116  |  |  * open and shared GDALDataset's, and if the GetDescription() name for one  | 
4117  |  |  * exactly matches the pszFilename passed to GDALOpenShared() it will be  | 
4118  |  |  * referenced and returned.  | 
4119  |  |  *  | 
4120  |  |  * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same  | 
4121  |  |  * pszFilename from two different threads, a different GDALDataset object will  | 
4122  |  |  * be returned as it is not safe to use the same dataset from different threads,  | 
4123  |  |  * unless the user does explicitly use mutexes in its code.  | 
4124  |  |  *  | 
4125  |  |  * For drivers supporting the VSI virtual file API, it is possible to open a  | 
4126  |  |  * file in a .zip archive (see VSIInstallZipFileHandler()), in a  | 
4127  |  |  * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP  | 
4128  |  |  * server (see VSIInstallCurlFileHandler())  | 
4129  |  |  *  | 
4130  |  |  * \sa GDALOpen()  | 
4131  |  |  * \sa GDALOpenEx()  | 
4132  |  |  *  | 
4133  |  |  * @param pszFilename the name of the file to access.  In the case of  | 
4134  |  |  * exotic drivers this may not refer to a physical file, but instead contain  | 
4135  |  |  * information for the driver on how to access a dataset.  It should be in  | 
4136  |  |  * UTF-8 encoding.  | 
4137  |  |  *  | 
4138  |  |  * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many  | 
4139  |  |  * drivers support only read only access.  | 
4140  |  |  *  | 
4141  |  |  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications  | 
4142  |  |  * this handle can be cast to a GDALDataset *.  | 
4143  |  |  */  | 
4144  |  |  | 
4145  |  | GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,  | 
4146  |  |                                         GDALAccess eAccess)  | 
4147  | 0  | { | 
4148  | 0  |     VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);  | 
4149  | 0  |     return GDALOpenEx(pszFilename,  | 
4150  | 0  |                       GDAL_OF_RASTER |  | 
4151  | 0  |                           (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |  | 
4152  | 0  |                           GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,  | 
4153  | 0  |                       nullptr, nullptr, nullptr);  | 
4154  | 0  | }  | 
4155  |  |  | 
4156  |  | /************************************************************************/  | 
4157  |  | /*                             GDALClose()                              */  | 
4158  |  | /************************************************************************/  | 
4159  |  |  | 
4160  |  | /**  | 
4161  |  |  * \brief Close GDAL dataset.  | 
4162  |  |  *  | 
4163  |  |  * For non-shared datasets (opened with GDALOpen()) the dataset is closed  | 
4164  |  |  * using the C++ "delete" operator, recovering all dataset related resources.  | 
4165  |  |  * For shared datasets (opened with GDALOpenShared()) the dataset is  | 
4166  |  |  * dereferenced, and closed only if the referenced count has dropped below 1.  | 
4167  |  |  *  | 
4168  |  |  * @param hDS The dataset to close.  May be cast from a "GDALDataset *".  | 
4169  |  |  * @return CE_None in case of success (return value since GDAL 3.7). On a  | 
4170  |  |  * shared dataset whose reference count is not dropped below 1, CE_None will  | 
4171  |  |  * be returned.  | 
4172  |  |  */  | 
4173  |  |  | 
4174  |  | CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)  | 
4175  |  |  | 
4176  | 0  | { | 
4177  | 0  |     if (!hDS)  | 
4178  | 0  |         return CE_None;  | 
4179  |  |  | 
4180  | 0  | #ifdef OGRAPISPY_ENABLED  | 
4181  | 0  |     if (bOGRAPISpyEnabled)  | 
4182  | 0  |         OGRAPISpyPreClose(hDS);  | 
4183  | 0  | #endif  | 
4184  |  | 
  | 
4185  | 0  |     GDALDataset *poDS = GDALDataset::FromHandle(hDS);  | 
4186  |  | 
  | 
4187  | 0  |     if (poDS->GetShared())  | 
4188  | 0  |     { | 
4189  |  |         /* --------------------------------------------------------------------  | 
4190  |  |          */  | 
4191  |  |         /*      If this file is in the shared dataset list then dereference */  | 
4192  |  |         /*      it, and only delete/remote it if the reference count has */  | 
4193  |  |         /*      dropped to zero. */  | 
4194  |  |         /* --------------------------------------------------------------------  | 
4195  |  |          */  | 
4196  | 0  |         if (poDS->Dereference() > 0)  | 
4197  | 0  |             return CE_None;  | 
4198  |  |  | 
4199  | 0  |         CPLErr eErr = poDS->Close();  | 
4200  | 0  |         delete poDS;  | 
4201  |  | 
  | 
4202  | 0  | #ifdef OGRAPISPY_ENABLED  | 
4203  | 0  |         if (bOGRAPISpyEnabled)  | 
4204  | 0  |             OGRAPISpyPostClose();  | 
4205  | 0  | #endif  | 
4206  |  | 
  | 
4207  | 0  |         return eErr;  | 
4208  | 0  |     }  | 
4209  |  |  | 
4210  |  |     /* -------------------------------------------------------------------- */  | 
4211  |  |     /*      This is not shared dataset, so directly delete it.              */  | 
4212  |  |     /* -------------------------------------------------------------------- */  | 
4213  | 0  |     CPLErr eErr = poDS->Close();  | 
4214  | 0  |     delete poDS;  | 
4215  |  | 
  | 
4216  | 0  | #ifdef OGRAPISPY_ENABLED  | 
4217  | 0  |     if (bOGRAPISpyEnabled)  | 
4218  | 0  |         OGRAPISpyPostClose();  | 
4219  | 0  | #endif  | 
4220  | 0  |     return eErr;  | 
4221  | 0  | }  | 
4222  |  |  | 
4223  |  | /************************************************************************/  | 
4224  |  | /*                        GDALDumpOpenDataset()                         */  | 
4225  |  | /************************************************************************/  | 
4226  |  |  | 
4227  |  | static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)  | 
4228  | 0  | { | 
4229  | 0  |     SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);  | 
4230  | 0  |     FILE *fp = static_cast<FILE *>(user_data);  | 
4231  | 0  |     GDALDataset *poDS = psStruct->poDS;  | 
4232  |  | 
  | 
4233  | 0  |     const char *pszDriverName = poDS->GetDriver() == nullptr  | 
4234  | 0  |                                     ? "DriverIsNULL"  | 
4235  | 0  |                                     : poDS->GetDriver()->GetDescription();  | 
4236  |  | 
  | 
4237  | 0  |     poDS->Reference();  | 
4238  | 0  |     CPL_IGNORE_RET_VAL(  | 
4239  | 0  |         VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),  | 
4240  | 0  |                    poDS->GetShared() ? 'S' : 'N', pszDriverName,  | 
4241  | 0  |                    static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),  | 
4242  | 0  |                    poDS->GetRasterYSize(), poDS->GetRasterCount(),  | 
4243  | 0  |                    poDS->GetDescription()));  | 
4244  |  | 
  | 
4245  | 0  |     return TRUE;  | 
4246  | 0  | }  | 
4247  |  |  | 
4248  |  | static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)  | 
4249  | 0  | { | 
4250  |  |  | 
4251  |  |     // Don't list shared datasets. They have already been listed by  | 
4252  |  |     // GDALDumpOpenSharedDatasetsForeach.  | 
4253  | 0  |     if (poDS->GetShared())  | 
4254  | 0  |         return TRUE;  | 
4255  |  |  | 
4256  | 0  |     const char *pszDriverName = poDS->GetDriver() == nullptr  | 
4257  | 0  |                                     ? "DriverIsNULL"  | 
4258  | 0  |                                     : poDS->GetDriver()->GetDescription();  | 
4259  |  | 
  | 
4260  | 0  |     poDS->Reference();  | 
4261  | 0  |     CPL_IGNORE_RET_VAL(  | 
4262  | 0  |         VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),  | 
4263  | 0  |                    poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,  | 
4264  | 0  |                    poDS->GetRasterXSize(), poDS->GetRasterYSize(),  | 
4265  | 0  |                    poDS->GetRasterCount(), poDS->GetDescription()));  | 
4266  |  | 
  | 
4267  | 0  |     return TRUE;  | 
4268  | 0  | }  | 
4269  |  |  | 
4270  |  | /**  | 
4271  |  |  * \brief List open datasets.  | 
4272  |  |  *  | 
4273  |  |  * Dumps a list of all open datasets (shared or not) to the indicated  | 
4274  |  |  * text file (may be stdout or stderr).   This function is primarily intended  | 
4275  |  |  * to assist in debugging "dataset leaks" and reference counting issues.  | 
4276  |  |  * The information reported includes the dataset name, referenced count,  | 
4277  |  |  * shared status, driver name, size, and band count.  | 
4278  |  |  */  | 
4279  |  |  | 
4280  |  | int CPL_STDCALL GDALDumpOpenDatasets(FILE *fp)  | 
4281  |  |  | 
4282  | 0  | { | 
4283  | 0  |     VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);  | 
4284  |  |  | 
4285  | 0  |     CPLMutexHolderD(&hDLMutex);  | 
4286  |  | 
  | 
4287  | 0  |     if (poAllDatasetMap == nullptr)  | 
4288  | 0  |         return 0;  | 
4289  |  |  | 
4290  | 0  |     CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));  | 
4291  |  | 
  | 
4292  | 0  |     for (const auto &oIter : *poAllDatasetMap)  | 
4293  | 0  |     { | 
4294  | 0  |         GDALDumpOpenDatasetsForeach(oIter.first, fp);  | 
4295  | 0  |     }  | 
4296  |  | 
  | 
4297  | 0  |     if (phSharedDatasetSet != nullptr)  | 
4298  | 0  |     { | 
4299  | 0  |         CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach,  | 
4300  | 0  |                           fp);  | 
4301  | 0  |     }  | 
4302  | 0  |     return static_cast<int>(poAllDatasetMap->size());  | 
4303  | 0  | }  | 
4304  |  |  | 
4305  |  | /************************************************************************/  | 
4306  |  | /*                        BeginAsyncReader()                            */  | 
4307  |  | /************************************************************************/  | 
4308  |  |  | 
4309  |  | /**  | 
4310  |  |  * \brief Sets up an asynchronous data request  | 
4311  |  |  *  | 
4312  |  |  * This method establish an asynchronous raster read request for the  | 
4313  |  |  * indicated window on the dataset into the indicated buffer.  The parameters  | 
4314  |  |  * for windowing, buffer size, buffer type and buffer organization are similar  | 
4315  |  |  * to those for GDALDataset::RasterIO(); however, this call only launches  | 
4316  |  |  * the request and filling the buffer is accomplished via calls to  | 
4317  |  |  * GetNextUpdatedRegion() on the return GDALAsyncReader session object.  | 
4318  |  |  *  | 
4319  |  |  * Once all processing for the created session is complete, or if no further  | 
4320  |  |  * refinement of the request is required, the GDALAsyncReader object should  | 
4321  |  |  * be destroyed with the GDALDataset::EndAsyncReader() method.  | 
4322  |  |  *  | 
4323  |  |  * Note that the data buffer (pData) will potentially continue to be  | 
4324  |  |  * updated as long as the session lives, but it is not deallocated when  | 
4325  |  |  * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It  | 
4326  |  |  * should be deallocated by the application at that point.  | 
4327  |  |  *  | 
4328  |  |  * Additional information on asynchronous IO in GDAL may be found at:  | 
4329  |  |  *   https://gdal.org/development/rfc/rfc24_progressive_data_support.html  | 
4330  |  |  *  | 
4331  |  |  * This method is the same as the C GDALBeginAsyncReader() function.  | 
4332  |  |  *  | 
4333  |  |  * @param nXOff The pixel offset to the top left corner of the region  | 
4334  |  |  * of the band to be accessed.  This would be zero to start from the left side.  | 
4335  |  |  *  | 
4336  |  |  * @param nYOff The line offset to the top left corner of the region  | 
4337  |  |  * of the band to be accessed.  This would be zero to start from the top.  | 
4338  |  |  *  | 
4339  |  |  * @param nXSize The width of the region of the band to be accessed in pixels.  | 
4340  |  |  *  | 
4341  |  |  * @param nYSize The height of the region of the band to be accessed in lines.  | 
4342  |  |  *  | 
4343  |  |  * @param pBuf The buffer into which the data should be read. This buffer must  | 
4344  |  |  * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.  | 
4345  |  |  * It is organized in left to right,top to bottom pixel order.  Spacing is  | 
4346  |  |  * controlled by the nPixelSpace, and nLineSpace parameters.  | 
4347  |  |  *  | 
4348  |  |  * @param nBufXSize the width of the buffer image into which the desired region  | 
4349  |  |  * is to be read, or from which it is to be written.  | 
4350  |  |  *  | 
4351  |  |  * @param nBufYSize the height of the buffer image into which the desired  | 
4352  |  |  * region is to be read, or from which it is to be written.  | 
4353  |  |  *  | 
4354  |  |  * @param eBufType the type of the pixel values in the pData data buffer.  The  | 
4355  |  |  * pixel values will automatically be translated to/from the GDALRasterBand  | 
4356  |  |  * data type as needed.  | 
4357  |  |  *  | 
4358  |  |  * @param nBandCount the number of bands being read or written.  | 
4359  |  |  *  | 
4360  |  |  * @param panBandMap the list of nBandCount band numbers being read/written.  | 
4361  |  |  * Note band numbers are 1 based.   This may be NULL to select the first  | 
4362  |  |  * nBandCount bands.  | 
4363  |  |  *  | 
4364  |  |  * @param nPixelSpace The byte offset from the start of one pixel value in  | 
4365  |  |  * pData to the start of the next pixel value within a scanline.  If defaulted  | 
4366  |  |  * (0) the size of the datatype eBufType is used.  | 
4367  |  |  *  | 
4368  |  |  * @param nLineSpace The byte offset from the start of one scanline in  | 
4369  |  |  * pData to the start of the next.  If defaulted the size of the datatype  | 
4370  |  |  * eBufType * nBufXSize is used.  | 
4371  |  |  *  | 
4372  |  |  * @param nBandSpace the byte offset from the start of one bands data to the  | 
4373  |  |  * start of the next.  If defaulted (zero) the value will be  | 
4374  |  |  * nLineSpace * nBufYSize implying band sequential organization  | 
4375  |  |  * of the data buffer.  | 
4376  |  |  *  | 
4377  |  |  * @param papszOptions Driver specific control options in a string list or NULL.  | 
4378  |  |  * Consult driver documentation for options supported.  | 
4379  |  |  *  | 
4380  |  |  * @return The GDALAsyncReader object representing the request.  | 
4381  |  |  */  | 
4382  |  |  | 
4383  |  | GDALAsyncReader *GDALDataset::BeginAsyncReader(  | 
4384  |  |     int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,  | 
4385  |  |     int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,  | 
4386  |  |     int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions)  | 
4387  | 0  | { | 
4388  |  |     // See gdaldefaultasync.cpp  | 
4389  |  | 
  | 
4390  | 0  |     return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,  | 
4391  | 0  |                                      nBufXSize, nBufYSize, eBufType, nBandCount,  | 
4392  | 0  |                                      panBandMap, nPixelSpace, nLineSpace,  | 
4393  | 0  |                                      nBandSpace, papszOptions);  | 
4394  | 0  | }  | 
4395  |  |  | 
4396  |  | /************************************************************************/  | 
4397  |  | /*                        GDALBeginAsyncReader()                      */  | 
4398  |  | /************************************************************************/  | 
4399  |  |  | 
4400  |  | /**  | 
4401  |  |  * \brief Sets up an asynchronous data request  | 
4402  |  |  *  | 
4403  |  |  * This method establish an asynchronous raster read request for the  | 
4404  |  |  * indicated window on the dataset into the indicated buffer.  The parameters  | 
4405  |  |  * for windowing, buffer size, buffer type and buffer organization are similar  | 
4406  |  |  * to those for GDALDataset::RasterIO(); however, this call only launches  | 
4407  |  |  * the request and filling the buffer is accomplished via calls to  | 
4408  |  |  * GetNextUpdatedRegion() on the return GDALAsyncReader session object.  | 
4409  |  |  *  | 
4410  |  |  * Once all processing for the created session is complete, or if no further  | 
4411  |  |  * refinement of the request is required, the GDALAsyncReader object should  | 
4412  |  |  * be destroyed with the GDALDataset::EndAsyncReader() method.  | 
4413  |  |  *  | 
4414  |  |  * Note that the data buffer (pData) will potentially continue to be  | 
4415  |  |  * updated as long as the session lives, but it is not deallocated when  | 
4416  |  |  * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It  | 
4417  |  |  * should be deallocated by the application at that point.  | 
4418  |  |  *  | 
4419  |  |  * Additional information on asynchronous IO in GDAL may be found at:  | 
4420  |  |  *   https://gdal.org/development/rfc/rfc24_progressive_data_support.html  | 
4421  |  |  *  | 
4422  |  |  * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.  | 
4423  |  |  *  | 
4424  |  |  * @param hDS handle to the dataset object.  | 
4425  |  |  *  | 
4426  |  |  * @param nXOff The pixel offset to the top left corner of the region  | 
4427  |  |  * of the band to be accessed.  This would be zero to start from the left side.  | 
4428  |  |  *  | 
4429  |  |  * @param nYOff The line offset to the top left corner of the region  | 
4430  |  |  * of the band to be accessed.  This would be zero to start from the top.  | 
4431  |  |  *  | 
4432  |  |  * @param nXSize The width of the region of the band to be accessed in pixels.  | 
4433  |  |  *  | 
4434  |  |  * @param nYSize The height of the region of the band to be accessed in lines.  | 
4435  |  |  *  | 
4436  |  |  * @param pBuf The buffer into which the data should be read. This buffer must  | 
4437  |  |  * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.  | 
4438  |  |  * It is organized in left to right,top to bottom pixel order.  Spacing is  | 
4439  |  |  * controlled by the nPixelSpace, and nLineSpace parameters.  | 
4440  |  |  *  | 
4441  |  |  * @param nBufXSize the width of the buffer image into which the desired region  | 
4442  |  |  * is to be read, or from which it is to be written.  | 
4443  |  |  *  | 
4444  |  |  * @param nBufYSize the height of the buffer image into which the desired  | 
4445  |  |  * region is to be read, or from which it is to be written.  | 
4446  |  |  *  | 
4447  |  |  * @param eBufType the type of the pixel values in the pData data buffer.  The  | 
4448  |  |  * pixel values will automatically be translated to/from the GDALRasterBand  | 
4449  |  |  * data type as needed.  | 
4450  |  |  *  | 
4451  |  |  * @param nBandCount the number of bands being read or written.  | 
4452  |  |  *  | 
4453  |  |  * @param panBandMap the list of nBandCount band numbers being read/written.  | 
4454  |  |  * Note band numbers are 1 based.   This may be NULL to select the first  | 
4455  |  |  * nBandCount bands.  | 
4456  |  |  *  | 
4457  |  |  * @param nPixelSpace The byte offset from the start of one pixel value in  | 
4458  |  |  * pData to the start of the next pixel value within a scanline.  If defaulted  | 
4459  |  |  * (0) the size of the datatype eBufType is used.  | 
4460  |  |  *  | 
4461  |  |  * @param nLineSpace The byte offset from the start of one scanline in  | 
4462  |  |  * pData to the start of the next.  If defaulted the size of the datatype  | 
4463  |  |  * eBufType * nBufXSize is used.  | 
4464  |  |  *  | 
4465  |  |  * @param nBandSpace the byte offset from the start of one bands data to the  | 
4466  |  |  * start of the next.  If defaulted (zero) the value will be  | 
4467  |  |  * nLineSpace * nBufYSize implying band sequential organization  | 
4468  |  |  * of the data buffer.  | 
4469  |  |  *  | 
4470  |  |  * @param papszOptions Driver specific control options in a string list or NULL.  | 
4471  |  |  * Consult driver documentation for options supported.  | 
4472  |  |  *  | 
4473  |  |  * @return handle representing the request.  | 
4474  |  |  */  | 
4475  |  |  | 
4476  |  | GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(  | 
4477  |  |     GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf,  | 
4478  |  |     int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount,  | 
4479  |  |     int *panBandMap, int nPixelSpace, int nLineSpace, int nBandSpace,  | 
4480  |  |     CSLConstList papszOptions)  | 
4481  |  |  | 
4482  | 0  | { | 
4483  | 0  |     VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);  | 
4484  | 0  |     return static_cast<GDALAsyncReaderH>(  | 
4485  | 0  |         GDALDataset::FromHandle(hDS)->BeginAsyncReader(  | 
4486  | 0  |             nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,  | 
4487  | 0  |             nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,  | 
4488  | 0  |             const_cast<char **>(papszOptions)));  | 
4489  | 0  | }  | 
4490  |  |  | 
4491  |  | /************************************************************************/  | 
4492  |  | /*                        EndAsyncReader()                            */  | 
4493  |  | /************************************************************************/  | 
4494  |  |  | 
4495  |  | /**  | 
4496  |  |  * End asynchronous request.  | 
4497  |  |  *  | 
4498  |  |  * This method destroys an asynchronous io request and recovers all  | 
4499  |  |  * resources associated with it.  | 
4500  |  |  *  | 
4501  |  |  * This method is the same as the C function GDALEndAsyncReader().  | 
4502  |  |  *  | 
4503  |  |  * @param poARIO pointer to a GDALAsyncReader  | 
4504  |  |  */  | 
4505  |  |  | 
4506  |  | void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO)  | 
4507  | 0  | { | 
4508  | 0  |     delete poARIO;  | 
4509  | 0  | }  | 
4510  |  |  | 
4511  |  | /************************************************************************/  | 
4512  |  | /*                        GDALEndAsyncReader()                        */  | 
4513  |  | /************************************************************************/  | 
4514  |  |  | 
4515  |  | /**  | 
4516  |  |  * End asynchronous request.  | 
4517  |  |  *  | 
4518  |  |  * This method destroys an asynchronous io request and recovers all  | 
4519  |  |  * resources associated with it.  | 
4520  |  |  *  | 
4521  |  |  * This method is the same as the C++ method GDALDataset::EndAsyncReader().  | 
4522  |  |  *  | 
4523  |  |  * @param hDS handle to the dataset object.  | 
4524  |  |  * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()  | 
4525  |  |  */  | 
4526  |  |  | 
4527  |  | void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS,  | 
4528  |  |                                     GDALAsyncReaderH hAsyncReaderH)  | 
4529  | 0  | { | 
4530  | 0  |     VALIDATE_POINTER0(hDS, "GDALDataset");  | 
4531  | 0  |     VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");  | 
4532  | 0  |     GDALDataset::FromHandle(hDS)->EndAsyncReader(  | 
4533  | 0  |         static_cast<GDALAsyncReader *>(hAsyncReaderH));  | 
4534  | 0  | }  | 
4535  |  |  | 
4536  |  | /************************************************************************/  | 
4537  |  | /*                       CloseDependentDatasets()                       */  | 
4538  |  | /************************************************************************/  | 
4539  |  |  | 
4540  |  | /**  | 
4541  |  |  * Drop references to any other datasets referenced by this dataset.  | 
4542  |  |  *  | 
4543  |  |  * This method should release any reference to other datasets (e.g. a VRT  | 
4544  |  |  * dataset to its sources), but not close the current dataset itself.  | 
4545  |  |  *  | 
4546  |  |  * If at least, one reference to a dependent dataset has been dropped,  | 
4547  |  |  * this method should return TRUE. Otherwise it *should* return FALSE.  | 
4548  |  |  * (Failure to return the proper value might result in infinite loop)  | 
4549  |  |  *  | 
4550  |  |  * This method can be called several times on a given dataset. After  | 
4551  |  |  * the first time, it should not do anything and return FALSE.  | 
4552  |  |  *  | 
4553  |  |  * The driver implementation may choose to destroy its raster bands,  | 
4554  |  |  * so be careful not to call any method on the raster bands afterwards.  | 
4555  |  |  *  | 
4556  |  |  * Basically the only safe action you can do after calling  | 
4557  |  |  * CloseDependentDatasets() is to call the destructor.  | 
4558  |  |  *  | 
4559  |  |  * Note: the only legitimate caller of CloseDependentDatasets() is  | 
4560  |  |  * GDALDriverManager::~GDALDriverManager()  | 
4561  |  |  *  | 
4562  |  |  * @return TRUE if at least one reference to another dataset has been dropped.  | 
4563  |  |  */  | 
4564  |  | int GDALDataset::CloseDependentDatasets()  | 
4565  | 0  | { | 
4566  | 0  |     return oOvManager.CloseDependentDatasets();  | 
4567  | 0  | }  | 
4568  |  |  | 
4569  |  | /************************************************************************/  | 
4570  |  | /*                            ReportError()                             */  | 
4571  |  | /************************************************************************/  | 
4572  |  |  | 
4573  |  | #ifndef DOXYGEN_XML  | 
4574  |  | /**  | 
4575  |  |  * \brief Emits an error related to a dataset.  | 
4576  |  |  *  | 
4577  |  |  * This function is a wrapper for regular CPLError(). The only difference  | 
4578  |  |  * with CPLError() is that it prepends the error message with the dataset  | 
4579  |  |  * name.  | 
4580  |  |  *  | 
4581  |  |  * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.  | 
4582  |  |  * @param err_no the error number (CPLE_*) from cpl_error.h.  | 
4583  |  |  * @param fmt a printf() style format string.  Any additional arguments  | 
4584  |  |  * will be treated as arguments to fill in this format in a manner  | 
4585  |  |  * similar to printf().  | 
4586  |  |  *  | 
4587  |  |  * @since GDAL 1.9.0  | 
4588  |  |  */  | 
4589  |  |  | 
4590  |  | void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,  | 
4591  |  |                               const char *fmt, ...) const  | 
4592  | 0  | { | 
4593  | 0  |     va_list args;  | 
4594  | 0  |     va_start(args, fmt);  | 
4595  | 0  |     ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);  | 
4596  | 0  |     va_end(args);  | 
4597  | 0  | }  | 
4598  |  |  | 
4599  |  | /**  | 
4600  |  |  * \brief Emits an error related to a dataset (static method)  | 
4601  |  |  *  | 
4602  |  |  * This function is a wrapper for regular CPLError(). The only difference  | 
4603  |  |  * with CPLError() is that it prepends the error message with the dataset  | 
4604  |  |  * name.  | 
4605  |  |  *  | 
4606  |  |  * @param pszDSName dataset name.  | 
4607  |  |  * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.  | 
4608  |  |  * @param err_no the error number (CPLE_*) from cpl_error.h.  | 
4609  |  |  * @param fmt a printf() style format string.  Any additional arguments  | 
4610  |  |  * will be treated as arguments to fill in this format in a manner  | 
4611  |  |  * similar to printf().  | 
4612  |  |  *  | 
4613  |  |  * @since GDAL 3.2.0  | 
4614  |  |  */  | 
4615  |  |  | 
4616  |  | void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,  | 
4617  |  |                               CPLErrorNum err_no, const char *fmt, ...)  | 
4618  | 0  | { | 
4619  | 0  |     va_list args;  | 
4620  | 0  |     va_start(args, fmt);  | 
4621  | 0  |     ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);  | 
4622  | 0  |     va_end(args);  | 
4623  | 0  | }  | 
4624  |  |  | 
4625  |  | void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,  | 
4626  |  |                                CPLErrorNum err_no, const char *fmt,  | 
4627  |  |                                va_list args)  | 
4628  | 0  | { | 
4629  | 0  |     pszDSName = CPLGetFilename(pszDSName);  | 
4630  | 0  |     if (pszDSName[0] != '\0')  | 
4631  | 0  |     { | 
4632  | 0  |         CPLError(eErrClass, err_no, "%s",  | 
4633  | 0  |                  std::string(pszDSName)  | 
4634  | 0  |                      .append(": ") | 
4635  | 0  |                      .append(CPLString().vPrintf(fmt, args))  | 
4636  | 0  |                      .c_str());  | 
4637  | 0  |     }  | 
4638  | 0  |     else  | 
4639  | 0  |     { | 
4640  | 0  |         CPLErrorV(eErrClass, err_no, fmt, args);  | 
4641  | 0  |     }  | 
4642  | 0  | }  | 
4643  |  | #endif  | 
4644  |  |  | 
4645  |  | /************************************************************************/  | 
4646  |  | /*                            GetMetadata()                             */  | 
4647  |  | /************************************************************************/  | 
4648  |  | char **GDALDataset::GetMetadata(const char *pszDomain)  | 
4649  | 0  | { | 
4650  |  | #ifndef WITHOUT_DERIVED  | 
4651  |  |     if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))  | 
4652  |  |     { | 
4653  |  |         oDerivedMetadataList.Clear();  | 
4654  |  |  | 
4655  |  |         // First condition: at least one raster band.  | 
4656  |  |         if (GetRasterCount() > 0)  | 
4657  |  |         { | 
4658  |  |             // Check if there is at least one complex band.  | 
4659  |  |             bool hasAComplexBand = false;  | 
4660  |  |  | 
4661  |  |             for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)  | 
4662  |  |             { | 
4663  |  |                 if (GDALDataTypeIsComplex(  | 
4664  |  |                         GetRasterBand(rasterId)->GetRasterDataType()))  | 
4665  |  |                 { | 
4666  |  |                     hasAComplexBand = true;  | 
4667  |  |                     break;  | 
4668  |  |                 }  | 
4669  |  |             }  | 
4670  |  |  | 
4671  |  |             unsigned int nbSupportedDerivedDS = 0;  | 
4672  |  |             const DerivedDatasetDescription *poDDSDesc =  | 
4673  |  |                 GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);  | 
4674  |  |  | 
4675  |  |             int nNumDataset = 1;  | 
4676  |  |             for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;  | 
4677  |  |                  ++derivedId)  | 
4678  |  |             { | 
4679  |  |                 if (hasAComplexBand ||  | 
4680  |  |                     CPLString(poDDSDesc[derivedId].pszInputPixelType) !=  | 
4681  |  |                         "complex")  | 
4682  |  |                 { | 
4683  |  |                     oDerivedMetadataList.SetNameValue(  | 
4684  |  |                         CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset), | 
4685  |  |                         CPLSPrintf("DERIVED_SUBDATASET:%s:%s", | 
4686  |  |                                    poDDSDesc[derivedId].pszDatasetName,  | 
4687  |  |                                    GetDescription()));  | 
4688  |  |  | 
4689  |  |                     CPLString osDesc(  | 
4690  |  |                         CPLSPrintf("%s from %s", | 
4691  |  |                                    poDDSDesc[derivedId].pszDatasetDescription,  | 
4692  |  |                                    GetDescription()));  | 
4693  |  |                     oDerivedMetadataList.SetNameValue(  | 
4694  |  |                         CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset), | 
4695  |  |                         osDesc.c_str());  | 
4696  |  |  | 
4697  |  |                     nNumDataset++;  | 
4698  |  |                 }  | 
4699  |  |             }  | 
4700  |  |         }  | 
4701  |  |         return oDerivedMetadataList.List();  | 
4702  |  |     }  | 
4703  |  | #endif  | 
4704  |  | 
  | 
4705  | 0  |     return GDALMajorObject::GetMetadata(pszDomain);  | 
4706  | 0  | }  | 
4707  |  |  | 
4708  |  | // clang-format off  | 
4709  |  |  | 
4710  |  | /**  | 
4711  |  |  * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)  | 
4712  |  |  * \brief Set metadata.  | 
4713  |  |  *  | 
4714  |  |  * CAUTION: depending on the format, older values of the updated information  | 
4715  |  |  * might still be found in the file in a "ghost" state, even if no longer  | 
4716  |  |  * accessible through the GDAL API. This is for example the case of the GTiff  | 
4717  |  |  * format (this is not a exhaustive list)  | 
4718  |  |  *  | 
4719  |  |  * The C function GDALSetMetadata() does the same thing as this method.  | 
4720  |  |  *  | 
4721  |  |  * @param papszMetadata the metadata in name=value string list format to  | 
4722  |  |  * apply.  | 
4723  |  |  * @param pszDomain the domain of interest.  Use "" or NULL for the default  | 
4724  |  |  * domain.  | 
4725  |  |  * @return CE_None on success, CE_Failure on failure and CE_Warning if the  | 
4726  |  |  * metadata has been accepted, but is likely not maintained persistently  | 
4727  |  |  * by the underlying object between sessions.  | 
4728  |  |  */  | 
4729  |  |  | 
4730  |  | /**  | 
4731  |  |  * \fn GDALDataset::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)  | 
4732  |  |  * \brief Set single metadata item.  | 
4733  |  |  *  | 
4734  |  |  * CAUTION: depending on the format, older values of the updated information  | 
4735  |  |  * might still be found in the file in a "ghost" state, even if no longer  | 
4736  |  |  * accessible through the GDAL API. This is for example the case of the GTiff  | 
4737  |  |  * format (this is not a exhaustive list)  | 
4738  |  |  *  | 
4739  |  |  * The C function GDALSetMetadataItem() does the same thing as this method.  | 
4740  |  |  *  | 
4741  |  |  * @param pszName the key for the metadata item to fetch.  | 
4742  |  |  * @param pszValue the value to assign to the key.  | 
4743  |  |  * @param pszDomain the domain to set within, use NULL for the default domain.  | 
4744  |  |  *  | 
4745  |  |  * @return CE_None on success, or an error code on failure.  | 
4746  |  |  */  | 
4747  |  |  | 
4748  |  | // clang-format on  | 
4749  |  |  | 
4750  |  | /************************************************************************/  | 
4751  |  | /*                            GetMetadataDomainList()                   */  | 
4752  |  | /************************************************************************/  | 
4753  |  |  | 
4754  |  | char **GDALDataset::GetMetadataDomainList()  | 
4755  | 0  | { | 
4756  | 0  |     char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());  | 
4757  |  |  | 
4758  |  |     // Ensure that we do not duplicate DERIVED domain.  | 
4759  | 0  |     if (GetRasterCount() > 0 &&  | 
4760  | 0  |         CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)  | 
4761  | 0  |     { | 
4762  | 0  |         currentDomainList =  | 
4763  | 0  |             CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");  | 
4764  | 0  |     }  | 
4765  | 0  |     return currentDomainList;  | 
4766  | 0  | }  | 
4767  |  |  | 
4768  |  | /************************************************************************/  | 
4769  |  | /*                            GetDriverName()                           */  | 
4770  |  | /************************************************************************/  | 
4771  |  |  | 
4772  |  | /** Return driver name.  | 
4773  |  |  * @return driver name.  | 
4774  |  |  */  | 
4775  |  | const char *GDALDataset::GetDriverName()  | 
4776  | 0  | { | 
4777  | 0  |     if (poDriver)  | 
4778  | 0  |         return poDriver->GetDescription();  | 
4779  | 0  |     return "";  | 
4780  | 0  | }  | 
4781  |  |  | 
4782  |  | /************************************************************************/  | 
4783  |  | /*                     GDALDatasetReleaseResultSet()                    */  | 
4784  |  | /************************************************************************/  | 
4785  |  |  | 
4786  |  | /**  | 
4787  |  |  \brief Release results of ExecuteSQL().  | 
4788  |  |  | 
4789  |  |  This function should only be used to deallocate OGRLayers resulting from  | 
4790  |  |  an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a  | 
4791  |  |  results set before destroying the GDALDataset may cause errors.  | 
4792  |  |  | 
4793  |  |  This function is the same as the C++ method GDALDataset::ReleaseResultSet()  | 
4794  |  |  | 
4795  |  |  @since GDAL 2.0  | 
4796  |  |  | 
4797  |  |  @param hDS the dataset handle.  | 
4798  |  |  @param hLayer the result of a previous ExecuteSQL() call.  | 
4799  |  |  | 
4800  |  | */  | 
4801  |  | void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)  | 
4802  |  |  | 
4803  | 0  | { | 
4804  | 0  |     VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");  | 
4805  |  |  | 
4806  | 0  | #ifdef OGRAPISPY_ENABLED  | 
4807  | 0  |     if (bOGRAPISpyEnabled)  | 
4808  | 0  |         OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);  | 
4809  | 0  | #endif  | 
4810  |  | 
  | 
4811  | 0  |     GDALDataset::FromHandle(hDS)->ReleaseResultSet(  | 
4812  | 0  |         OGRLayer::FromHandle(hLayer));  | 
4813  | 0  | }  | 
4814  |  |  | 
4815  |  | /************************************************************************/  | 
4816  |  | /*                       GDALDatasetGetLayerCount()                     */  | 
4817  |  | /************************************************************************/  | 
4818  |  |  | 
4819  |  | /**  | 
4820  |  |  \brief Get the number of layers in this dataset.  | 
4821  |  |  | 
4822  |  |  This function is the same as the C++ method GDALDataset::GetLayerCount()  | 
4823  |  |  | 
4824  |  |  @since GDAL 2.0  | 
4825  |  |  | 
4826  |  |  @param hDS the dataset handle.  | 
4827  |  |  @return layer count.  | 
4828  |  | */  | 
4829  |  |  | 
4830  |  | int GDALDatasetGetLayerCount(GDALDatasetH hDS)  | 
4831  |  |  | 
4832  | 0  | { | 
4833  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);  | 
4834  |  |  | 
4835  | 0  | #ifdef OGRAPISPY_ENABLED  | 
4836  | 0  |     if (bOGRAPISpyEnabled)  | 
4837  | 0  |         OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));  | 
4838  | 0  | #endif  | 
4839  |  | 
  | 
4840  | 0  |     return GDALDataset::FromHandle(hDS)->GetLayerCount();  | 
4841  | 0  | }  | 
4842  |  |  | 
4843  |  | /************************************************************************/  | 
4844  |  | /*                        GDALDatasetGetLayer()                         */  | 
4845  |  | /************************************************************************/  | 
4846  |  |  | 
4847  |  | /**  | 
4848  |  |  \brief Fetch a layer by index.  | 
4849  |  |  | 
4850  |  |  The returned layer remains owned by the  | 
4851  |  |  GDALDataset and should not be deleted by the application.  | 
4852  |  |  | 
4853  |  |  This function is the same as the C++ method GDALDataset::GetLayer()  | 
4854  |  |  | 
4855  |  |  @since GDAL 2.0  | 
4856  |  |  | 
4857  |  |  @param hDS the dataset handle.  | 
4858  |  |  @param iLayer a layer number between 0 and GetLayerCount()-1.  | 
4859  |  |  | 
4860  |  |  @return the layer, or NULL if iLayer is out of range or an error occurs.  | 
4861  |  | */  | 
4862  |  |  | 
4863  |  | OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)  | 
4864  |  |  | 
4865  | 0  | { | 
4866  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);  | 
4867  |  |  | 
4868  | 0  |     OGRLayerH hLayer =  | 
4869  | 0  |         OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));  | 
4870  |  | 
  | 
4871  | 0  | #ifdef OGRAPISPY_ENABLED  | 
4872  | 0  |     if (bOGRAPISpyEnabled)  | 
4873  | 0  |         OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);  | 
4874  | 0  | #endif  | 
4875  |  | 
  | 
4876  | 0  |     return hLayer;  | 
4877  | 0  | }  | 
4878  |  |  | 
4879  |  | /************************************************************************/  | 
4880  |  | /*                     GDALDatasetGetLayerByName()                      */  | 
4881  |  | /************************************************************************/  | 
4882  |  |  | 
4883  |  | /**  | 
4884  |  |  \brief Fetch a layer by name.  | 
4885  |  |  | 
4886  |  |  The returned layer remains owned by the  | 
4887  |  |  GDALDataset and should not be deleted by the application.  | 
4888  |  |  | 
4889  |  |  This function is the same as the C++ method GDALDataset::GetLayerByName()  | 
4890  |  |  | 
4891  |  |  @since GDAL 2.0  | 
4892  |  |  | 
4893  |  |  @param hDS the dataset handle.  | 
4894  |  |  @param pszName the layer name of the layer to fetch.  | 
4895  |  |  | 
4896  |  |  @return the layer, or NULL if Layer is not found or an error occurs.  | 
4897  |  | */  | 
4898  |  |  | 
4899  |  | OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)  | 
4900  |  |  | 
4901  | 0  | { | 
4902  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);  | 
4903  |  |  | 
4904  | 0  |     OGRLayerH hLayer = OGRLayer::ToHandle(  | 
4905  | 0  |         GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));  | 
4906  |  | 
  | 
4907  | 0  | #ifdef OGRAPISPY_ENABLED  | 
4908  | 0  |     if (bOGRAPISpyEnabled)  | 
4909  | 0  |         OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);  | 
4910  | 0  | #endif  | 
4911  |  | 
  | 
4912  | 0  |     return hLayer;  | 
4913  | 0  | }  | 
4914  |  |  | 
4915  |  | /************************************************************************/  | 
4916  |  | /*                        GDALDatasetIsLayerPrivate()                   */  | 
4917  |  | /************************************************************************/  | 
4918  |  |  | 
4919  |  | /**  | 
4920  |  |  \brief Returns true if the layer at the specified index is deemed a private or  | 
4921  |  |  system table, or an internal detail only.  | 
4922  |  |  | 
4923  |  |  This function is the same as the C++ method GDALDataset::IsLayerPrivate()  | 
4924  |  |  | 
4925  |  |  @since GDAL 3.4  | 
4926  |  |  | 
4927  |  |  @param hDS the dataset handle.  | 
4928  |  |  @param iLayer a layer number between 0 and GetLayerCount()-1.  | 
4929  |  |  | 
4930  |  |  @return true if the layer is a private or system table.  | 
4931  |  | */  | 
4932  |  |  | 
4933  |  | int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)  | 
4934  |  |  | 
4935  | 0  | { | 
4936  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);  | 
4937  |  |  | 
4938  | 0  |     const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);  | 
4939  |  | 
  | 
4940  | 0  |     return res ? 1 : 0;  | 
4941  | 0  | }  | 
4942  |  |  | 
4943  |  | /************************************************************************/  | 
4944  |  | /*                            GetLayerIndex()                           */  | 
4945  |  | /************************************************************************/  | 
4946  |  |  | 
4947  |  | /**  | 
4948  |  |  \brief Returns the index of the layer specified by name.  | 
4949  |  |  | 
4950  |  |  @since GDAL 3.12  | 
4951  |  |  | 
4952  |  |  @param pszName layer name (not NULL)  | 
4953  |  |  | 
4954  |  |  @return an index >= 0, or -1 if not found.  | 
4955  |  | */  | 
4956  |  |  | 
4957  |  | int GDALDataset::GetLayerIndex(const char *pszName)  | 
4958  | 0  | { | 
4959  | 0  |     const int nLayerCount = GetLayerCount();  | 
4960  | 0  |     int iMatch = -1;  | 
4961  | 0  |     for (int i = 0; i < nLayerCount; ++i)  | 
4962  | 0  |     { | 
4963  | 0  |         if (const auto poLayer = GetLayer(i))  | 
4964  | 0  |         { | 
4965  | 0  |             const char *pszLayerName = poLayer->GetDescription();  | 
4966  | 0  |             if (strcmp(pszName, pszLayerName) == 0)  | 
4967  | 0  |             { | 
4968  | 0  |                 iMatch = i;  | 
4969  | 0  |                 break;  | 
4970  | 0  |             }  | 
4971  | 0  |             else if (EQUAL(pszName, pszLayerName))  | 
4972  | 0  |             { | 
4973  | 0  |                 iMatch = i;  | 
4974  | 0  |             }  | 
4975  | 0  |         }  | 
4976  | 0  |     }  | 
4977  | 0  |     return iMatch;  | 
4978  | 0  | }  | 
4979  |  |  | 
4980  |  | /************************************************************************/  | 
4981  |  | /*                        GDALDatasetDeleteLayer()                      */  | 
4982  |  | /************************************************************************/  | 
4983  |  |  | 
4984  |  | /**  | 
4985  |  |  \brief Delete the indicated layer from the datasource.  | 
4986  |  |  | 
4987  |  |  If this function is supported  | 
4988  |  |  the ODsCDeleteLayer capability will test TRUE on the GDALDataset.  | 
4989  |  |  | 
4990  |  |  This method is the same as the C++ method GDALDataset::DeleteLayer().  | 
4991  |  |  | 
4992  |  |  @since GDAL 2.0  | 
4993  |  |  | 
4994  |  |  @param hDS the dataset handle.  | 
4995  |  |  @param iLayer the index of the layer to delete.  | 
4996  |  |  | 
4997  |  |  @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting  | 
4998  |  |  layers is not supported for this datasource.  | 
4999  |  |  | 
5000  |  | */  | 
5001  |  | OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)  | 
5002  |  |  | 
5003  | 0  | { | 
5004  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);  | 
5005  |  |  | 
5006  | 0  | #ifdef OGRAPISPY_ENABLED  | 
5007  | 0  |     if (bOGRAPISpyEnabled)  | 
5008  | 0  |         OGRAPISpy_DS_DeleteLayer(hDS, iLayer);  | 
5009  | 0  | #endif  | 
5010  |  | 
  | 
5011  | 0  |     return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);  | 
5012  | 0  | }  | 
5013  |  |  | 
5014  |  | /************************************************************************/  | 
5015  |  | /*                            CreateLayer()                             */  | 
5016  |  | /************************************************************************/  | 
5017  |  |  | 
5018  |  | /**  | 
5019  |  | \brief This method attempts to create a new layer on the dataset with the  | 
5020  |  | indicated name, coordinate system, geometry type.  | 
5021  |  |  | 
5022  |  | The papszOptions argument  | 
5023  |  | can be used to control driver specific creation options.  These options are  | 
5024  |  | normally documented in the format specific documentation.  | 
5025  |  | That function will try to validate the creation option list passed to the  | 
5026  |  | driver with the GDALValidateCreationOptions() method. This check can be  | 
5027  |  | disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set  | 
5028  |  | to NO.  | 
5029  |  |  | 
5030  |  | Drivers should extend the ICreateLayer() method and not  | 
5031  |  | CreateLayer(). CreateLayer() adds validation of layer creation options, before  | 
5032  |  | delegating the actual work to ICreateLayer().  | 
5033  |  |  | 
5034  |  | This method is the same as the C function GDALDatasetCreateLayer() and the  | 
5035  |  | deprecated OGR_DS_CreateLayer().  | 
5036  |  |  | 
5037  |  | Example:  | 
5038  |  |  | 
5039  |  | \code{.cpp} | 
5040  |  | #include "gdal.h"  | 
5041  |  | #include "cpl_string.h"  | 
5042  |  |  | 
5043  |  | ...  | 
5044  |  |  | 
5045  |  |         OGRLayer *poLayer;  | 
5046  |  |         char     **papszOptions;  | 
5047  |  |  | 
5048  |  |         if( !poDS->TestCapability( ODsCCreateLayer ) )  | 
5049  |  |         { | 
5050  |  |         ...  | 
5051  |  |         }  | 
5052  |  |  | 
5053  |  |         papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );  | 
5054  |  |         poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,  | 
5055  |  |                                      papszOptions );  | 
5056  |  |         CSLDestroy( papszOptions );  | 
5057  |  |  | 
5058  |  |         if( poLayer == NULL )  | 
5059  |  |         { | 
5060  |  |             ...  | 
5061  |  |         }  | 
5062  |  | \endcode  | 
5063  |  |  | 
5064  |  | @param pszName the name for the new layer.  This should ideally not  | 
5065  |  | match any existing layer on the datasource.  | 
5066  |  | @param poSpatialRef the coordinate system to use for the new layer, or NULL if  | 
5067  |  | no coordinate system is available.  | 
5068  |  | @param eGType the geometry type for the layer.  Use wkbUnknown if there  | 
5069  |  | are no constraints on the types geometry to be written.  | 
5070  |  | @param papszOptions a StringList of name=value options.  Options are driver  | 
5071  |  | specific.  | 
5072  |  |  | 
5073  |  | @return NULL is returned on failure, or a new OGRLayer handle on success.  | 
5074  |  |  | 
5075  |  | */  | 
5076  |  |  | 
5077  |  | OGRLayer *GDALDataset::CreateLayer(const char *pszName,  | 
5078  |  |                                    const OGRSpatialReference *poSpatialRef,  | 
5079  |  |                                    OGRwkbGeometryType eGType,  | 
5080  |  |                                    CSLConstList papszOptions)  | 
5081  |  |  | 
5082  | 0  | { | 
5083  | 0  |     if (eGType == wkbNone)  | 
5084  | 0  |     { | 
5085  | 0  |         return CreateLayer(pszName, nullptr, papszOptions);  | 
5086  | 0  |     }  | 
5087  | 0  |     else  | 
5088  | 0  |     { | 
5089  | 0  |         OGRGeomFieldDefn oGeomFieldDefn("", eGType); | 
5090  | 0  |         oGeomFieldDefn.SetSpatialRef(poSpatialRef);  | 
5091  | 0  |         return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);  | 
5092  | 0  |     }  | 
5093  | 0  | }  | 
5094  |  |  | 
5095  |  | /**  | 
5096  |  | \brief This method attempts to create a new layer on the dataset with the  | 
5097  |  | indicated name and geometry field definition.  | 
5098  |  |  | 
5099  |  | When poGeomFieldDefn is not null, most drivers should honor  | 
5100  |  | poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().  | 
5101  |  | Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the  | 
5102  |  | GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor  | 
5103  |  | poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are  | 
5104  |  | very few currently.  | 
5105  |  |  | 
5106  |  | Note that even if a geometry coordinate precision is set and a driver honors the  | 
5107  |  | GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to  | 
5108  |  | OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible  | 
5109  |  | with the coordinate precision. That is they are assumed to be valid once their  | 
5110  |  | coordinates are rounded to it. If it might not be the case, the user may set  | 
5111  |  | the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()  | 
5112  |  | or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on  | 
5113  |  | the passed geometries.  | 
5114  |  |  | 
5115  |  | The papszOptions argument  | 
5116  |  | can be used to control driver specific creation options. These options are  | 
5117  |  | normally documented in the format specific documentation.  | 
5118  |  | This function will try to validate the creation option list passed to the  | 
5119  |  | driver with the GDALValidateCreationOptions() method. This check can be  | 
5120  |  | disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set  | 
5121  |  | to NO.  | 
5122  |  |  | 
5123  |  | Drivers should extend the ICreateLayer() method and not  | 
5124  |  | CreateLayer(). CreateLayer() adds validation of layer creation options, before  | 
5125  |  | delegating the actual work to ICreateLayer().  | 
5126  |  |  | 
5127  |  | This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().  | 
5128  |  |  | 
5129  |  | @param pszName the name for the new layer.  This should ideally not  | 
5130  |  | match any existing layer on the datasource.  | 
5131  |  | @param poGeomFieldDefn the geometry field definition to use for the new layer,  | 
5132  |  | or NULL if there is no geometry field.  | 
5133  |  | @param papszOptions a StringList of name=value options.  Options are driver  | 
5134  |  | specific.  | 
5135  |  |  | 
5136  |  | @return NULL is returned on failure, or a new OGRLayer handle on success.  | 
5137  |  | @since 3.9  | 
5138  |  |  | 
5139  |  | */  | 
5140  |  |  | 
5141  |  | OGRLayer *GDALDataset::CreateLayer(const char *pszName,  | 
5142  |  |                                    const OGRGeomFieldDefn *poGeomFieldDefn,  | 
5143  |  |                                    CSLConstList papszOptions)  | 
5144  |  |  | 
5145  | 0  | { | 
5146  | 0  |     if (CPLTestBool(  | 
5147  | 0  |             CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES"))) | 
5148  | 0  |     { | 
5149  | 0  |         ValidateLayerCreationOptions(papszOptions);  | 
5150  | 0  |     }  | 
5151  |  | 
  | 
5152  | 0  |     OGRLayer *poLayer;  | 
5153  | 0  |     if (poGeomFieldDefn)  | 
5154  | 0  |     { | 
5155  | 0  |         OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);  | 
5156  | 0  |         if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&  | 
5157  | 0  |             !TestCapability(ODsCCurveGeometries))  | 
5158  | 0  |         { | 
5159  | 0  |             oGeomFieldDefn.SetType(  | 
5160  | 0  |                 OGR_GT_GetLinear(poGeomFieldDefn->GetType()));  | 
5161  | 0  |         }  | 
5162  |  | 
  | 
5163  | 0  |         poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);  | 
5164  | 0  |     }  | 
5165  | 0  |     else  | 
5166  | 0  |     { | 
5167  | 0  |         poLayer = ICreateLayer(pszName, nullptr, papszOptions);  | 
5168  | 0  |     }  | 
5169  | 0  | #ifdef DEBUG  | 
5170  | 0  |     if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&  | 
5171  | 0  |         !poLayer->TestCapability(OLCCurveGeometries))  | 
5172  | 0  |     { | 
5173  | 0  |         CPLError(CE_Warning, CPLE_AppDefined,  | 
5174  | 0  |                  "Inconsistent driver: Layer geometry type is non-linear, but "  | 
5175  | 0  |                  "TestCapability(OLCCurveGeometries) returns FALSE.");  | 
5176  | 0  |     }  | 
5177  | 0  | #endif  | 
5178  |  | 
  | 
5179  | 0  |     return poLayer;  | 
5180  | 0  | }  | 
5181  |  |  | 
5182  |  | //! @cond Doxygen_Suppress  | 
5183  |  |  | 
5184  |  | // Technical override to avoid ambiguous choice between the old and new  | 
5185  |  | // new CreateLayer() signatures.  | 
5186  |  | OGRLayer *GDALDataset::CreateLayer(const char *pszName)  | 
5187  | 0  | { | 
5188  | 0  |     OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown); | 
5189  | 0  |     return CreateLayer(pszName, &oGeomFieldDefn, nullptr);  | 
5190  | 0  | }  | 
5191  |  |  | 
5192  |  | // Technical override to avoid ambiguous choice between the old and new  | 
5193  |  | // new CreateLayer() signatures.  | 
5194  |  | OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)  | 
5195  | 0  | { | 
5196  | 0  |     OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown); | 
5197  | 0  |     return CreateLayer(pszName, &oGeomFieldDefn, nullptr);  | 
5198  | 0  | }  | 
5199  |  |  | 
5200  |  | //!@endcond  | 
5201  |  |  | 
5202  |  | /************************************************************************/  | 
5203  |  | /*                         GDALDatasetCreateLayer()                     */  | 
5204  |  | /************************************************************************/  | 
5205  |  |  | 
5206  |  | /**  | 
5207  |  | \brief This function attempts to create a new layer on the dataset with the  | 
5208  |  | indicated name, coordinate system, geometry type.  | 
5209  |  |  | 
5210  |  | The papszOptions argument can be used to control driver specific creation  | 
5211  |  | options.  These options are normally documented in the format specific  | 
5212  |  | documentation.  | 
5213  |  |  | 
5214  |  | This method is the same as the C++ method GDALDataset::CreateLayer().  | 
5215  |  |  | 
5216  |  | Example:  | 
5217  |  |  | 
5218  |  | \code{.c} | 
5219  |  | #include "gdal.h"  | 
5220  |  | #include "cpl_string.h"  | 
5221  |  |  | 
5222  |  | ...  | 
5223  |  |  | 
5224  |  |         OGRLayerH  hLayer;  | 
5225  |  |         char     **papszOptions;  | 
5226  |  |  | 
5227  |  |         if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )  | 
5228  |  |         { | 
5229  |  |         ...  | 
5230  |  |         }  | 
5231  |  |  | 
5232  |  |         papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );  | 
5233  |  |         hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,  | 
5234  |  |                                          papszOptions );  | 
5235  |  |         CSLDestroy( papszOptions );  | 
5236  |  |  | 
5237  |  |         if( hLayer == NULL )  | 
5238  |  |         { | 
5239  |  |             ...  | 
5240  |  |         }  | 
5241  |  | \endcode  | 
5242  |  |  | 
5243  |  | @since GDAL 2.0  | 
5244  |  |  | 
5245  |  | @param hDS the dataset handle  | 
5246  |  | @param pszName the name for the new layer.  This should ideally not  | 
5247  |  | match any existing layer on the datasource.  | 
5248  |  | @param hSpatialRef the coordinate system to use for the new layer, or NULL if  | 
5249  |  | no coordinate system is available.  | 
5250  |  | @param eGType the geometry type for the layer.  Use wkbUnknown if there  | 
5251  |  | are no constraints on the types geometry to be written.  | 
5252  |  | @param papszOptions a StringList of name=value options.  Options are driver  | 
5253  |  | specific.  | 
5254  |  |  | 
5255  |  | @return NULL is returned on failure, or a new OGRLayer handle on success.  | 
5256  |  |  | 
5257  |  | */  | 
5258  |  |  | 
5259  |  | OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,  | 
5260  |  |                                  OGRSpatialReferenceH hSpatialRef,  | 
5261  |  |                                  OGRwkbGeometryType eGType,  | 
5262  |  |                                  CSLConstList papszOptions)  | 
5263  |  |  | 
5264  | 0  | { | 
5265  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);  | 
5266  |  |  | 
5267  | 0  |     if (pszName == nullptr)  | 
5268  | 0  |     { | 
5269  | 0  |         CPLError(CE_Failure, CPLE_ObjectNull,  | 
5270  | 0  |                  "Name was NULL in GDALDatasetCreateLayer");  | 
5271  | 0  |         return nullptr;  | 
5272  | 0  |     }  | 
5273  |  |  | 
5274  | 0  |     OGRLayerH hLayer =  | 
5275  | 0  |         OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(  | 
5276  | 0  |             pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,  | 
5277  | 0  |             const_cast<char **>(papszOptions)));  | 
5278  |  | 
  | 
5279  | 0  | #ifdef OGRAPISPY_ENABLED  | 
5280  | 0  |     if (bOGRAPISpyEnabled)  | 
5281  | 0  |         OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,  | 
5282  | 0  |                                  const_cast<char **>(papszOptions), hLayer);  | 
5283  | 0  | #endif  | 
5284  |  | 
  | 
5285  | 0  |     return hLayer;  | 
5286  | 0  | }  | 
5287  |  |  | 
5288  |  | /************************************************************************/  | 
5289  |  | /*                 GDALDatasetCreateLayerFromGeomFieldDefn()            */  | 
5290  |  | /************************************************************************/  | 
5291  |  |  | 
5292  |  | /**  | 
5293  |  | \brief This function attempts to create a new layer on the dataset with the  | 
5294  |  | indicated name and geometry field.  | 
5295  |  |  | 
5296  |  | When poGeomFieldDefn is not null, most drivers should honor  | 
5297  |  | poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().  | 
5298  |  | Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the  | 
5299  |  | GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor  | 
5300  |  | poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are  | 
5301  |  | very few currently.  | 
5302  |  |  | 
5303  |  | Note that even if a geometry coordinate precision is set and a driver honors the  | 
5304  |  | GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to  | 
5305  |  | OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible  | 
5306  |  | with the coordinate precision. That is they are assumed to be valid once their  | 
5307  |  | coordinates are rounded to it. If it might not be the case, the user may set  | 
5308  |  | the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()  | 
5309  |  | or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on  | 
5310  |  | the passed geometries.  | 
5311  |  |  | 
5312  |  | The papszOptions argument can be used to control driver specific creation  | 
5313  |  | options.  These options are normally documented in the format specific  | 
5314  |  | documentation.  | 
5315  |  |  | 
5316  |  | This method is the same as the C++ method GDALDataset::CreateLayer().  | 
5317  |  |  | 
5318  |  | @param hDS the dataset handle  | 
5319  |  | @param pszName the name for the new layer.  This should ideally not  | 
5320  |  | match any existing layer on the datasource.  | 
5321  |  | @param hGeomFieldDefn the geometry field definition. May be NULL to indicate  | 
5322  |  | a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()  | 
5323  |  | for drivers supporting that interface).  | 
5324  |  | @param papszOptions a StringList of name=value options.  Options are driver  | 
5325  |  | specific.  | 
5326  |  |  | 
5327  |  | @return NULL is returned on failure, or a new OGRLayer handle on success.  | 
5328  |  |  | 
5329  |  | @since GDAL 3.9  | 
5330  |  |  | 
5331  |  | */  | 
5332  |  |  | 
5333  |  | OGRLayerH  | 
5334  |  | GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,  | 
5335  |  |                                         OGRGeomFieldDefnH hGeomFieldDefn,  | 
5336  |  |                                         CSLConstList papszOptions)  | 
5337  |  |  | 
5338  | 0  | { | 
5339  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);  | 
5340  |  |  | 
5341  | 0  |     if (!pszName)  | 
5342  | 0  |     { | 
5343  | 0  |         CPLError(CE_Failure, CPLE_ObjectNull,  | 
5344  | 0  |                  "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");  | 
5345  | 0  |         return nullptr;  | 
5346  | 0  |     }  | 
5347  |  |  | 
5348  | 0  |     OGRLayerH hLayer =  | 
5349  | 0  |         OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(  | 
5350  | 0  |             pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),  | 
5351  | 0  |             papszOptions));  | 
5352  | 0  |     return hLayer;  | 
5353  | 0  | }  | 
5354  |  |  | 
5355  |  | /************************************************************************/  | 
5356  |  | /*                         GDALDatasetCopyLayer()                       */  | 
5357  |  | /************************************************************************/  | 
5358  |  |  | 
5359  |  | /**  | 
5360  |  |  \brief Duplicate an existing layer.  | 
5361  |  |  | 
5362  |  |  This function creates a new layer, duplicate the field definitions of the  | 
5363  |  |  source layer and then duplicate each features of the source layer.  | 
5364  |  |  The papszOptions argument  | 
5365  |  |  can be used to control driver specific creation options.  These options are  | 
5366  |  |  normally documented in the format specific documentation.  | 
5367  |  |  The source layer may come from another dataset.  | 
5368  |  |  | 
5369  |  |  This method is the same as the C++ method GDALDataset::CopyLayer()  | 
5370  |  |  | 
5371  |  |  @since GDAL 2.0  | 
5372  |  |  | 
5373  |  |  @param hDS the dataset handle.  | 
5374  |  |  @param hSrcLayer source layer.  | 
5375  |  |  @param pszNewName the name of the layer to create.  | 
5376  |  |  @param papszOptions a StringList of name=value options.  Options are driver  | 
5377  |  |                      specific.  | 
5378  |  |  | 
5379  |  |  @return a handle to the layer, or NULL if an error occurs.  | 
5380  |  | */  | 
5381  |  | OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,  | 
5382  |  |                                const char *pszNewName,  | 
5383  |  |                                CSLConstList papszOptions)  | 
5384  |  |  | 
5385  | 0  | { | 
5386  | 0  |     VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);  | 
5387  | 0  |     VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);  | 
5388  | 0  |     VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);  | 
5389  |  |  | 
5390  | 0  |     return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(  | 
5391  | 0  |         OGRLayer::FromHandle(hSrcLayer), pszNewName,  | 
5392  | 0  |         const_cast<char **>(papszOptions)));  | 
5393  | 0  | }  | 
5394  |  |  | 
5395  |  | /************************************************************************/  | 
5396  |  | /*                        GDALDatasetExecuteSQL()                       */  | 
5397  |  | /************************************************************************/  | 
5398  |  |  | 
5399  |  | /**  | 
5400  |  |  \brief Execute an SQL statement against the data store.  | 
5401  |  |  | 
5402  |  |  The result of an SQL query is either NULL for statements that are in error,  | 
5403  |  |  or that have no results set, or an OGRLayer pointer representing a results  | 
5404  |  |  set from the query.  Note that this OGRLayer is in addition to the layers  | 
5405  |  |  in the data store and must be destroyed with  | 
5406  |  |  ReleaseResultSet() before the dataset is closed  | 
5407  |  |  (destroyed).  | 
5408  |  |  | 
5409  |  |  This method is the same as the C++ method GDALDataset::ExecuteSQL()  | 
5410  |  |  | 
5411  |  |  For more information on the SQL dialect supported internally by OGR  | 
5412  |  |  review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>  | 
5413  |  |  document.  Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through  | 
5414  |  |  to the underlying RDBMS.  | 
5415  |  |  | 
5416  |  |  Starting with OGR 1.10, the <a  | 
5417  |  |  href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can  | 
5418  |  |  also be used.  | 
5419  |  |  | 
5420  |  |  @since GDAL 2.0  | 
5421  |  |  | 
5422  |  |  @param hDS the dataset handle.  | 
5423  |  |  @param pszStatement the SQL statement to execute.  | 
5424  |  |  @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.  | 
5425  |  |  | 
5426  |  |  @param pszDialect allows control of the statement dialect. If set to NULL, the  | 
5427  |  |  OGR SQL engine will be used, except for RDBMS drivers that will use their  | 
5428  |  |  dedicated SQL engine, unless OGRSQL is explicitly passed as the  | 
5429  |  |  dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.  | 
5430  |  |  | 
5431  |  |  @return an OGRLayer containing the results of the query.  Deallocate with  | 
5432  |  |  GDALDatasetReleaseResultSet().  | 
5433  |  |  | 
5434  |  | */  | 
5435  |  |  | 
5436  |  | OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,  | 
5437  |  |                                 OGRGeometryH hSpatialFilter,  | 
5438  |  |                                 const char *pszDialect)  | 
5439  |  |  | 
5440  | 0  | { | 
5441  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);  | 
5442  |  |  | 
5443  | 0  |     OGRLayerH hLayer =  | 
5444  | 0  |         OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(  | 
5445  | 0  |             pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));  | 
5446  |  | 
  | 
5447  | 0  | #ifdef OGRAPISPY_ENABLED  | 
5448  | 0  |     if (bOGRAPISpyEnabled)  | 
5449  | 0  |         OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,  | 
5450  | 0  |                                 hLayer);  | 
5451  | 0  | #endif  | 
5452  |  | 
  | 
5453  | 0  |     return hLayer;  | 
5454  | 0  | }  | 
5455  |  |  | 
5456  |  | /************************************************************************/  | 
5457  |  | /*                        GDALDatasetAbortSQL()                         */  | 
5458  |  | /************************************************************************/  | 
5459  |  |  | 
5460  |  | /**  | 
5461  |  |  \brief Abort any SQL statement running in the data store.  | 
5462  |  |  | 
5463  |  |  This function can be safely called from any thread (pending that the dataset  | 
5464  |  |  object is still alive). Driver implementations will make sure that it can be  | 
5465  |  |  called in a thread-safe way.  | 
5466  |  |  | 
5467  |  |  This might not be implemented by all drivers. At time of writing, only SQLite,  | 
5468  |  |  GPKG and PG drivers implement it  | 
5469  |  |  | 
5470  |  |  This method is the same as the C++ method GDALDataset::AbortSQL()  | 
5471  |  |  | 
5472  |  |  @since GDAL 3.2.0  | 
5473  |  |  | 
5474  |  |  @param hDS the dataset handle.  | 
5475  |  |  | 
5476  |  |  @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL  | 
5477  |  |  is not supported for this datasource. .  | 
5478  |  |  | 
5479  |  | */  | 
5480  |  |  | 
5481  |  | OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)  | 
5482  |  |  | 
5483  | 0  | { | 
5484  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);  | 
5485  | 0  |     return GDALDataset::FromHandle(hDS)->AbortSQL();  | 
5486  | 0  | }  | 
5487  |  |  | 
5488  |  | /************************************************************************/  | 
5489  |  | /*                      GDALDatasetGetStyleTable()                      */  | 
5490  |  | /************************************************************************/  | 
5491  |  |  | 
5492  |  | /**  | 
5493  |  |  \brief Returns dataset style table.  | 
5494  |  |  | 
5495  |  |  This function is the same as the C++ method GDALDataset::GetStyleTable()  | 
5496  |  |  | 
5497  |  |  @since GDAL 2.0  | 
5498  |  |  | 
5499  |  |  @param hDS the dataset handle  | 
5500  |  |  @return handle to a style table which should not be modified or freed by the  | 
5501  |  |  caller.  | 
5502  |  | */  | 
5503  |  |  | 
5504  |  | OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)  | 
5505  |  |  | 
5506  | 0  | { | 
5507  | 0  |     VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);  | 
5508  |  |  | 
5509  | 0  |     return reinterpret_cast<OGRStyleTableH>(  | 
5510  | 0  |         GDALDataset::FromHandle(hDS)->GetStyleTable());  | 
5511  | 0  | }  | 
5512  |  |  | 
5513  |  | /************************************************************************/  | 
5514  |  | /*                    GDALDatasetSetStyleTableDirectly()                */  | 
5515  |  | /************************************************************************/  | 
5516  |  |  | 
5517  |  | /**  | 
5518  |  |  \brief Set dataset style table.  | 
5519  |  |  | 
5520  |  |  This function operate exactly as GDALDatasetSetStyleTable() except that it  | 
5521  |  |  assumes ownership of the passed table.  | 
5522  |  |  | 
5523  |  |  This function is the same as the C++ method  | 
5524  |  |  GDALDataset::SetStyleTableDirectly()  | 
5525  |  |  | 
5526  |  |  @since GDAL 2.0  | 
5527  |  |  | 
5528  |  |  @param hDS the dataset handle  | 
5529  |  |  @param hStyleTable style table handle to set  | 
5530  |  |  | 
5531  |  | */  | 
5532  |  |  | 
5533  |  | void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,  | 
5534  |  |                                       OGRStyleTableH hStyleTable)  | 
5535  |  |  | 
5536  | 0  | { | 
5537  | 0  |     VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");  | 
5538  |  |  | 
5539  | 0  |     GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(  | 
5540  | 0  |         reinterpret_cast<OGRStyleTable *>(hStyleTable));  | 
5541  | 0  | }  | 
5542  |  |  | 
5543  |  | /************************************************************************/  | 
5544  |  | /*                     GDALDatasetSetStyleTable()                       */  | 
5545  |  | /************************************************************************/  | 
5546  |  |  | 
5547  |  | /**  | 
5548  |  |  \brief Set dataset style table.  | 
5549  |  |  | 
5550  |  |  This function operate exactly as GDALDatasetSetStyleTableDirectly() except that  | 
5551  |  |  it assumes ownership of the passed table.  | 
5552  |  |  | 
5553  |  |  This function is the same as the C++ method GDALDataset::SetStyleTable()  | 
5554  |  |  | 
5555  |  |  @since GDAL 2.0  | 
5556  |  |  | 
5557  |  |  @param hDS the dataset handle  | 
5558  |  |  @param hStyleTable style table handle to set  | 
5559  |  |  | 
5560  |  | */  | 
5561  |  |  | 
5562  |  | void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)  | 
5563  |  |  | 
5564  | 0  | { | 
5565  | 0  |     VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");  | 
5566  | 0  |     VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");  | 
5567  |  |  | 
5568  | 0  |     GDALDataset::FromHandle(hDS)->SetStyleTable(  | 
5569  | 0  |         reinterpret_cast<OGRStyleTable *>(hStyleTable));  | 
5570  | 0  | }  | 
5571  |  |  | 
5572  |  | /************************************************************************/  | 
5573  |  | /*                    ValidateLayerCreationOptions()                    */  | 
5574  |  | /************************************************************************/  | 
5575  |  |  | 
5576  |  | //! @cond Doxygen_Suppress  | 
5577  |  | int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)  | 
5578  | 0  | { | 
5579  | 0  |     const char *pszOptionList =  | 
5580  | 0  |         GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);  | 
5581  | 0  |     if (pszOptionList == nullptr && poDriver != nullptr)  | 
5582  | 0  |     { | 
5583  | 0  |         pszOptionList =  | 
5584  | 0  |             poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);  | 
5585  | 0  |     }  | 
5586  | 0  |     CPLString osDataset;  | 
5587  | 0  |     osDataset.Printf("dataset %s", GetDescription()); | 
5588  | 0  |     return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",  | 
5589  | 0  |                                osDataset);  | 
5590  | 0  | }  | 
5591  |  |  | 
5592  |  | //! @endcond  | 
5593  |  |  | 
5594  |  | /************************************************************************/  | 
5595  |  | /*                              Release()                               */  | 
5596  |  | /************************************************************************/  | 
5597  |  |  | 
5598  |  | /**  | 
5599  |  | \brief Drop a reference to this dataset, and if the reference count drops to one  | 
5600  |  | close (destroy) the dataset.  | 
5601  |  |  | 
5602  |  | This method is the same as the C function OGRReleaseDataSource().  | 
5603  |  |  | 
5604  |  | @deprecated. In GDAL 2, use GDALClose() instead  | 
5605  |  |  | 
5606  |  | @return OGRERR_NONE on success or an error code.  | 
5607  |  | */  | 
5608  |  |  | 
5609  |  | OGRErr GDALDataset::Release()  | 
5610  |  |  | 
5611  | 0  | { | 
5612  | 0  |     ReleaseRef();  | 
5613  | 0  |     return OGRERR_NONE;  | 
5614  | 0  | }  | 
5615  |  |  | 
5616  |  | /************************************************************************/  | 
5617  |  | /*                            GetRefCount()                             */  | 
5618  |  | /************************************************************************/  | 
5619  |  |  | 
5620  |  | /**  | 
5621  |  | \brief Fetch reference count.  | 
5622  |  |  | 
5623  |  | This method is the same as the C function OGR_DS_GetRefCount().  | 
5624  |  |  | 
5625  |  | In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
5626  |  |  | 
5627  |  | @return the current reference count for the datasource object itself.  | 
5628  |  | */  | 
5629  |  |  | 
5630  |  | int GDALDataset::GetRefCount() const  | 
5631  | 0  | { | 
5632  | 0  |     return nRefCount;  | 
5633  | 0  | }  | 
5634  |  |  | 
5635  |  | /************************************************************************/  | 
5636  |  | /*                         GetSummaryRefCount()                         */  | 
5637  |  | /************************************************************************/  | 
5638  |  |  | 
5639  |  | /**  | 
5640  |  | \brief Fetch reference count of datasource and all owned layers.  | 
5641  |  |  | 
5642  |  | This method is the same as the C function  OGR_DS_GetSummaryRefCount().  | 
5643  |  |  | 
5644  |  | In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
5645  |  |  | 
5646  |  | @deprecated  | 
5647  |  |  | 
5648  |  | @return the current summary reference count for the datasource and its layers.  | 
5649  |  | */  | 
5650  |  |  | 
5651  |  | int GDALDataset::GetSummaryRefCount() const  | 
5652  |  |  | 
5653  | 0  | { | 
5654  | 0  |     CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);  | 
5655  | 0  |     int nSummaryCount = nRefCount;  | 
5656  | 0  |     GDALDataset *poUseThis = const_cast<GDALDataset *>(this);  | 
5657  |  | 
  | 
5658  | 0  |     for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)  | 
5659  | 0  |         nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();  | 
5660  |  | 
  | 
5661  | 0  |     return nSummaryCount;  | 
5662  | 0  | }  | 
5663  |  |  | 
5664  |  | /************************************************************************/  | 
5665  |  | /*                           ICreateLayer()                             */  | 
5666  |  | /************************************************************************/  | 
5667  |  |  | 
5668  |  | /**  | 
5669  |  |  \brief This method attempts to create a new layer on the dataset with the  | 
5670  |  |  indicated name, coordinate system, geometry type.  | 
5671  |  |  | 
5672  |  |  This method is reserved to implementation by drivers.  | 
5673  |  |  | 
5674  |  |  The papszOptions argument can be used to control driver specific creation  | 
5675  |  |  options.  These options are normally documented in the format specific  | 
5676  |  |  documentation.  | 
5677  |  |  | 
5678  |  |  @param pszName the name for the new layer.  This should ideally not  | 
5679  |  |  match any existing layer on the datasource.  | 
5680  |  |  @param poGeomFieldDefn the geometry field definition to use for the new layer,  | 
5681  |  |  or NULL if there is no geometry field.  | 
5682  |  |  @param papszOptions a StringList of name=value options.  Options are driver  | 
5683  |  |  specific.  | 
5684  |  |  | 
5685  |  |  @return NULL is returned on failure, or a new OGRLayer handle on success.  | 
5686  |  |  | 
5687  |  |  @since GDAL 2.0 (prototype modified in 3.9)  | 
5688  |  | */  | 
5689  |  |  | 
5690  |  | OGRLayer *  | 
5691  |  | GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,  | 
5692  |  |                           CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,  | 
5693  |  |                           CPL_UNUSED CSLConstList papszOptions)  | 
5694  |  |  | 
5695  | 0  | { | 
5696  | 0  |     CPLError(CE_Failure, CPLE_NotSupported,  | 
5697  | 0  |              "CreateLayer() not supported by this dataset.");  | 
5698  |  | 
  | 
5699  | 0  |     return nullptr;  | 
5700  | 0  | }  | 
5701  |  |  | 
5702  |  | /************************************************************************/  | 
5703  |  | /*                             CopyLayer()                              */  | 
5704  |  | /************************************************************************/  | 
5705  |  |  | 
5706  |  | /**  | 
5707  |  |  \brief Duplicate an existing layer.  | 
5708  |  |  | 
5709  |  |  This method creates a new layer, duplicate the field definitions of the  | 
5710  |  |  source layer and then duplicate each features of the source layer.  | 
5711  |  |  The papszOptions argument  | 
5712  |  |  can be used to control driver specific creation options.  These options are  | 
5713  |  |  normally documented in the format specific documentation.  | 
5714  |  |  The source layer may come from another dataset.  | 
5715  |  |  | 
5716  |  |  This method is the same as the C function GDALDatasetCopyLayer() and the  | 
5717  |  |  deprecated OGR_DS_CopyLayer().  | 
5718  |  |  | 
5719  |  |  In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
5720  |  |  | 
5721  |  |  @param poSrcLayer source layer.  | 
5722  |  |  @param pszNewName the name of the layer to create.  | 
5723  |  |  @param papszOptions a StringList of name=value options.  Options are driver  | 
5724  |  |                      specific. There is a common option to set output layer  | 
5725  |  |                      spatial reference: DST_SRSWKT. The option should be in  | 
5726  |  |                      WKT format. Starting with GDAL 3.7, the common option  | 
5727  |  |                      COPY_MD can be set to NO to prevent the default copying  | 
5728  |  |                      of the metadata from the source layer to the target layer.  | 
5729  |  |  | 
5730  |  |  @return a handle to the layer, or NULL if an error occurs.  | 
5731  |  | */  | 
5732  |  |  | 
5733  |  | OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,  | 
5734  |  |                                  char **papszOptions)  | 
5735  |  |  | 
5736  | 0  | { | 
5737  |  |     /* -------------------------------------------------------------------- */  | 
5738  |  |     /*      Create the layer.                                               */  | 
5739  |  |     /* -------------------------------------------------------------------- */  | 
5740  | 0  |     if (!TestCapability(ODsCCreateLayer))  | 
5741  | 0  |     { | 
5742  | 0  |         CPLError(CE_Failure, CPLE_NotSupported,  | 
5743  | 0  |                  "This datasource does not support creation of layers.");  | 
5744  | 0  |         return nullptr;  | 
5745  | 0  |     }  | 
5746  |  |  | 
5747  | 0  |     const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");  | 
5748  | 0  |     OGRSpatialReference oDstSpaRef(pszSRSWKT);  | 
5749  | 0  |     oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);  | 
5750  | 0  |     OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();  | 
5751  | 0  |     OGRLayer *poDstLayer = nullptr;  | 
5752  |  | 
  | 
5753  | 0  |     CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));  | 
5754  | 0  |     aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr); | 
5755  | 0  |     aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr); | 
5756  |  | 
  | 
5757  | 0  |     CPLErrorReset();  | 
5758  | 0  |     const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();  | 
5759  | 0  |     if (nSrcGeomFieldCount == 1)  | 
5760  | 0  |     { | 
5761  | 0  |         OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));  | 
5762  | 0  |         if (pszSRSWKT)  | 
5763  | 0  |             oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);  | 
5764  | 0  |         poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,  | 
5765  | 0  |                                   aosCleanedUpOptions.List());  | 
5766  | 0  |     }  | 
5767  | 0  |     else  | 
5768  | 0  |     { | 
5769  | 0  |         poDstLayer =  | 
5770  | 0  |             ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());  | 
5771  | 0  |     }  | 
5772  |  | 
  | 
5773  | 0  |     if (poDstLayer == nullptr)  | 
5774  | 0  |         return nullptr;  | 
5775  |  |  | 
5776  | 0  |     if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))  | 
5777  | 0  |     { | 
5778  | 0  |         char **papszMD = poSrcLayer->GetMetadata();  | 
5779  | 0  |         if (papszMD)  | 
5780  | 0  |             poDstLayer->SetMetadata(papszMD);  | 
5781  | 0  |     }  | 
5782  |  |  | 
5783  |  |     /* -------------------------------------------------------------------- */  | 
5784  |  |     /*      Add fields.  Default to copy all fields, and make sure to       */  | 
5785  |  |     /*      establish a mapping between indices, rather than names, in      */  | 
5786  |  |     /*      case the target datasource has altered it (e.g. Shapefile       */  | 
5787  |  |     /*      limited to 10 char field names).                                */  | 
5788  |  |     /* -------------------------------------------------------------------- */  | 
5789  | 0  |     const int nSrcFieldCount = poSrcDefn->GetFieldCount();  | 
5790  |  |  | 
5791  |  |     // Initialize the index-to-index map to -1's.  | 
5792  | 0  |     std::vector<int> anMap(nSrcFieldCount, -1);  | 
5793  |  |  | 
5794  |  |     // Caution: At the time of writing, the MapInfo driver  | 
5795  |  |     // returns NULL until a field has been added.  | 
5796  | 0  |     OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();  | 
5797  | 0  |     int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;  | 
5798  | 0  |     for (int iField = 0; iField < nSrcFieldCount; ++iField)  | 
5799  | 0  |     { | 
5800  | 0  |         OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);  | 
5801  | 0  |         OGRFieldDefn oFieldDefn(poSrcFieldDefn);  | 
5802  |  |  | 
5803  |  |         // The field may have been already created at layer creation.  | 
5804  | 0  |         int iDstField = -1;  | 
5805  | 0  |         if (poDstFDefn)  | 
5806  | 0  |             iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());  | 
5807  | 0  |         if (iDstField >= 0)  | 
5808  | 0  |         { | 
5809  | 0  |             anMap[iField] = iDstField;  | 
5810  | 0  |         }  | 
5811  | 0  |         else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)  | 
5812  | 0  |         { | 
5813  |  |             // Now that we've created a field, GetLayerDefn() won't return NULL.  | 
5814  | 0  |             if (poDstFDefn == nullptr)  | 
5815  | 0  |                 poDstFDefn = poDstLayer->GetLayerDefn();  | 
5816  |  |  | 
5817  |  |             // Sanity check: if it fails, the driver is buggy.  | 
5818  | 0  |             if (poDstFDefn != nullptr &&  | 
5819  | 0  |                 poDstFDefn->GetFieldCount() != nDstFieldCount + 1)  | 
5820  | 0  |             { | 
5821  | 0  |                 CPLError(CE_Warning, CPLE_AppDefined,  | 
5822  | 0  |                          "The output driver has claimed to have added the %s "  | 
5823  | 0  |                          "field, but it did not!",  | 
5824  | 0  |                          oFieldDefn.GetNameRef());  | 
5825  | 0  |             }  | 
5826  | 0  |             else  | 
5827  | 0  |             { | 
5828  | 0  |                 anMap[iField] = nDstFieldCount;  | 
5829  | 0  |                 ++nDstFieldCount;  | 
5830  | 0  |             }  | 
5831  | 0  |         }  | 
5832  | 0  |     }  | 
5833  |  |  | 
5834  |  |     /* -------------------------------------------------------------------- */  | 
5835  | 0  |     std::unique_ptr<OGRCoordinateTransformation> poCT;  | 
5836  | 0  |     OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();  | 
5837  | 0  |     if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&  | 
5838  | 0  |         sourceSRS->IsSame(&oDstSpaRef) == FALSE)  | 
5839  | 0  |     { | 
5840  | 0  |         poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));  | 
5841  | 0  |         if (nullptr == poCT)  | 
5842  | 0  |         { | 
5843  | 0  |             CPLError(CE_Failure, CPLE_NotSupported,  | 
5844  | 0  |                      "This input/output spatial reference is not supported.");  | 
5845  | 0  |             return nullptr;  | 
5846  | 0  |         }  | 
5847  | 0  |     }  | 
5848  |  |     /* -------------------------------------------------------------------- */  | 
5849  |  |     /*      Create geometry fields.                                         */  | 
5850  |  |     /* -------------------------------------------------------------------- */  | 
5851  | 0  |     if (nSrcGeomFieldCount > 1 &&  | 
5852  | 0  |         TestCapability(ODsCCreateGeomFieldAfterCreateLayer))  | 
5853  | 0  |     { | 
5854  |  | 
  | 
5855  | 0  |         for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)  | 
5856  | 0  |         { | 
5857  | 0  |             if (nullptr == pszSRSWKT)  | 
5858  | 0  |             { | 
5859  | 0  |                 poDstLayer->CreateGeomField(  | 
5860  | 0  |                     poSrcDefn->GetGeomFieldDefn(iField));  | 
5861  | 0  |             }  | 
5862  | 0  |             else  | 
5863  | 0  |             { | 
5864  | 0  |                 OGRGeomFieldDefn *pDstGeomFieldDefn =  | 
5865  | 0  |                     poSrcDefn->GetGeomFieldDefn(iField);  | 
5866  | 0  |                 pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);  | 
5867  | 0  |                 poDstLayer->CreateGeomField(pDstGeomFieldDefn);  | 
5868  | 0  |             }  | 
5869  | 0  |         }  | 
5870  | 0  |     }  | 
5871  |  |  | 
5872  |  |     /* -------------------------------------------------------------------- */  | 
5873  |  |     /*      Check if the destination layer supports transactions and set a  */  | 
5874  |  |     /*      default number of features in a single transaction.             */  | 
5875  |  |     /* -------------------------------------------------------------------- */  | 
5876  | 0  |     const int nGroupTransactions =  | 
5877  | 0  |         poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;  | 
5878  |  |  | 
5879  |  |     /* -------------------------------------------------------------------- */  | 
5880  |  |     /*      Transfer features.                                              */  | 
5881  |  |     /* -------------------------------------------------------------------- */  | 
5882  | 0  |     poSrcLayer->ResetReading();  | 
5883  |  | 
  | 
5884  | 0  |     if (nGroupTransactions <= 0)  | 
5885  | 0  |     { | 
5886  | 0  |         while (true)  | 
5887  | 0  |         { | 
5888  | 0  |             auto poFeature =  | 
5889  | 0  |                 std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());  | 
5890  |  | 
  | 
5891  | 0  |             if (poFeature == nullptr)  | 
5892  | 0  |                 break;  | 
5893  |  |  | 
5894  | 0  |             CPLErrorReset();  | 
5895  | 0  |             auto poDstFeature =  | 
5896  | 0  |                 std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());  | 
5897  |  | 
  | 
5898  | 0  |             if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=  | 
5899  | 0  |                 OGRERR_NONE)  | 
5900  | 0  |             { | 
5901  | 0  |                 CPLError(CE_Failure, CPLE_AppDefined,  | 
5902  | 0  |                          "Unable to translate feature " CPL_FRMT_GIB  | 
5903  | 0  |                          " from layer %s.",  | 
5904  | 0  |                          poFeature->GetFID(), poSrcDefn->GetName());  | 
5905  | 0  |                 return poDstLayer;  | 
5906  | 0  |             }  | 
5907  |  |  | 
5908  | 0  |             if (nullptr != poCT)  | 
5909  | 0  |             { | 
5910  | 0  |                 for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)  | 
5911  | 0  |                 { | 
5912  | 0  |                     OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);  | 
5913  | 0  |                     if (nullptr == pGeom)  | 
5914  | 0  |                         continue;  | 
5915  |  |  | 
5916  | 0  |                     const OGRErr eErr = pGeom->transform(poCT.get());  | 
5917  | 0  |                     if (eErr == OGRERR_NONE)  | 
5918  | 0  |                         continue;  | 
5919  |  |  | 
5920  | 0  |                     CPLError(CE_Failure, CPLE_AppDefined,  | 
5921  | 0  |                              "Unable to transform geometry " CPL_FRMT_GIB  | 
5922  | 0  |                              " from layer %s.",  | 
5923  | 0  |                              poFeature->GetFID(), poSrcDefn->GetName());  | 
5924  | 0  |                     return poDstLayer;  | 
5925  | 0  |                 }  | 
5926  | 0  |             }  | 
5927  |  |  | 
5928  | 0  |             poDstFeature->SetFID(poFeature->GetFID());  | 
5929  |  | 
  | 
5930  | 0  |             CPLErrorReset();  | 
5931  | 0  |             if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)  | 
5932  | 0  |             { | 
5933  | 0  |                 return poDstLayer;  | 
5934  | 0  |             }  | 
5935  | 0  |         }  | 
5936  | 0  |     }  | 
5937  | 0  |     else  | 
5938  | 0  |     { | 
5939  | 0  |         std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;  | 
5940  | 0  |         try  | 
5941  | 0  |         { | 
5942  | 0  |             apoDstFeatures.resize(nGroupTransactions);  | 
5943  | 0  |         }  | 
5944  | 0  |         catch (const std::exception &e)  | 
5945  | 0  |         { | 
5946  | 0  |             CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());  | 
5947  | 0  |             return poDstLayer;  | 
5948  | 0  |         }  | 
5949  | 0  |         bool bStopTransfer = false;  | 
5950  | 0  |         while (!bStopTransfer)  | 
5951  | 0  |         { | 
5952  |  |             /* --------------------------------------------------------------------  | 
5953  |  |              */  | 
5954  |  |             /*      Fill the array with features. */  | 
5955  |  |             /* --------------------------------------------------------------------  | 
5956  |  |              */  | 
5957  |  |             // Number of features in the temporary array.  | 
5958  | 0  |             int nFeatCount = 0;  // Used after for.  | 
5959  | 0  |             for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)  | 
5960  | 0  |             { | 
5961  | 0  |                 auto poFeature =  | 
5962  | 0  |                     std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());  | 
5963  |  | 
  | 
5964  | 0  |                 if (poFeature == nullptr)  | 
5965  | 0  |                 { | 
5966  | 0  |                     bStopTransfer = true;  | 
5967  | 0  |                     break;  | 
5968  | 0  |                 }  | 
5969  |  |  | 
5970  | 0  |                 CPLErrorReset();  | 
5971  | 0  |                 apoDstFeatures[nFeatCount] =  | 
5972  | 0  |                     std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());  | 
5973  |  | 
  | 
5974  | 0  |                 if (apoDstFeatures[nFeatCount]->SetFrom(  | 
5975  | 0  |                         poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)  | 
5976  | 0  |                 { | 
5977  | 0  |                     CPLError(CE_Failure, CPLE_AppDefined,  | 
5978  | 0  |                              "Unable to translate feature " CPL_FRMT_GIB  | 
5979  | 0  |                              " from layer %s.",  | 
5980  | 0  |                              poFeature->GetFID(), poSrcDefn->GetName());  | 
5981  | 0  |                     bStopTransfer = true;  | 
5982  | 0  |                     poFeature.reset();  | 
5983  | 0  |                     break;  | 
5984  | 0  |                 }  | 
5985  |  |  | 
5986  | 0  |                 if (nullptr != poCT)  | 
5987  | 0  |                 { | 
5988  | 0  |                     for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)  | 
5989  | 0  |                     { | 
5990  | 0  |                         OGRGeometry *pGeom =  | 
5991  | 0  |                             apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);  | 
5992  | 0  |                         if (nullptr == pGeom)  | 
5993  | 0  |                             continue;  | 
5994  |  |  | 
5995  | 0  |                         const OGRErr eErr = pGeom->transform(poCT.get());  | 
5996  | 0  |                         if (eErr == OGRERR_NONE)  | 
5997  | 0  |                             continue;  | 
5998  |  |  | 
5999  | 0  |                         CPLError(CE_Failure, CPLE_AppDefined,  | 
6000  | 0  |                                  "Unable to transform geometry " CPL_FRMT_GIB  | 
6001  | 0  |                                  " from layer %s.",  | 
6002  | 0  |                                  poFeature->GetFID(), poSrcDefn->GetName());  | 
6003  | 0  |                         bStopTransfer = true;  | 
6004  | 0  |                         poFeature.reset();  | 
6005  | 0  |                         break;  | 
6006  | 0  |                     }  | 
6007  | 0  |                 }  | 
6008  |  | 
  | 
6009  | 0  |                 if (poFeature)  | 
6010  | 0  |                 { | 
6011  | 0  |                     apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());  | 
6012  | 0  |                 }  | 
6013  | 0  |             }  | 
6014  |  | 
  | 
6015  | 0  |             CPLErrorReset();  | 
6016  | 0  |             bool bStopTransaction = false;  | 
6017  | 0  |             while (!bStopTransaction)  | 
6018  | 0  |             { | 
6019  | 0  |                 bStopTransaction = true;  | 
6020  | 0  |                 if (poDstLayer->StartTransaction() != OGRERR_NONE)  | 
6021  | 0  |                     break;  | 
6022  | 0  |                 for (int i = 0; i < nFeatCount; ++i)  | 
6023  | 0  |                 { | 
6024  | 0  |                     if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=  | 
6025  | 0  |                         OGRERR_NONE)  | 
6026  | 0  |                     { | 
6027  | 0  |                         bStopTransfer = true;  | 
6028  | 0  |                         bStopTransaction = false;  | 
6029  | 0  |                         break;  | 
6030  | 0  |                     }  | 
6031  | 0  |                     apoDstFeatures[i].reset();  | 
6032  | 0  |                 }  | 
6033  | 0  |                 if (bStopTransaction)  | 
6034  | 0  |                 { | 
6035  | 0  |                     if (poDstLayer->CommitTransaction() != OGRERR_NONE)  | 
6036  | 0  |                         break;  | 
6037  | 0  |                 }  | 
6038  | 0  |                 else  | 
6039  | 0  |                 { | 
6040  | 0  |                     poDstLayer->RollbackTransaction();  | 
6041  | 0  |                 }  | 
6042  | 0  |             }  | 
6043  | 0  |         }  | 
6044  | 0  |     }  | 
6045  |  |  | 
6046  | 0  |     return poDstLayer;  | 
6047  | 0  | }  | 
6048  |  |  | 
6049  |  | /************************************************************************/  | 
6050  |  | /*                            DeleteLayer()                             */  | 
6051  |  | /************************************************************************/  | 
6052  |  |  | 
6053  |  | /**  | 
6054  |  |  \fn GDALDataset::DeleteLayer(int)  | 
6055  |  |  \brief Delete the indicated layer from the datasource.  | 
6056  |  |  | 
6057  |  |  If this method is supported  | 
6058  |  |  the ODsCDeleteLayer capability will test TRUE on the GDALDataset.  | 
6059  |  |  | 
6060  |  |  This method is the same as the C function GDALDatasetDeleteLayer() and the  | 
6061  |  |  deprecated OGR_DS_DeleteLayer().  | 
6062  |  |  | 
6063  |  |  In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
6064  |  |  | 
6065  |  |  @param iLayer the index of the layer to delete.  | 
6066  |  |  | 
6067  |  |  @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting  | 
6068  |  |  layers is not supported for this datasource.  | 
6069  |  |  | 
6070  |  | */  | 
6071  |  |  | 
6072  |  | OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)  | 
6073  |  |  | 
6074  | 0  | { | 
6075  | 0  |     CPLError(CE_Failure, CPLE_NotSupported,  | 
6076  | 0  |              "DeleteLayer() not supported by this dataset.");  | 
6077  |  | 
  | 
6078  | 0  |     return OGRERR_UNSUPPORTED_OPERATION;  | 
6079  | 0  | }  | 
6080  |  |  | 
6081  |  | /************************************************************************/  | 
6082  |  | /*                           GetLayerByName()                           */  | 
6083  |  | /************************************************************************/  | 
6084  |  |  | 
6085  |  | /**  | 
6086  |  |  \brief Fetch a layer by name.  | 
6087  |  |  | 
6088  |  |  The returned layer remains owned by the  | 
6089  |  |  GDALDataset and should not be deleted by the application.  | 
6090  |  |  | 
6091  |  |  This method is the same as the C function GDALDatasetGetLayerByName() and the  | 
6092  |  |  deprecated OGR_DS_GetLayerByName().  | 
6093  |  |  | 
6094  |  |  In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
6095  |  |  | 
6096  |  |  @param pszName the layer name of the layer to fetch.  | 
6097  |  |  | 
6098  |  |  @return the layer, or NULL if Layer is not found or an error occurs.  | 
6099  |  | */  | 
6100  |  |  | 
6101  |  | OGRLayer *GDALDataset::GetLayerByName(const char *pszName)  | 
6102  |  |  | 
6103  | 0  | { | 
6104  | 0  |     CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);  | 
6105  |  | 
  | 
6106  | 0  |     if (!pszName)  | 
6107  | 0  |         return nullptr;  | 
6108  |  |  | 
6109  |  |     // First a case sensitive check.  | 
6110  | 0  |     for (int i = 0; i < GetLayerCount(); ++i)  | 
6111  | 0  |     { | 
6112  | 0  |         OGRLayer *poLayer = GetLayer(i);  | 
6113  |  | 
  | 
6114  | 0  |         if (strcmp(pszName, poLayer->GetName()) == 0)  | 
6115  | 0  |             return poLayer;  | 
6116  | 0  |     }  | 
6117  |  |  | 
6118  |  |     // Then case insensitive.  | 
6119  | 0  |     for (int i = 0; i < GetLayerCount(); ++i)  | 
6120  | 0  |     { | 
6121  | 0  |         OGRLayer *poLayer = GetLayer(i);  | 
6122  |  | 
  | 
6123  | 0  |         if (EQUAL(pszName, poLayer->GetName()))  | 
6124  | 0  |             return poLayer;  | 
6125  | 0  |     }  | 
6126  |  |  | 
6127  | 0  |     return nullptr;  | 
6128  | 0  | }  | 
6129  |  |  | 
6130  |  | //! @cond Doxygen_Suppress  | 
6131  |  | /************************************************************************/  | 
6132  |  | /*                       ProcessSQLCreateIndex()                        */  | 
6133  |  | /*                                                                      */  | 
6134  |  | /*      The correct syntax for creating an index in our dialect of      */  | 
6135  |  | /*      SQL is:                                                         */  | 
6136  |  | /*                                                                      */  | 
6137  |  | /*        CREATE INDEX ON <layername> USING <columnname>                */  | 
6138  |  | /************************************************************************/  | 
6139  |  |  | 
6140  |  | OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)  | 
6141  |  |  | 
6142  | 0  | { | 
6143  | 0  |     char **papszTokens = CSLTokenizeString(pszSQLCommand);  | 
6144  |  |  | 
6145  |  |     /* -------------------------------------------------------------------- */  | 
6146  |  |     /*      Do some general syntax checking.                                */  | 
6147  |  |     /* -------------------------------------------------------------------- */  | 
6148  | 0  |     if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||  | 
6149  | 0  |         !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||  | 
6150  | 0  |         !EQUAL(papszTokens[4], "USING"))  | 
6151  | 0  |     { | 
6152  | 0  |         CSLDestroy(papszTokens);  | 
6153  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6154  | 0  |                  "Syntax error in CREATE INDEX command.\n"  | 
6155  | 0  |                  "Was '%s'\n"  | 
6156  | 0  |                  "Should be of form 'CREATE INDEX ON <table> USING <field>'",  | 
6157  | 0  |                  pszSQLCommand);  | 
6158  | 0  |         return OGRERR_FAILURE;  | 
6159  | 0  |     }  | 
6160  |  |  | 
6161  |  |     /* -------------------------------------------------------------------- */  | 
6162  |  |     /*      Find the named layer.                                           */  | 
6163  |  |     /* -------------------------------------------------------------------- */  | 
6164  | 0  |     OGRLayer *poLayer = GetLayerByName(papszTokens[3]);  | 
6165  | 0  |     if (poLayer == nullptr)  | 
6166  | 0  |     { | 
6167  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6168  | 0  |                  "CREATE INDEX ON failed, no such layer as `%s'.",  | 
6169  | 0  |                  papszTokens[3]);  | 
6170  | 0  |         CSLDestroy(papszTokens);  | 
6171  | 0  |         return OGRERR_FAILURE;  | 
6172  | 0  |     }  | 
6173  |  |  | 
6174  |  |     /* -------------------------------------------------------------------- */  | 
6175  |  |     /*      Does this layer even support attribute indexes?                 */  | 
6176  |  |     /* -------------------------------------------------------------------- */  | 
6177  | 0  |     if (poLayer->GetIndex() == nullptr)  | 
6178  | 0  |     { | 
6179  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6180  | 0  |                  "CREATE INDEX ON not supported by this driver.");  | 
6181  | 0  |         CSLDestroy(papszTokens);  | 
6182  | 0  |         return OGRERR_FAILURE;  | 
6183  | 0  |     }  | 
6184  |  |  | 
6185  |  |     /* -------------------------------------------------------------------- */  | 
6186  |  |     /*      Find the named field.                                           */  | 
6187  |  |     /* -------------------------------------------------------------------- */  | 
6188  | 0  |     int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);  | 
6189  |  | 
  | 
6190  | 0  |     CSLDestroy(papszTokens);  | 
6191  |  | 
  | 
6192  | 0  |     if (i >= poLayer->GetLayerDefn()->GetFieldCount())  | 
6193  | 0  |     { | 
6194  | 0  |         CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",  | 
6195  | 0  |                  pszSQLCommand);  | 
6196  | 0  |         return OGRERR_FAILURE;  | 
6197  | 0  |     }  | 
6198  |  |  | 
6199  |  |     /* -------------------------------------------------------------------- */  | 
6200  |  |     /*      Attempt to create the index.                                    */  | 
6201  |  |     /* -------------------------------------------------------------------- */  | 
6202  | 0  |     OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);  | 
6203  | 0  |     if (eErr == OGRERR_NONE)  | 
6204  | 0  |     { | 
6205  | 0  |         eErr = poLayer->GetIndex()->IndexAllFeatures(i);  | 
6206  | 0  |     }  | 
6207  | 0  |     else  | 
6208  | 0  |     { | 
6209  | 0  |         if (strlen(CPLGetLastErrorMsg()) == 0)  | 
6210  | 0  |             CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);  | 
6211  | 0  |     }  | 
6212  |  | 
  | 
6213  | 0  |     return eErr;  | 
6214  | 0  | }  | 
6215  |  |  | 
6216  |  | /************************************************************************/  | 
6217  |  | /*                        ProcessSQLDropIndex()                         */  | 
6218  |  | /*                                                                      */  | 
6219  |  | /*      The correct syntax for dropping one or more indexes in          */  | 
6220  |  | /*      the OGR SQL dialect is:                                         */  | 
6221  |  | /*                                                                      */  | 
6222  |  | /*          DROP INDEX ON <layername> [USING <columnname>]              */  | 
6223  |  | /************************************************************************/  | 
6224  |  |  | 
6225  |  | OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)  | 
6226  |  |  | 
6227  | 0  | { | 
6228  | 0  |     char **papszTokens = CSLTokenizeString(pszSQLCommand);  | 
6229  |  |  | 
6230  |  |     /* -------------------------------------------------------------------- */  | 
6231  |  |     /*      Do some general syntax checking.                                */  | 
6232  |  |     /* -------------------------------------------------------------------- */  | 
6233  | 0  |     if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||  | 
6234  | 0  |         !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||  | 
6235  | 0  |         !EQUAL(papszTokens[2], "ON") ||  | 
6236  | 0  |         (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))  | 
6237  | 0  |     { | 
6238  | 0  |         CSLDestroy(papszTokens);  | 
6239  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6240  | 0  |                  "Syntax error in DROP INDEX command.\n"  | 
6241  | 0  |                  "Was '%s'\n"  | 
6242  | 0  |                  "Should be of form 'DROP INDEX ON <table> [USING <field>]'",  | 
6243  | 0  |                  pszSQLCommand);  | 
6244  | 0  |         return OGRERR_FAILURE;  | 
6245  | 0  |     }  | 
6246  |  |  | 
6247  |  |     /* -------------------------------------------------------------------- */  | 
6248  |  |     /*      Find the named layer.                                           */  | 
6249  |  |     /* -------------------------------------------------------------------- */  | 
6250  | 0  |     OGRLayer *poLayer = GetLayerByName(papszTokens[3]);  | 
6251  | 0  |     if (poLayer == nullptr)  | 
6252  | 0  |     { | 
6253  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6254  | 0  |                  "DROP INDEX ON failed, no such layer as `%s'.",  | 
6255  | 0  |                  papszTokens[3]);  | 
6256  | 0  |         CSLDestroy(papszTokens);  | 
6257  | 0  |         return OGRERR_FAILURE;  | 
6258  | 0  |     }  | 
6259  |  |  | 
6260  |  |     /* -------------------------------------------------------------------- */  | 
6261  |  |     /*      Does this layer even support attribute indexes?                 */  | 
6262  |  |     /* -------------------------------------------------------------------- */  | 
6263  | 0  |     if (poLayer->GetIndex() == nullptr)  | 
6264  | 0  |     { | 
6265  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6266  | 0  |                  "Indexes not supported by this driver.");  | 
6267  | 0  |         CSLDestroy(papszTokens);  | 
6268  | 0  |         return OGRERR_FAILURE;  | 
6269  | 0  |     }  | 
6270  |  |  | 
6271  |  |     /* -------------------------------------------------------------------- */  | 
6272  |  |     /*      If we were not given a field name, drop all indexes.            */  | 
6273  |  |     /* -------------------------------------------------------------------- */  | 
6274  | 0  |     if (CSLCount(papszTokens) == 4)  | 
6275  | 0  |     { | 
6276  | 0  |         for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)  | 
6277  | 0  |         { | 
6278  | 0  |             OGRAttrIndex *poAttrIndex;  | 
6279  |  | 
  | 
6280  | 0  |             poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);  | 
6281  | 0  |             if (poAttrIndex != nullptr)  | 
6282  | 0  |             { | 
6283  | 0  |                 const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);  | 
6284  | 0  |                 if (eErr != OGRERR_NONE)  | 
6285  | 0  |                 { | 
6286  | 0  |                     CSLDestroy(papszTokens);  | 
6287  | 0  |                     return eErr;  | 
6288  | 0  |                 }  | 
6289  | 0  |             }  | 
6290  | 0  |         }  | 
6291  |  |  | 
6292  | 0  |         CSLDestroy(papszTokens);  | 
6293  | 0  |         return OGRERR_NONE;  | 
6294  | 0  |     }  | 
6295  |  |  | 
6296  |  |     /* -------------------------------------------------------------------- */  | 
6297  |  |     /*      Find the named field.                                           */  | 
6298  |  |     /* -------------------------------------------------------------------- */  | 
6299  | 0  |     int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);  | 
6300  | 0  |     CSLDestroy(papszTokens);  | 
6301  |  | 
  | 
6302  | 0  |     if (i >= poLayer->GetLayerDefn()->GetFieldCount())  | 
6303  | 0  |     { | 
6304  | 0  |         CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",  | 
6305  | 0  |                  pszSQLCommand);  | 
6306  | 0  |         return OGRERR_FAILURE;  | 
6307  | 0  |     }  | 
6308  |  |  | 
6309  |  |     /* -------------------------------------------------------------------- */  | 
6310  |  |     /*      Attempt to drop the index.                                      */  | 
6311  |  |     /* -------------------------------------------------------------------- */  | 
6312  | 0  |     const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);  | 
6313  |  | 
  | 
6314  | 0  |     return eErr;  | 
6315  | 0  | }  | 
6316  |  |  | 
6317  |  | /************************************************************************/  | 
6318  |  | /*                        ProcessSQLDropTable()                         */  | 
6319  |  | /*                                                                      */  | 
6320  |  | /*      The correct syntax for dropping a table (layer) in the OGR SQL  */  | 
6321  |  | /*      dialect is:                                                     */  | 
6322  |  | /*                                                                      */  | 
6323  |  | /*          DROP TABLE <layername>                                      */  | 
6324  |  | /************************************************************************/  | 
6325  |  |  | 
6326  |  | OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)  | 
6327  |  |  | 
6328  | 0  | { | 
6329  | 0  |     char **papszTokens = CSLTokenizeString(pszSQLCommand);  | 
6330  |  |  | 
6331  |  |     /* -------------------------------------------------------------------- */  | 
6332  |  |     /*      Do some general syntax checking.                                */  | 
6333  |  |     /* -------------------------------------------------------------------- */  | 
6334  | 0  |     if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||  | 
6335  | 0  |         !EQUAL(papszTokens[1], "TABLE"))  | 
6336  | 0  |     { | 
6337  | 0  |         CSLDestroy(papszTokens);  | 
6338  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6339  | 0  |                  "Syntax error in DROP TABLE command.\n"  | 
6340  | 0  |                  "Was '%s'\n"  | 
6341  | 0  |                  "Should be of form 'DROP TABLE <table>'",  | 
6342  | 0  |                  pszSQLCommand);  | 
6343  | 0  |         return OGRERR_FAILURE;  | 
6344  | 0  |     }  | 
6345  |  |  | 
6346  |  |     /* -------------------------------------------------------------------- */  | 
6347  |  |     /*      Find the named layer.                                           */  | 
6348  |  |     /* -------------------------------------------------------------------- */  | 
6349  | 0  |     OGRLayer *poLayer = nullptr;  | 
6350  |  | 
  | 
6351  | 0  |     int i = 0;  // Used after for.  | 
6352  | 0  |     for (; i < GetLayerCount(); ++i)  | 
6353  | 0  |     { | 
6354  | 0  |         poLayer = GetLayer(i);  | 
6355  |  | 
  | 
6356  | 0  |         if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))  | 
6357  | 0  |             break;  | 
6358  | 0  |         poLayer = nullptr;  | 
6359  | 0  |     }  | 
6360  |  | 
  | 
6361  | 0  |     if (poLayer == nullptr)  | 
6362  | 0  |     { | 
6363  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6364  | 0  |                  "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);  | 
6365  | 0  |         CSLDestroy(papszTokens);  | 
6366  | 0  |         return OGRERR_FAILURE;  | 
6367  | 0  |     }  | 
6368  |  |  | 
6369  | 0  |     CSLDestroy(papszTokens);  | 
6370  |  |  | 
6371  |  |     /* -------------------------------------------------------------------- */  | 
6372  |  |     /*      Delete it.                                                      */  | 
6373  |  |     /* -------------------------------------------------------------------- */  | 
6374  |  | 
  | 
6375  | 0  |     return DeleteLayer(i);  | 
6376  | 0  | }  | 
6377  |  |  | 
6378  |  | //! @endcond  | 
6379  |  |  | 
6380  |  | /************************************************************************/  | 
6381  |  | /*                    GDALDatasetParseSQLType()                       */  | 
6382  |  | /************************************************************************/  | 
6383  |  |  | 
6384  |  | /* All arguments will be altered */  | 
6385  |  | static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,  | 
6386  |  |                                             int &nPrecision)  | 
6387  | 0  | { | 
6388  | 0  |     char *pszParenthesis = strchr(pszType, '('); | 
6389  | 0  |     if (pszParenthesis)  | 
6390  | 0  |     { | 
6391  | 0  |         nWidth = atoi(pszParenthesis + 1);  | 
6392  | 0  |         *pszParenthesis = '\0';  | 
6393  | 0  |         char *pszComma = strchr(pszParenthesis + 1, ',');  | 
6394  | 0  |         if (pszComma)  | 
6395  | 0  |             nPrecision = atoi(pszComma + 1);  | 
6396  | 0  |     }  | 
6397  |  | 
  | 
6398  | 0  |     OGRFieldType eType = OFTString;  | 
6399  | 0  |     if (EQUAL(pszType, "INTEGER"))  | 
6400  | 0  |         eType = OFTInteger;  | 
6401  | 0  |     else if (EQUAL(pszType, "INTEGER[]"))  | 
6402  | 0  |         eType = OFTIntegerList;  | 
6403  | 0  |     else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||  | 
6404  | 0  |              EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||  | 
6405  | 0  |              EQUAL(pszType, "REAL") /* unofficial alias */)  | 
6406  | 0  |         eType = OFTReal;  | 
6407  | 0  |     else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||  | 
6408  | 0  |              EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||  | 
6409  | 0  |              EQUAL(pszType, "REAL[]") /* unofficial alias */)  | 
6410  | 0  |         eType = OFTRealList;  | 
6411  | 0  |     else if (EQUAL(pszType, "CHARACTER") ||  | 
6412  | 0  |              EQUAL(pszType, "TEXT") /* unofficial alias */ ||  | 
6413  | 0  |              EQUAL(pszType, "STRING") /* unofficial alias */ ||  | 
6414  | 0  |              EQUAL(pszType, "VARCHAR") /* unofficial alias */)  | 
6415  | 0  |         eType = OFTString;  | 
6416  | 0  |     else if (EQUAL(pszType, "TEXT[]") ||  | 
6417  | 0  |              EQUAL(pszType, "STRING[]") /* unofficial alias */ ||  | 
6418  | 0  |              EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)  | 
6419  | 0  |         eType = OFTStringList;  | 
6420  | 0  |     else if (EQUAL(pszType, "DATE"))  | 
6421  | 0  |         eType = OFTDate;  | 
6422  | 0  |     else if (EQUAL(pszType, "TIME"))  | 
6423  | 0  |         eType = OFTTime;  | 
6424  | 0  |     else if (EQUAL(pszType, "TIMESTAMP") ||  | 
6425  | 0  |              EQUAL(pszType, "DATETIME") /* unofficial alias */)  | 
6426  | 0  |         eType = OFTDateTime;  | 
6427  | 0  |     else  | 
6428  | 0  |         CPLError(CE_Warning, CPLE_NotSupported,  | 
6429  | 0  |                  "Unsupported column type '%s'. Defaulting to VARCHAR",  | 
6430  | 0  |                  pszType);  | 
6431  |  | 
  | 
6432  | 0  |     return eType;  | 
6433  | 0  | }  | 
6434  |  |  | 
6435  |  | /************************************************************************/  | 
6436  |  | /*                    ProcessSQLAlterTableAddColumn()                   */  | 
6437  |  | /*                                                                      */  | 
6438  |  | /*      The correct syntax for adding a column in the OGR SQL           */  | 
6439  |  | /*      dialect is:                                                     */  | 
6440  |  | /*                                                                      */  | 
6441  |  | /*       ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */  | 
6442  |  | /************************************************************************/  | 
6443  |  |  | 
6444  |  | //! @cond Doxygen_Suppress  | 
6445  |  | OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)  | 
6446  |  |  | 
6447  | 0  | { | 
6448  | 0  |     char **papszTokens = CSLTokenizeString(pszSQLCommand);  | 
6449  |  |  | 
6450  |  |     /* -------------------------------------------------------------------- */  | 
6451  |  |     /*      Do some general syntax checking.                                */  | 
6452  |  |     /* -------------------------------------------------------------------- */  | 
6453  | 0  |     const char *pszLayerName = nullptr;  | 
6454  | 0  |     const char *pszColumnName = nullptr;  | 
6455  | 0  |     int iTypeIndex = 0;  | 
6456  | 0  |     const int nTokens = CSLCount(papszTokens);  | 
6457  |  | 
  | 
6458  | 0  |     if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&  | 
6459  | 0  |         EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&  | 
6460  | 0  |         EQUAL(papszTokens[4], "COLUMN"))  | 
6461  | 0  |     { | 
6462  | 0  |         pszLayerName = papszTokens[2];  | 
6463  | 0  |         pszColumnName = papszTokens[5];  | 
6464  | 0  |         iTypeIndex = 6;  | 
6465  | 0  |     }  | 
6466  | 0  |     else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&  | 
6467  | 0  |              EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))  | 
6468  | 0  |     { | 
6469  | 0  |         pszLayerName = papszTokens[2];  | 
6470  | 0  |         pszColumnName = papszTokens[4];  | 
6471  | 0  |         iTypeIndex = 5;  | 
6472  | 0  |     }  | 
6473  | 0  |     else  | 
6474  | 0  |     { | 
6475  | 0  |         CSLDestroy(papszTokens);  | 
6476  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6477  | 0  |                  "Syntax error in ALTER TABLE ADD COLUMN command.\n"  | 
6478  | 0  |                  "Was '%s'\n"  | 
6479  | 0  |                  "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "  | 
6480  | 0  |                  "<columnname> <columntype>'",  | 
6481  | 0  |                  pszSQLCommand);  | 
6482  | 0  |         return OGRERR_FAILURE;  | 
6483  | 0  |     }  | 
6484  |  |  | 
6485  |  |     /* -------------------------------------------------------------------- */  | 
6486  |  |     /*      Merge type components into a single string if there were split  */  | 
6487  |  |     /*      with spaces                                                     */  | 
6488  |  |     /* -------------------------------------------------------------------- */  | 
6489  | 0  |     CPLString osType;  | 
6490  | 0  |     for (int i = iTypeIndex; i < nTokens; ++i)  | 
6491  | 0  |     { | 
6492  | 0  |         osType += papszTokens[i];  | 
6493  | 0  |         CPLFree(papszTokens[i]);  | 
6494  | 0  |     }  | 
6495  | 0  |     char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);  | 
6496  | 0  |     papszTokens[iTypeIndex + 1] = nullptr;  | 
6497  |  |  | 
6498  |  |     /* -------------------------------------------------------------------- */  | 
6499  |  |     /*      Find the named layer.                                           */  | 
6500  |  |     /* -------------------------------------------------------------------- */  | 
6501  | 0  |     OGRLayer *poLayer = GetLayerByName(pszLayerName);  | 
6502  | 0  |     if (poLayer == nullptr)  | 
6503  | 0  |     { | 
6504  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6505  | 0  |                  "%s failed, no such layer as `%s'.", pszSQLCommand,  | 
6506  | 0  |                  pszLayerName);  | 
6507  | 0  |         CSLDestroy(papszTokens);  | 
6508  | 0  |         return OGRERR_FAILURE;  | 
6509  | 0  |     }  | 
6510  |  |  | 
6511  |  |     /* -------------------------------------------------------------------- */  | 
6512  |  |     /*      Add column.                                                     */  | 
6513  |  |     /* -------------------------------------------------------------------- */  | 
6514  |  |  | 
6515  | 0  |     int nWidth = 0;  | 
6516  | 0  |     int nPrecision = 0;  | 
6517  | 0  |     OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);  | 
6518  | 0  |     OGRFieldDefn oFieldDefn(pszColumnName, eType);  | 
6519  | 0  |     oFieldDefn.SetWidth(nWidth);  | 
6520  | 0  |     oFieldDefn.SetPrecision(nPrecision);  | 
6521  |  | 
  | 
6522  | 0  |     CSLDestroy(papszTokens);  | 
6523  |  | 
  | 
6524  | 0  |     return poLayer->CreateField(&oFieldDefn);  | 
6525  | 0  | }  | 
6526  |  |  | 
6527  |  | /************************************************************************/  | 
6528  |  | /*                    ProcessSQLAlterTableDropColumn()                  */  | 
6529  |  | /*                                                                      */  | 
6530  |  | /*      The correct syntax for dropping a column in the OGR SQL         */  | 
6531  |  | /*      dialect is:                                                     */  | 
6532  |  | /*                                                                      */  | 
6533  |  | /*          ALTER TABLE <layername> DROP [COLUMN] <columnname>          */  | 
6534  |  | /************************************************************************/  | 
6535  |  |  | 
6536  |  | OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)  | 
6537  |  |  | 
6538  | 0  | { | 
6539  | 0  |     char **papszTokens = CSLTokenizeString(pszSQLCommand);  | 
6540  |  |  | 
6541  |  |     /* -------------------------------------------------------------------- */  | 
6542  |  |     /*      Do some general syntax checking.                                */  | 
6543  |  |     /* -------------------------------------------------------------------- */  | 
6544  | 0  |     const char *pszLayerName = nullptr;  | 
6545  | 0  |     const char *pszColumnName = nullptr;  | 
6546  | 0  |     if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&  | 
6547  | 0  |         EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&  | 
6548  | 0  |         EQUAL(papszTokens[4], "COLUMN"))  | 
6549  | 0  |     { | 
6550  | 0  |         pszLayerName = papszTokens[2];  | 
6551  | 0  |         pszColumnName = papszTokens[5];  | 
6552  | 0  |     }  | 
6553  | 0  |     else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&  | 
6554  | 0  |              EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))  | 
6555  | 0  |     { | 
6556  | 0  |         pszLayerName = papszTokens[2];  | 
6557  | 0  |         pszColumnName = papszTokens[4];  | 
6558  | 0  |     }  | 
6559  | 0  |     else  | 
6560  | 0  |     { | 
6561  | 0  |         CSLDestroy(papszTokens);  | 
6562  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6563  | 0  |                  "Syntax error in ALTER TABLE DROP COLUMN command.\n"  | 
6564  | 0  |                  "Was '%s'\n"  | 
6565  | 0  |                  "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "  | 
6566  | 0  |                  "<columnname>'",  | 
6567  | 0  |                  pszSQLCommand);  | 
6568  | 0  |         return OGRERR_FAILURE;  | 
6569  | 0  |     }  | 
6570  |  |  | 
6571  |  |     /* -------------------------------------------------------------------- */  | 
6572  |  |     /*      Find the named layer.                                           */  | 
6573  |  |     /* -------------------------------------------------------------------- */  | 
6574  | 0  |     OGRLayer *poLayer = GetLayerByName(pszLayerName);  | 
6575  | 0  |     if (poLayer == nullptr)  | 
6576  | 0  |     { | 
6577  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6578  | 0  |                  "%s failed, no such layer as `%s'.", pszSQLCommand,  | 
6579  | 0  |                  pszLayerName);  | 
6580  | 0  |         CSLDestroy(papszTokens);  | 
6581  | 0  |         return OGRERR_FAILURE;  | 
6582  | 0  |     }  | 
6583  |  |  | 
6584  |  |     /* -------------------------------------------------------------------- */  | 
6585  |  |     /*      Find the field.                                                 */  | 
6586  |  |     /* -------------------------------------------------------------------- */  | 
6587  |  |  | 
6588  | 0  |     int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);  | 
6589  | 0  |     if (nFieldIndex < 0)  | 
6590  | 0  |     { | 
6591  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6592  | 0  |                  "%s failed, no such field as `%s'.", pszSQLCommand,  | 
6593  | 0  |                  pszColumnName);  | 
6594  | 0  |         CSLDestroy(papszTokens);  | 
6595  | 0  |         return OGRERR_FAILURE;  | 
6596  | 0  |     }  | 
6597  |  |  | 
6598  |  |     /* -------------------------------------------------------------------- */  | 
6599  |  |     /*      Remove it.                                                      */  | 
6600  |  |     /* -------------------------------------------------------------------- */  | 
6601  |  |  | 
6602  | 0  |     CSLDestroy(papszTokens);  | 
6603  |  | 
  | 
6604  | 0  |     return poLayer->DeleteField(nFieldIndex);  | 
6605  | 0  | }  | 
6606  |  |  | 
6607  |  | /************************************************************************/  | 
6608  |  | /*                 ProcessSQLAlterTableRenameColumn()                   */  | 
6609  |  | /*                                                                      */  | 
6610  |  | /*      The correct syntax for renaming a column in the OGR SQL         */  | 
6611  |  | /*      dialect is:                                                     */  | 
6612  |  | /*                                                                      */  | 
6613  |  | /*       ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */  | 
6614  |  | /************************************************************************/  | 
6615  |  |  | 
6616  |  | OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)  | 
6617  |  |  | 
6618  | 0  | { | 
6619  | 0  |     char **papszTokens = CSLTokenizeString(pszSQLCommand);  | 
6620  |  |  | 
6621  |  |     /* -------------------------------------------------------------------- */  | 
6622  |  |     /*      Do some general syntax checking.                                */  | 
6623  |  |     /* -------------------------------------------------------------------- */  | 
6624  | 0  |     const char *pszLayerName = nullptr;  | 
6625  | 0  |     const char *pszOldColName = nullptr;  | 
6626  | 0  |     const char *pszNewColName = nullptr;  | 
6627  | 0  |     if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&  | 
6628  | 0  |         EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&  | 
6629  | 0  |         EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))  | 
6630  | 0  |     { | 
6631  | 0  |         pszLayerName = papszTokens[2];  | 
6632  | 0  |         pszOldColName = papszTokens[5];  | 
6633  | 0  |         pszNewColName = papszTokens[7];  | 
6634  | 0  |     }  | 
6635  | 0  |     else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&  | 
6636  | 0  |              EQUAL(papszTokens[1], "TABLE") &&  | 
6637  | 0  |              EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))  | 
6638  | 0  |     { | 
6639  | 0  |         pszLayerName = papszTokens[2];  | 
6640  | 0  |         pszOldColName = papszTokens[4];  | 
6641  | 0  |         pszNewColName = papszTokens[6];  | 
6642  | 0  |     }  | 
6643  | 0  |     else  | 
6644  | 0  |     { | 
6645  | 0  |         CSLDestroy(papszTokens);  | 
6646  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6647  | 0  |                  "Syntax error in ALTER TABLE RENAME COLUMN command.\n"  | 
6648  | 0  |                  "Was '%s'\n"  | 
6649  | 0  |                  "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "  | 
6650  | 0  |                  "<columnname> TO <newname>'",  | 
6651  | 0  |                  pszSQLCommand);  | 
6652  | 0  |         return OGRERR_FAILURE;  | 
6653  | 0  |     }  | 
6654  |  |  | 
6655  |  |     /* -------------------------------------------------------------------- */  | 
6656  |  |     /*      Find the named layer.                                           */  | 
6657  |  |     /* -------------------------------------------------------------------- */  | 
6658  | 0  |     OGRLayer *poLayer = GetLayerByName(pszLayerName);  | 
6659  | 0  |     if (poLayer == nullptr)  | 
6660  | 0  |     { | 
6661  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6662  | 0  |                  "%s failed, no such layer as `%s'.", pszSQLCommand,  | 
6663  | 0  |                  pszLayerName);  | 
6664  | 0  |         CSLDestroy(papszTokens);  | 
6665  | 0  |         return OGRERR_FAILURE;  | 
6666  | 0  |     }  | 
6667  |  |  | 
6668  |  |     /* -------------------------------------------------------------------- */  | 
6669  |  |     /*      Find the field.                                                 */  | 
6670  |  |     /* -------------------------------------------------------------------- */  | 
6671  |  |  | 
6672  | 0  |     const int nFieldIndex =  | 
6673  | 0  |         poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);  | 
6674  | 0  |     if (nFieldIndex < 0)  | 
6675  | 0  |     { | 
6676  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6677  | 0  |                  "%s failed, no such field as `%s'.", pszSQLCommand,  | 
6678  | 0  |                  pszOldColName);  | 
6679  | 0  |         CSLDestroy(papszTokens);  | 
6680  | 0  |         return OGRERR_FAILURE;  | 
6681  | 0  |     }  | 
6682  |  |  | 
6683  |  |     /* -------------------------------------------------------------------- */  | 
6684  |  |     /*      Rename column.                                                  */  | 
6685  |  |     /* -------------------------------------------------------------------- */  | 
6686  | 0  |     OGRFieldDefn *poOldFieldDefn =  | 
6687  | 0  |         poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);  | 
6688  | 0  |     OGRFieldDefn oNewFieldDefn(poOldFieldDefn);  | 
6689  | 0  |     oNewFieldDefn.SetName(pszNewColName);  | 
6690  |  | 
  | 
6691  | 0  |     CSLDestroy(papszTokens);  | 
6692  |  | 
  | 
6693  | 0  |     return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,  | 
6694  | 0  |                                    ALTER_NAME_FLAG);  | 
6695  | 0  | }  | 
6696  |  |  | 
6697  |  | /************************************************************************/  | 
6698  |  | /*                 ProcessSQLAlterTableAlterColumn()                    */  | 
6699  |  | /*                                                                      */  | 
6700  |  | /*      The correct syntax for altering the type of a column in the     */  | 
6701  |  | /*      OGR SQL dialect is:                                             */  | 
6702  |  | /*                                                                      */  | 
6703  |  | /*   ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */  | 
6704  |  | /************************************************************************/  | 
6705  |  |  | 
6706  |  | OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)  | 
6707  |  |  | 
6708  | 0  | { | 
6709  | 0  |     char **papszTokens = CSLTokenizeString(pszSQLCommand);  | 
6710  |  |  | 
6711  |  |     /* -------------------------------------------------------------------- */  | 
6712  |  |     /*      Do some general syntax checking.                                */  | 
6713  |  |     /* -------------------------------------------------------------------- */  | 
6714  | 0  |     const char *pszLayerName = nullptr;  | 
6715  | 0  |     const char *pszColumnName = nullptr;  | 
6716  | 0  |     int iTypeIndex = 0;  | 
6717  | 0  |     const int nTokens = CSLCount(papszTokens);  | 
6718  |  | 
  | 
6719  | 0  |     if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&  | 
6720  | 0  |         EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&  | 
6721  | 0  |         EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))  | 
6722  | 0  |     { | 
6723  | 0  |         pszLayerName = papszTokens[2];  | 
6724  | 0  |         pszColumnName = papszTokens[5];  | 
6725  | 0  |         iTypeIndex = 7;  | 
6726  | 0  |     }  | 
6727  | 0  |     else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&  | 
6728  | 0  |              EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&  | 
6729  | 0  |              EQUAL(papszTokens[5], "TYPE"))  | 
6730  | 0  |     { | 
6731  | 0  |         pszLayerName = papszTokens[2];  | 
6732  | 0  |         pszColumnName = papszTokens[4];  | 
6733  | 0  |         iTypeIndex = 6;  | 
6734  | 0  |     }  | 
6735  | 0  |     else  | 
6736  | 0  |     { | 
6737  | 0  |         CSLDestroy(papszTokens);  | 
6738  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6739  | 0  |                  "Syntax error in ALTER TABLE ALTER COLUMN command.\n"  | 
6740  | 0  |                  "Was '%s'\n"  | 
6741  | 0  |                  "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "  | 
6742  | 0  |                  "<columnname> TYPE <columntype>'",  | 
6743  | 0  |                  pszSQLCommand);  | 
6744  | 0  |         return OGRERR_FAILURE;  | 
6745  | 0  |     }  | 
6746  |  |  | 
6747  |  |     /* -------------------------------------------------------------------- */  | 
6748  |  |     /*      Merge type components into a single string if there were split  */  | 
6749  |  |     /*      with spaces                                                     */  | 
6750  |  |     /* -------------------------------------------------------------------- */  | 
6751  | 0  |     CPLString osType;  | 
6752  | 0  |     for (int i = iTypeIndex; i < nTokens; ++i)  | 
6753  | 0  |     { | 
6754  | 0  |         osType += papszTokens[i];  | 
6755  | 0  |         CPLFree(papszTokens[i]);  | 
6756  | 0  |     }  | 
6757  | 0  |     char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);  | 
6758  | 0  |     papszTokens[iTypeIndex + 1] = nullptr;  | 
6759  |  |  | 
6760  |  |     /* -------------------------------------------------------------------- */  | 
6761  |  |     /*      Find the named layer.                                           */  | 
6762  |  |     /* -------------------------------------------------------------------- */  | 
6763  | 0  |     OGRLayer *poLayer = GetLayerByName(pszLayerName);  | 
6764  | 0  |     if (poLayer == nullptr)  | 
6765  | 0  |     { | 
6766  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6767  | 0  |                  "%s failed, no such layer as `%s'.", pszSQLCommand,  | 
6768  | 0  |                  pszLayerName);  | 
6769  | 0  |         CSLDestroy(papszTokens);  | 
6770  | 0  |         return OGRERR_FAILURE;  | 
6771  | 0  |     }  | 
6772  |  |  | 
6773  |  |     /* -------------------------------------------------------------------- */  | 
6774  |  |     /*      Find the field.                                                 */  | 
6775  |  |     /* -------------------------------------------------------------------- */  | 
6776  |  |  | 
6777  | 0  |     const int nFieldIndex =  | 
6778  | 0  |         poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);  | 
6779  | 0  |     if (nFieldIndex < 0)  | 
6780  | 0  |     { | 
6781  | 0  |         CPLError(CE_Failure, CPLE_AppDefined,  | 
6782  | 0  |                  "%s failed, no such field as `%s'.", pszSQLCommand,  | 
6783  | 0  |                  pszColumnName);  | 
6784  | 0  |         CSLDestroy(papszTokens);  | 
6785  | 0  |         return OGRERR_FAILURE;  | 
6786  | 0  |     }  | 
6787  |  |  | 
6788  |  |     /* -------------------------------------------------------------------- */  | 
6789  |  |     /*      Alter column.                                                   */  | 
6790  |  |     /* -------------------------------------------------------------------- */  | 
6791  |  |  | 
6792  | 0  |     OGRFieldDefn *poOldFieldDefn =  | 
6793  | 0  |         poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);  | 
6794  | 0  |     OGRFieldDefn oNewFieldDefn(poOldFieldDefn);  | 
6795  |  | 
  | 
6796  | 0  |     int nWidth = 0;  | 
6797  | 0  |     int nPrecision = 0;  | 
6798  | 0  |     OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);  | 
6799  | 0  |     oNewFieldDefn.SetType(eType);  | 
6800  | 0  |     oNewFieldDefn.SetWidth(nWidth);  | 
6801  | 0  |     oNewFieldDefn.SetPrecision(nPrecision);  | 
6802  |  | 
  | 
6803  | 0  |     int l_nFlags = 0;  | 
6804  | 0  |     if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())  | 
6805  | 0  |         l_nFlags |= ALTER_TYPE_FLAG;  | 
6806  | 0  |     if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||  | 
6807  | 0  |         poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())  | 
6808  | 0  |         l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;  | 
6809  |  | 
  | 
6810  | 0  |     CSLDestroy(papszTokens);  | 
6811  |  | 
  | 
6812  | 0  |     if (l_nFlags == 0)  | 
6813  | 0  |         return OGRERR_NONE;  | 
6814  |  |  | 
6815  | 0  |     return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);  | 
6816  | 0  | }  | 
6817  |  |  | 
6818  |  | //! @endcond  | 
6819  |  |  | 
6820  |  | /************************************************************************/  | 
6821  |  | /*                             ExecuteSQL()                             */  | 
6822  |  | /************************************************************************/  | 
6823  |  |  | 
6824  |  | /**  | 
6825  |  |  \brief Execute an SQL statement against the data store.  | 
6826  |  |  | 
6827  |  |  The result of an SQL query is either NULL for statements that are in error,  | 
6828  |  |  or that have no results set, or an OGRLayer pointer representing a results  | 
6829  |  |  set from the query.  Note that this OGRLayer is in addition to the layers  | 
6830  |  |  in the data store and must be destroyed with  | 
6831  |  |  ReleaseResultSet() before the dataset is closed  | 
6832  |  |  (destroyed).  | 
6833  |  |  | 
6834  |  |  This method is the same as the C function GDALDatasetExecuteSQL() and the  | 
6835  |  |  deprecated OGR_DS_ExecuteSQL().  | 
6836  |  |  | 
6837  |  |  For more information on the SQL dialect supported internally by OGR  | 
6838  |  |  review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>  | 
6839  |  |  document.  Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through  | 
6840  |  |  to the underlying RDBMS.  | 
6841  |  |  | 
6842  |  |  Starting with OGR 1.10, the <a  | 
6843  |  |  href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can  | 
6844  |  |  also be used.  | 
6845  |  |  | 
6846  |  |  In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
6847  |  |  | 
6848  |  |  @param pszStatement the SQL statement to execute.  | 
6849  |  |  @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.  | 
6850  |  |  @param pszDialect allows control of the statement dialect. If set to NULL, the  | 
6851  |  |  OGR SQL engine will be used, except for RDBMS drivers that will use their  | 
6852  |  |  dedicated SQL engine, unless OGRSQL is explicitly passed as the  | 
6853  |  |  dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.  | 
6854  |  |  | 
6855  |  |  @return an OGRLayer containing the results of the query.  Deallocate with  | 
6856  |  |  ReleaseResultSet().  | 
6857  |  |  | 
6858  |  | */  | 
6859  |  |  | 
6860  |  | OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,  | 
6861  |  |                                   OGRGeometry *poSpatialFilter,  | 
6862  |  |                                   const char *pszDialect)  | 
6863  |  |  | 
6864  | 0  | { | 
6865  | 0  |     return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);  | 
6866  | 0  | }  | 
6867  |  |  | 
6868  |  | //! @cond Doxygen_Suppress  | 
6869  |  | OGRLayer *  | 
6870  |  | GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,  | 
6871  |  |                         const char *pszDialect,  | 
6872  |  |                         swq_select_parse_options *poSelectParseOptions)  | 
6873  |  |  | 
6874  | 0  | { | 
6875  | 0  |     if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))  | 
6876  | 0  |     { | 
6877  |  | #ifdef SQLITE_ENABLED  | 
6878  |  |         return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,  | 
6879  |  |                                    pszDialect);  | 
6880  |  | #else  | 
6881  | 0  |         CPLError(CE_Failure, CPLE_NotSupported,  | 
6882  | 0  |                  "The SQLite driver needs to be compiled to support the "  | 
6883  | 0  |                  "SQLite SQL dialect");  | 
6884  | 0  |         return nullptr;  | 
6885  | 0  | #endif  | 
6886  | 0  |     }  | 
6887  |  |  | 
6888  | 0  |     if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&  | 
6889  | 0  |         !EQUAL(pszDialect, "OGRSQL"))  | 
6890  | 0  |     { | 
6891  | 0  |         std::string osDialectList = "'OGRSQL'";  | 
6892  |  | #ifdef SQLITE_ENABLED  | 
6893  |  |         osDialectList += ", 'SQLITE'";  | 
6894  |  | #endif  | 
6895  | 0  |         const char *pszDialects =  | 
6896  | 0  |             GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);  | 
6897  | 0  |         if (pszDialects)  | 
6898  | 0  |         { | 
6899  | 0  |             const CPLStringList aosTokens(  | 
6900  | 0  |                 CSLTokenizeString2(pszDialects, " ", 0));  | 
6901  | 0  |             for (int i = 0; i < aosTokens.size(); ++i)  | 
6902  | 0  |             { | 
6903  | 0  |                 if (!EQUAL(aosTokens[i], "OGRSQL") &&  | 
6904  | 0  |                     !EQUAL(aosTokens[i], "SQLITE"))  | 
6905  | 0  |                 { | 
6906  | 0  |                     osDialectList += ", '";  | 
6907  | 0  |                     osDialectList += aosTokens[i];  | 
6908  | 0  |                     osDialectList += "'";  | 
6909  | 0  |                 }  | 
6910  | 0  |             }  | 
6911  | 0  |         }  | 
6912  | 0  |         CPLError(CE_Warning, CPLE_NotSupported,  | 
6913  | 0  |                  "Dialect '%s' is unsupported. Only supported dialects are %s. "  | 
6914  | 0  |                  "Defaulting to OGRSQL",  | 
6915  | 0  |                  pszDialect, osDialectList.c_str());  | 
6916  | 0  |     }  | 
6917  |  |  | 
6918  |  |     /* -------------------------------------------------------------------- */  | 
6919  |  |     /*      Handle CREATE INDEX statements specially.                       */  | 
6920  |  |     /* -------------------------------------------------------------------- */  | 
6921  | 0  |     if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))  | 
6922  | 0  |     { | 
6923  | 0  |         ProcessSQLCreateIndex(pszStatement);  | 
6924  | 0  |         return nullptr;  | 
6925  | 0  |     }  | 
6926  |  |  | 
6927  |  |     /* -------------------------------------------------------------------- */  | 
6928  |  |     /*      Handle DROP INDEX statements specially.                         */  | 
6929  |  |     /* -------------------------------------------------------------------- */  | 
6930  | 0  |     if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))  | 
6931  | 0  |     { | 
6932  | 0  |         ProcessSQLDropIndex(pszStatement);  | 
6933  | 0  |         return nullptr;  | 
6934  | 0  |     }  | 
6935  |  |  | 
6936  |  |     /* -------------------------------------------------------------------- */  | 
6937  |  |     /*      Handle DROP TABLE statements specially.                         */  | 
6938  |  |     /* -------------------------------------------------------------------- */  | 
6939  | 0  |     if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))  | 
6940  | 0  |     { | 
6941  | 0  |         ProcessSQLDropTable(pszStatement);  | 
6942  | 0  |         return nullptr;  | 
6943  | 0  |     }  | 
6944  |  |  | 
6945  |  |     /* -------------------------------------------------------------------- */  | 
6946  |  |     /*      Handle ALTER TABLE statements specially.                        */  | 
6947  |  |     /* -------------------------------------------------------------------- */  | 
6948  | 0  |     if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))  | 
6949  | 0  |     { | 
6950  | 0  |         char **papszTokens = CSLTokenizeString(pszStatement);  | 
6951  | 0  |         const int nTokens = CSLCount(papszTokens);  | 
6952  | 0  |         if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))  | 
6953  | 0  |         { | 
6954  | 0  |             ProcessSQLAlterTableAddColumn(pszStatement);  | 
6955  | 0  |             CSLDestroy(papszTokens);  | 
6956  | 0  |             return nullptr;  | 
6957  | 0  |         }  | 
6958  | 0  |         else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))  | 
6959  | 0  |         { | 
6960  | 0  |             ProcessSQLAlterTableDropColumn(pszStatement);  | 
6961  | 0  |             CSLDestroy(papszTokens);  | 
6962  | 0  |             return nullptr;  | 
6963  | 0  |         }  | 
6964  | 0  |         else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&  | 
6965  | 0  |                  EQUAL(papszTokens[4], "TO"))  | 
6966  | 0  |         { | 
6967  | 0  |             const char *pszSrcTableName = papszTokens[2];  | 
6968  | 0  |             const char *pszDstTableName = papszTokens[5];  | 
6969  | 0  |             auto poSrcLayer = GetLayerByName(pszSrcTableName);  | 
6970  | 0  |             if (poSrcLayer)  | 
6971  | 0  |             { | 
6972  | 0  |                 CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));  | 
6973  | 0  |             }  | 
6974  | 0  |             else  | 
6975  | 0  |             { | 
6976  | 0  |                 CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");  | 
6977  | 0  |             }  | 
6978  | 0  |             CSLDestroy(papszTokens);  | 
6979  | 0  |             return nullptr;  | 
6980  | 0  |         }  | 
6981  | 0  |         else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))  | 
6982  | 0  |         { | 
6983  | 0  |             ProcessSQLAlterTableRenameColumn(pszStatement);  | 
6984  | 0  |             CSLDestroy(papszTokens);  | 
6985  | 0  |             return nullptr;  | 
6986  | 0  |         }  | 
6987  | 0  |         else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))  | 
6988  | 0  |         { | 
6989  | 0  |             ProcessSQLAlterTableAlterColumn(pszStatement);  | 
6990  | 0  |             CSLDestroy(papszTokens);  | 
6991  | 0  |             return nullptr;  | 
6992  | 0  |         }  | 
6993  | 0  |         else  | 
6994  | 0  |         { | 
6995  | 0  |             CPLError(CE_Failure, CPLE_AppDefined,  | 
6996  | 0  |                      "Unsupported ALTER TABLE command : %s", pszStatement);  | 
6997  | 0  |             CSLDestroy(papszTokens);  | 
6998  | 0  |             return nullptr;  | 
6999  | 0  |         }  | 
7000  | 0  |     }  | 
7001  |  |  | 
7002  |  |     /* -------------------------------------------------------------------- */  | 
7003  |  |     /*      Preparse the SQL statement.                                     */  | 
7004  |  |     /* -------------------------------------------------------------------- */  | 
7005  | 0  |     swq_select *psSelectInfo = new swq_select();  | 
7006  | 0  |     swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;  | 
7007  | 0  |     if (poSelectParseOptions != nullptr)  | 
7008  | 0  |         poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;  | 
7009  | 0  |     if (psSelectInfo->preparse(pszStatement,  | 
7010  | 0  |                                poCustomFuncRegistrar != nullptr) != CE_None)  | 
7011  | 0  |     { | 
7012  | 0  |         delete psSelectInfo;  | 
7013  | 0  |         return nullptr;  | 
7014  | 0  |     }  | 
7015  |  |  | 
7016  |  |     /* -------------------------------------------------------------------- */  | 
7017  |  |     /*      If there is no UNION ALL, build result layer.                   */  | 
7018  |  |     /* -------------------------------------------------------------------- */  | 
7019  | 0  |     if (psSelectInfo->poOtherSelect == nullptr)  | 
7020  | 0  |     { | 
7021  | 0  |         return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,  | 
7022  | 0  |                                         pszDialect, poSelectParseOptions);  | 
7023  | 0  |     }  | 
7024  |  |  | 
7025  |  |     /* -------------------------------------------------------------------- */  | 
7026  |  |     /*      Build result union layer.                                       */  | 
7027  |  |     /* -------------------------------------------------------------------- */  | 
7028  | 0  |     int nSrcLayers = 0;  | 
7029  | 0  |     OGRLayer **papoSrcLayers = nullptr;  | 
7030  |  | 
  | 
7031  | 0  |     do  | 
7032  | 0  |     { | 
7033  | 0  |         swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;  | 
7034  | 0  |         psSelectInfo->poOtherSelect = nullptr;  | 
7035  |  | 
  | 
7036  | 0  |         OGRLayer *poLayer = BuildLayerFromSelectInfo(  | 
7037  | 0  |             psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);  | 
7038  | 0  |         if (poLayer == nullptr)  | 
7039  | 0  |         { | 
7040  |  |             // Each source layer owns an independent select info.  | 
7041  | 0  |             for (int i = 0; i < nSrcLayers; ++i)  | 
7042  | 0  |                 delete papoSrcLayers[i];  | 
7043  | 0  |             CPLFree(papoSrcLayers);  | 
7044  |  |  | 
7045  |  |             // So we just have to destroy the remaining select info.  | 
7046  | 0  |             delete psNextSelectInfo;  | 
7047  |  | 
  | 
7048  | 0  |             return nullptr;  | 
7049  | 0  |         }  | 
7050  | 0  |         else  | 
7051  | 0  |         { | 
7052  | 0  |             papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(  | 
7053  | 0  |                 papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));  | 
7054  | 0  |             papoSrcLayers[nSrcLayers] = poLayer;  | 
7055  | 0  |             ++nSrcLayers;  | 
7056  |  | 
  | 
7057  | 0  |             psSelectInfo = psNextSelectInfo;  | 
7058  | 0  |         }  | 
7059  | 0  |     } while (psSelectInfo != nullptr);  | 
7060  |  |  | 
7061  | 0  |     return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE); | 
7062  | 0  | }  | 
7063  |  |  | 
7064  |  | //! @endcond  | 
7065  |  |  | 
7066  |  | /************************************************************************/  | 
7067  |  | /*                             AbortSQL()                             */  | 
7068  |  | /************************************************************************/  | 
7069  |  |  | 
7070  |  | /**  | 
7071  |  |  \brief Abort any SQL statement running in the data store.  | 
7072  |  |  | 
7073  |  |  This function can be safely called from any thread (pending that the dataset  | 
7074  |  |  object is still alive). Driver implementations will make sure that it can be  | 
7075  |  |  called in a thread-safe way.  | 
7076  |  |  | 
7077  |  |  This might not be implemented by all drivers. At time of writing, only SQLite,  | 
7078  |  |  GPKG and PG drivers implement it  | 
7079  |  |  | 
7080  |  |  This method is the same as the C method GDALDatasetAbortSQL()  | 
7081  |  |  | 
7082  |  |  @since GDAL 3.2.0  | 
7083  |  |  | 
7084  |  |  | 
7085  |  | */  | 
7086  |  |  | 
7087  |  | OGRErr GDALDataset::AbortSQL()  | 
7088  | 0  | { | 
7089  | 0  |     CPLError(CE_Failure, CPLE_NotSupported,  | 
7090  | 0  |              "AbortSQL is not supported for this driver.");  | 
7091  | 0  |     return OGRERR_UNSUPPORTED_OPERATION;  | 
7092  | 0  | }  | 
7093  |  |  | 
7094  |  | /************************************************************************/  | 
7095  |  | /*                        BuildLayerFromSelectInfo()                    */  | 
7096  |  | /************************************************************************/  | 
7097  |  |  | 
7098  |  | struct GDALSQLParseInfo  | 
7099  |  | { | 
7100  |  |     swq_field_list sFieldList;  | 
7101  |  |     int nExtraDSCount;  | 
7102  |  |     GDALDataset **papoExtraDS;  | 
7103  |  |     char *pszWHERE;  | 
7104  |  | };  | 
7105  |  |  | 
7106  |  | OGRLayer *GDALDataset::BuildLayerFromSelectInfo(  | 
7107  |  |     swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,  | 
7108  |  |     const char *pszDialect, swq_select_parse_options *poSelectParseOptions)  | 
7109  | 0  | { | 
7110  | 0  |     std::unique_ptr<swq_select> psSelectInfoUnique(psSelectInfo);  | 
7111  |  | 
  | 
7112  | 0  |     std::unique_ptr<OGRGenSQLResultsLayer> poResults;  | 
7113  | 0  |     GDALSQLParseInfo *psParseInfo =  | 
7114  | 0  |         BuildParseInfo(psSelectInfoUnique.get(), poSelectParseOptions);  | 
7115  |  | 
  | 
7116  | 0  |     if (psParseInfo)  | 
7117  | 0  |     { | 
7118  | 0  |         const auto nErrorCounter = CPLGetErrorCounter();  | 
7119  | 0  |         poResults = std::make_unique<OGRGenSQLResultsLayer>(  | 
7120  | 0  |             this, std::move(psSelectInfoUnique), poSpatialFilter,  | 
7121  | 0  |             psParseInfo->pszWHERE, pszDialect);  | 
7122  | 0  |         if (CPLGetErrorCounter() > nErrorCounter &&  | 
7123  | 0  |             CPLGetLastErrorType() != CE_None)  | 
7124  | 0  |             poResults.reset();  | 
7125  | 0  |     }  | 
7126  |  | 
  | 
7127  | 0  |     DestroyParseInfo(psParseInfo);  | 
7128  |  | 
  | 
7129  | 0  |     return poResults.release();  | 
7130  | 0  | }  | 
7131  |  |  | 
7132  |  | /************************************************************************/  | 
7133  |  | /*                             DestroyParseInfo()                       */  | 
7134  |  | /************************************************************************/  | 
7135  |  |  | 
7136  |  | //! @cond Doxygen_Suppress  | 
7137  |  | void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)  | 
7138  | 0  | { | 
7139  | 0  |     if (psParseInfo == nullptr)  | 
7140  | 0  |         return;  | 
7141  |  |  | 
7142  | 0  |     CPLFree(psParseInfo->sFieldList.names);  | 
7143  | 0  |     CPLFree(psParseInfo->sFieldList.types);  | 
7144  | 0  |     CPLFree(psParseInfo->sFieldList.table_ids);  | 
7145  | 0  |     CPLFree(psParseInfo->sFieldList.ids);  | 
7146  |  |  | 
7147  |  |     // Release the datasets we have opened with OGROpenShared()  | 
7148  |  |     // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself  | 
7149  |  |     // has taken a reference on them, which it will release in its  | 
7150  |  |     // destructor.  | 
7151  | 0  |     for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)  | 
7152  | 0  |         GDALClose(psParseInfo->papoExtraDS[iEDS]);  | 
7153  |  | 
  | 
7154  | 0  |     CPLFree(psParseInfo->papoExtraDS);  | 
7155  | 0  |     CPLFree(psParseInfo->pszWHERE);  | 
7156  | 0  |     CPLFree(psParseInfo);  | 
7157  | 0  | }  | 
7158  |  |  | 
7159  |  | /************************************************************************/  | 
7160  |  | /*                            BuildParseInfo()                          */  | 
7161  |  | /************************************************************************/  | 
7162  |  |  | 
7163  |  | GDALSQLParseInfo *  | 
7164  |  | GDALDataset::BuildParseInfo(swq_select *psSelectInfo,  | 
7165  |  |                             swq_select_parse_options *poSelectParseOptions)  | 
7166  | 0  | { | 
7167  | 0  |     int nFirstLayerFirstSpecialFieldIndex = 0;  | 
7168  |  | 
  | 
7169  | 0  |     GDALSQLParseInfo *psParseInfo =  | 
7170  | 0  |         static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));  | 
7171  |  |  | 
7172  |  |     /* -------------------------------------------------------------------- */  | 
7173  |  |     /*      Validate that all the source tables are recognized, count       */  | 
7174  |  |     /*      fields.                                                         */  | 
7175  |  |     /* -------------------------------------------------------------------- */  | 
7176  | 0  |     int nFieldCount = 0;  | 
7177  |  | 
  | 
7178  | 0  |     for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)  | 
7179  | 0  |     { | 
7180  | 0  |         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;  | 
7181  | 0  |         GDALDataset *poTableDS = this;  | 
7182  |  | 
  | 
7183  | 0  |         if (psTableDef->data_source != nullptr)  | 
7184  | 0  |         { | 
7185  | 0  |             poTableDS = GDALDataset::FromHandle(  | 
7186  | 0  |                 OGROpenShared(psTableDef->data_source, FALSE, nullptr));  | 
7187  | 0  |             if (poTableDS == nullptr)  | 
7188  | 0  |             { | 
7189  | 0  |                 if (strlen(CPLGetLastErrorMsg()) == 0)  | 
7190  | 0  |                     CPLError(CE_Failure, CPLE_AppDefined,  | 
7191  | 0  |                              "Unable to open secondary datasource "  | 
7192  | 0  |                              "`%s' required by JOIN.",  | 
7193  | 0  |                              psTableDef->data_source);  | 
7194  |  | 
  | 
7195  | 0  |                 DestroyParseInfo(psParseInfo);  | 
7196  | 0  |                 return nullptr;  | 
7197  | 0  |             }  | 
7198  |  |  | 
7199  |  |             // Keep in an array to release at the end of this function.  | 
7200  | 0  |             psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(  | 
7201  | 0  |                 psParseInfo->papoExtraDS,  | 
7202  | 0  |                 sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));  | 
7203  | 0  |             psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;  | 
7204  | 0  |         }  | 
7205  |  |  | 
7206  | 0  |         OGRLayer *poSrcLayer =  | 
7207  | 0  |             poTableDS->GetLayerByName(psTableDef->table_name);  | 
7208  |  | 
  | 
7209  | 0  |         if (poSrcLayer == nullptr)  | 
7210  | 0  |         { | 
7211  | 0  |             CPLError(CE_Failure, CPLE_AppDefined,  | 
7212  | 0  |                      "SELECT from table %s failed, no such table/featureclass.",  | 
7213  | 0  |                      psTableDef->table_name);  | 
7214  |  | 
  | 
7215  | 0  |             DestroyParseInfo(psParseInfo);  | 
7216  | 0  |             return nullptr;  | 
7217  | 0  |         }  | 
7218  |  |  | 
7219  | 0  |         nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();  | 
7220  | 0  |         if (iTable == 0 ||  | 
7221  | 0  |             (poSelectParseOptions &&  | 
7222  | 0  |              poSelectParseOptions->bAddSecondaryTablesGeometryFields))  | 
7223  | 0  |             nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();  | 
7224  |  | 
  | 
7225  | 0  |         const char *pszFID = poSrcLayer->GetFIDColumn();  | 
7226  | 0  |         if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&  | 
7227  | 0  |             poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)  | 
7228  | 0  |             nFieldCount++;  | 
7229  | 0  |     }  | 
7230  |  |  | 
7231  |  |     /* -------------------------------------------------------------------- */  | 
7232  |  |     /*      Build the field list for all indicated tables.                  */  | 
7233  |  |     /* -------------------------------------------------------------------- */  | 
7234  |  |  | 
7235  | 0  |     psParseInfo->sFieldList.table_count = psSelectInfo->table_count;  | 
7236  | 0  |     psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;  | 
7237  |  | 
  | 
7238  | 0  |     psParseInfo->sFieldList.count = 0;  | 
7239  | 0  |     psParseInfo->sFieldList.names = static_cast<char **>(  | 
7240  | 0  |         CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));  | 
7241  | 0  |     psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(  | 
7242  | 0  |         sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));  | 
7243  | 0  |     psParseInfo->sFieldList.table_ids = static_cast<int *>(  | 
7244  | 0  |         CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));  | 
7245  | 0  |     psParseInfo->sFieldList.ids = static_cast<int *>(  | 
7246  | 0  |         CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));  | 
7247  |  | 
  | 
7248  | 0  |     bool bIsFID64 = false;  | 
7249  | 0  |     for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)  | 
7250  | 0  |     { | 
7251  | 0  |         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;  | 
7252  | 0  |         GDALDataset *poTableDS = this;  | 
7253  |  | 
  | 
7254  | 0  |         if (psTableDef->data_source != nullptr)  | 
7255  | 0  |         { | 
7256  | 0  |             poTableDS = GDALDataset::FromHandle(  | 
7257  | 0  |                 OGROpenShared(psTableDef->data_source, FALSE, nullptr));  | 
7258  | 0  |             CPLAssert(poTableDS != nullptr);  | 
7259  | 0  |             poTableDS->Dereference();  | 
7260  | 0  |         }  | 
7261  |  |  | 
7262  | 0  |         OGRLayer *poSrcLayer =  | 
7263  | 0  |             poTableDS->GetLayerByName(psTableDef->table_name);  | 
7264  |  | 
  | 
7265  | 0  |         for (int iField = 0;  | 
7266  | 0  |              iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)  | 
7267  | 0  |         { | 
7268  | 0  |             OGRFieldDefn *poFDefn =  | 
7269  | 0  |                 poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);  | 
7270  | 0  |             const int iOutField = psParseInfo->sFieldList.count++;  | 
7271  | 0  |             psParseInfo->sFieldList.names[iOutField] =  | 
7272  | 0  |                 const_cast<char *>(poFDefn->GetNameRef());  | 
7273  | 0  |             if (poFDefn->GetType() == OFTInteger)  | 
7274  | 0  |             { | 
7275  | 0  |                 if (poFDefn->GetSubType() == OFSTBoolean)  | 
7276  | 0  |                     psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;  | 
7277  | 0  |                 else  | 
7278  | 0  |                     psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;  | 
7279  | 0  |             }  | 
7280  | 0  |             else if (poFDefn->GetType() == OFTInteger64)  | 
7281  | 0  |             { | 
7282  | 0  |                 if (poFDefn->GetSubType() == OFSTBoolean)  | 
7283  | 0  |                     psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;  | 
7284  | 0  |                 else  | 
7285  | 0  |                     psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;  | 
7286  | 0  |             }  | 
7287  | 0  |             else if (poFDefn->GetType() == OFTReal)  | 
7288  | 0  |                 psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;  | 
7289  | 0  |             else if (poFDefn->GetType() == OFTString)  | 
7290  | 0  |                 psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;  | 
7291  | 0  |             else if (poFDefn->GetType() == OFTTime)  | 
7292  | 0  |                 psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;  | 
7293  | 0  |             else if (poFDefn->GetType() == OFTDate)  | 
7294  | 0  |                 psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;  | 
7295  | 0  |             else if (poFDefn->GetType() == OFTDateTime)  | 
7296  | 0  |                 psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;  | 
7297  | 0  |             else  | 
7298  | 0  |                 psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;  | 
7299  |  | 
  | 
7300  | 0  |             psParseInfo->sFieldList.table_ids[iOutField] = iTable;  | 
7301  | 0  |             psParseInfo->sFieldList.ids[iOutField] = iField;  | 
7302  | 0  |         }  | 
7303  |  | 
  | 
7304  | 0  |         if (iTable == 0)  | 
7305  | 0  |         { | 
7306  | 0  |             nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;  | 
7307  | 0  |         }  | 
7308  |  | 
  | 
7309  | 0  |         if (iTable == 0 ||  | 
7310  | 0  |             (poSelectParseOptions &&  | 
7311  | 0  |              poSelectParseOptions->bAddSecondaryTablesGeometryFields))  | 
7312  | 0  |         { | 
7313  |  | 
  | 
7314  | 0  |             for (int iField = 0;  | 
7315  | 0  |                  iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();  | 
7316  | 0  |                  iField++)  | 
7317  | 0  |             { | 
7318  | 0  |                 OGRGeomFieldDefn *poFDefn =  | 
7319  | 0  |                     poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);  | 
7320  | 0  |                 const int iOutField = psParseInfo->sFieldList.count++;  | 
7321  | 0  |                 psParseInfo->sFieldList.names[iOutField] =  | 
7322  | 0  |                     const_cast<char *>(poFDefn->GetNameRef());  | 
7323  | 0  |                 if (*psParseInfo->sFieldList.names[iOutField] == '\0')  | 
7324  | 0  |                     psParseInfo->sFieldList.names[iOutField] =  | 
7325  | 0  |                         const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);  | 
7326  | 0  |                 psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;  | 
7327  |  | 
  | 
7328  | 0  |                 psParseInfo->sFieldList.table_ids[iOutField] = iTable;  | 
7329  | 0  |                 psParseInfo->sFieldList.ids[iOutField] =  | 
7330  | 0  |                     GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(  | 
7331  | 0  |                         poSrcLayer->GetLayerDefn(), iField);  | 
7332  | 0  |             }  | 
7333  | 0  |         }  | 
7334  |  | 
  | 
7335  | 0  |         if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&  | 
7336  | 0  |             EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))  | 
7337  | 0  |         { | 
7338  | 0  |             bIsFID64 = true;  | 
7339  | 0  |         }  | 
7340  | 0  |     }  | 
7341  |  |  | 
7342  |  |     /* -------------------------------------------------------------------- */  | 
7343  |  |     /*      Expand '*' in 'SELECT *' now before we add the pseudo fields    */  | 
7344  |  |     /* -------------------------------------------------------------------- */  | 
7345  | 0  |     const bool bAlwaysPrefixWithTableName =  | 
7346  | 0  |         poSelectParseOptions &&  | 
7347  | 0  |         poSelectParseOptions->bAlwaysPrefixWithTableName;  | 
7348  | 0  |     if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,  | 
7349  | 0  |                                       bAlwaysPrefixWithTableName) != CE_None)  | 
7350  | 0  |     { | 
7351  | 0  |         DestroyParseInfo(psParseInfo);  | 
7352  | 0  |         return nullptr;  | 
7353  | 0  |     }  | 
7354  |  |  | 
7355  | 0  |     for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)  | 
7356  | 0  |     { | 
7357  | 0  |         psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =  | 
7358  | 0  |             const_cast<char *>(SpecialFieldNames[iField]);  | 
7359  | 0  |         psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =  | 
7360  | 0  |             (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64  | 
7361  | 0  |                                             : SpecialFieldTypes[iField];  | 
7362  | 0  |         psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;  | 
7363  | 0  |         psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =  | 
7364  | 0  |             nFirstLayerFirstSpecialFieldIndex + iField;  | 
7365  | 0  |         psParseInfo->sFieldList.count++;  | 
7366  | 0  |     }  | 
7367  |  |  | 
7368  |  |     /* In the case a layer has an explicit FID column name, then add it */  | 
7369  |  |     /* so it can be selected */  | 
7370  | 0  |     for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)  | 
7371  | 0  |     { | 
7372  | 0  |         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;  | 
7373  | 0  |         GDALDataset *poTableDS = this;  | 
7374  |  | 
  | 
7375  | 0  |         if (psTableDef->data_source != nullptr)  | 
7376  | 0  |         { | 
7377  | 0  |             poTableDS = GDALDataset::FromHandle(  | 
7378  | 0  |                 OGROpenShared(psTableDef->data_source, FALSE, nullptr));  | 
7379  | 0  |             CPLAssert(poTableDS != nullptr);  | 
7380  | 0  |             poTableDS->Dereference();  | 
7381  | 0  |         }  | 
7382  |  |  | 
7383  | 0  |         OGRLayer *poSrcLayer =  | 
7384  | 0  |             poTableDS->GetLayerByName(psTableDef->table_name);  | 
7385  |  | 
  | 
7386  | 0  |         const char *pszFID = poSrcLayer->GetFIDColumn();  | 
7387  | 0  |         if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&  | 
7388  | 0  |             poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)  | 
7389  | 0  |         { | 
7390  | 0  |             const int iOutField = psParseInfo->sFieldList.count++;  | 
7391  | 0  |             psParseInfo->sFieldList.names[iOutField] =  | 
7392  | 0  |                 const_cast<char *>(pszFID);  | 
7393  | 0  |             if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&  | 
7394  | 0  |                 EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))  | 
7395  | 0  |             { | 
7396  | 0  |                 psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;  | 
7397  | 0  |             }  | 
7398  | 0  |             else  | 
7399  | 0  |             { | 
7400  | 0  |                 psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;  | 
7401  | 0  |             }  | 
7402  | 0  |             psParseInfo->sFieldList.table_ids[iOutField] = iTable;  | 
7403  | 0  |             psParseInfo->sFieldList.ids[iOutField] =  | 
7404  | 0  |                 poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;  | 
7405  | 0  |         }  | 
7406  | 0  |     }  | 
7407  |  |  | 
7408  |  |     /* -------------------------------------------------------------------- */  | 
7409  |  |     /*      Finish the parse operation.                                     */  | 
7410  |  |     /* -------------------------------------------------------------------- */  | 
7411  | 0  |     if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=  | 
7412  | 0  |         CE_None)  | 
7413  | 0  |     { | 
7414  | 0  |         DestroyParseInfo(psParseInfo);  | 
7415  | 0  |         return nullptr;  | 
7416  | 0  |     }  | 
7417  |  |  | 
7418  |  |     /* -------------------------------------------------------------------- */  | 
7419  |  |     /*      Extract the WHERE expression to use separately.                 */  | 
7420  |  |     /* -------------------------------------------------------------------- */  | 
7421  | 0  |     if (psSelectInfo->where_expr != nullptr)  | 
7422  | 0  |     { | 
7423  | 0  |         psParseInfo->pszWHERE =  | 
7424  | 0  |             psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');  | 
7425  |  |         // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );  | 
7426  | 0  |     }  | 
7427  |  | 
  | 
7428  | 0  |     return psParseInfo;  | 
7429  | 0  | }  | 
7430  |  |  | 
7431  |  | //! @endcond  | 
7432  |  |  | 
7433  |  | /************************************************************************/  | 
7434  |  | /*                          ReleaseResultSet()                          */  | 
7435  |  | /************************************************************************/  | 
7436  |  |  | 
7437  |  | /**  | 
7438  |  |  \brief Release results of ExecuteSQL().  | 
7439  |  |  | 
7440  |  |  This method should only be used to deallocate OGRLayers resulting from  | 
7441  |  |  an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a  | 
7442  |  |  results set before destroying the GDALDataset may cause errors.  | 
7443  |  |  | 
7444  |  |  This method is the same as the C function GDALDatasetReleaseResultSet() and the  | 
7445  |  |  deprecated OGR_DS_ReleaseResultSet().  | 
7446  |  |  | 
7447  |  |  In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
7448  |  |  | 
7449  |  |  @param poResultsSet the result of a previous ExecuteSQL() call.  | 
7450  |  | */  | 
7451  |  |  | 
7452  |  | void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)  | 
7453  |  |  | 
7454  | 0  | { | 
7455  | 0  |     delete poResultsSet;  | 
7456  | 0  | }  | 
7457  |  |  | 
7458  |  | /************************************************************************/  | 
7459  |  | /*                            GetStyleTable()                           */  | 
7460  |  | /************************************************************************/  | 
7461  |  |  | 
7462  |  | /**  | 
7463  |  |  \brief Returns dataset style table.  | 
7464  |  |  | 
7465  |  |  This method is the same as the C function GDALDatasetGetStyleTable() and the  | 
7466  |  |  deprecated OGR_DS_GetStyleTable().  | 
7467  |  |  | 
7468  |  |  In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
7469  |  |  | 
7470  |  |  @return pointer to a style table which should not be modified or freed by the  | 
7471  |  |  caller.  | 
7472  |  | */  | 
7473  |  |  | 
7474  |  | OGRStyleTable *GDALDataset::GetStyleTable()  | 
7475  | 0  | { | 
7476  | 0  |     return m_poStyleTable;  | 
7477  | 0  | }  | 
7478  |  |  | 
7479  |  | /************************************************************************/  | 
7480  |  | /*                         SetStyleTableDirectly()                      */  | 
7481  |  | /************************************************************************/  | 
7482  |  |  | 
7483  |  | /**  | 
7484  |  |  \brief Set dataset style table.  | 
7485  |  |  | 
7486  |  |  This method operate exactly as SetStyleTable() except that it  | 
7487  |  |  assumes ownership of the passed table.  | 
7488  |  |  | 
7489  |  |  This method is the same as the C function GDALDatasetSetStyleTableDirectly()  | 
7490  |  |  and the deprecated OGR_DS_SetStyleTableDirectly().  | 
7491  |  |  | 
7492  |  |  In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
7493  |  |  | 
7494  |  |  @param poStyleTable pointer to style table to set  | 
7495  |  |  | 
7496  |  | */  | 
7497  |  | void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)  | 
7498  | 0  | { | 
7499  | 0  |     if (m_poStyleTable)  | 
7500  | 0  |         delete m_poStyleTable;  | 
7501  | 0  |     m_poStyleTable = poStyleTable;  | 
7502  | 0  | }  | 
7503  |  |  | 
7504  |  | /************************************************************************/  | 
7505  |  | /*                            SetStyleTable()                           */  | 
7506  |  | /************************************************************************/  | 
7507  |  |  | 
7508  |  | /**  | 
7509  |  |  \brief Set dataset style table.  | 
7510  |  |  | 
7511  |  |  This method operate exactly as SetStyleTableDirectly() except  | 
7512  |  |  that it does not assume ownership of the passed table.  | 
7513  |  |  | 
7514  |  |  This method is the same as the C function GDALDatasetSetStyleTable() and the  | 
7515  |  |  deprecated OGR_DS_SetStyleTable().  | 
7516  |  |  | 
7517  |  |  In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
7518  |  |  | 
7519  |  |  @param poStyleTable pointer to style table to set  | 
7520  |  |  | 
7521  |  | */  | 
7522  |  |  | 
7523  |  | void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)  | 
7524  | 0  | { | 
7525  | 0  |     if (m_poStyleTable)  | 
7526  | 0  |         delete m_poStyleTable;  | 
7527  | 0  |     if (poStyleTable)  | 
7528  | 0  |         m_poStyleTable = poStyleTable->Clone();  | 
7529  | 0  | }  | 
7530  |  |  | 
7531  |  | /************************************************************************/  | 
7532  |  | /*                         IsGenericSQLDialect()                        */  | 
7533  |  | /************************************************************************/  | 
7534  |  |  | 
7535  |  | //! @cond Doxygen_Suppress  | 
7536  |  | int GDALDataset::IsGenericSQLDialect(const char *pszDialect)  | 
7537  | 0  | { | 
7538  | 0  |     return pszDialect != nullptr &&  | 
7539  | 0  |            (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));  | 
7540  | 0  | }  | 
7541  |  |  | 
7542  |  | //! @endcond  | 
7543  |  |  | 
7544  |  | /************************************************************************/  | 
7545  |  | /*                            GetLayerCount()                           */  | 
7546  |  | /************************************************************************/  | 
7547  |  |  | 
7548  |  | /**  | 
7549  |  |  \brief Get the number of layers in this dataset.  | 
7550  |  |  | 
7551  |  |  This method is the same as the C function GDALDatasetGetLayerCount(),  | 
7552  |  |  and the deprecated OGR_DS_GetLayerCount().  | 
7553  |  |  | 
7554  |  |  In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
7555  |  |  | 
7556  |  |  @return layer count.  | 
7557  |  | */  | 
7558  |  |  | 
7559  |  | int GDALDataset::GetLayerCount()  | 
7560  | 0  | { | 
7561  | 0  |     return 0;  | 
7562  | 0  | }  | 
7563  |  |  | 
7564  |  | /************************************************************************/  | 
7565  |  | /*                                GetLayer()                            */  | 
7566  |  | /************************************************************************/  | 
7567  |  |  | 
7568  |  | /**  | 
7569  |  |  \fn GDALDataset::GetLayer(int)  | 
7570  |  |  \brief Fetch a layer by index.  | 
7571  |  |  | 
7572  |  |  The returned layer remains owned by the  | 
7573  |  |  GDALDataset and should not be deleted by the application.  | 
7574  |  |  | 
7575  |  |  See GetLayers() for a C++ iterator version of this method.  | 
7576  |  |  | 
7577  |  |  This method is the same as the C function GDALDatasetGetLayer() and the  | 
7578  |  |  deprecated OGR_DS_GetLayer().  | 
7579  |  |  | 
7580  |  |  In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
7581  |  |  | 
7582  |  |  @param iLayer a layer number between 0 and GetLayerCount()-1.  | 
7583  |  |  | 
7584  |  |  @return the layer, or NULL if iLayer is out of range or an error occurs.  | 
7585  |  |  | 
7586  |  |  @see GetLayers()  | 
7587  |  | */  | 
7588  |  |  | 
7589  |  | OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer)  | 
7590  | 0  | { | 
7591  | 0  |     return nullptr;  | 
7592  | 0  | }  | 
7593  |  |  | 
7594  |  | /************************************************************************/  | 
7595  |  | /*                                IsLayerPrivate()                      */  | 
7596  |  | /************************************************************************/  | 
7597  |  |  | 
7598  |  | /**  | 
7599  |  |  \fn GDALDataset::IsLayerPrivate(int)  | 
7600  |  |  \brief Returns true if the layer at the specified index is deemed a private or  | 
7601  |  |  system table, or an internal detail only.  | 
7602  |  |  | 
7603  |  |  This method is the same as the C function GDALDatasetIsLayerPrivate().  | 
7604  |  |  | 
7605  |  |  @param iLayer a layer number between 0 and GetLayerCount()-1.  | 
7606  |  |  | 
7607  |  |  @return true if the layer is a private or system table.  | 
7608  |  |  | 
7609  |  |  @since GDAL 3.4  | 
7610  |  | */  | 
7611  |  |  | 
7612  |  | bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const  | 
7613  | 0  | { | 
7614  | 0  |     return false;  | 
7615  | 0  | }  | 
7616  |  |  | 
7617  |  | /************************************************************************/  | 
7618  |  | /*                           ResetReading()                             */  | 
7619  |  | /************************************************************************/  | 
7620  |  |  | 
7621  |  | /**  | 
7622  |  |  \brief Reset feature reading to start on the first feature.  | 
7623  |  |  | 
7624  |  |  This affects GetNextFeature().  | 
7625  |  |  | 
7626  |  |  Depending on drivers, this may also have the side effect of calling  | 
7627  |  |  OGRLayer::ResetReading() on the layers of this dataset.  | 
7628  |  |  | 
7629  |  |  This method is the same as the C function GDALDatasetResetReading().  | 
7630  |  |  | 
7631  |  |  @since GDAL 2.2  | 
7632  |  | */  | 
7633  |  | void GDALDataset::ResetReading()  | 
7634  | 0  | { | 
7635  | 0  |     if (!m_poPrivate)  | 
7636  | 0  |         return;  | 
7637  | 0  |     m_poPrivate->nCurrentLayerIdx = 0;  | 
7638  | 0  |     m_poPrivate->nLayerCount = -1;  | 
7639  | 0  |     m_poPrivate->poCurrentLayer = nullptr;  | 
7640  | 0  |     m_poPrivate->nFeatureReadInLayer = 0;  | 
7641  | 0  |     m_poPrivate->nFeatureReadInDataset = 0;  | 
7642  | 0  |     m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;  | 
7643  | 0  |     m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;  | 
7644  | 0  | }  | 
7645  |  |  | 
7646  |  | /************************************************************************/  | 
7647  |  | /*                         GDALDatasetResetReading()                    */  | 
7648  |  | /************************************************************************/  | 
7649  |  |  | 
7650  |  | /**  | 
7651  |  |  \brief Reset feature reading to start on the first feature.  | 
7652  |  |  | 
7653  |  |  This affects GDALDatasetGetNextFeature().  | 
7654  |  |  | 
7655  |  |  Depending on drivers, this may also have the side effect of calling  | 
7656  |  |  OGR_L_ResetReading() on the layers of this dataset.  | 
7657  |  |  | 
7658  |  |  This method is the same as the C++ method GDALDataset::ResetReading()  | 
7659  |  |  | 
7660  |  |  @param hDS dataset handle  | 
7661  |  |  @since GDAL 2.2  | 
7662  |  | */  | 
7663  |  | void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)  | 
7664  | 0  | { | 
7665  | 0  |     VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");  | 
7666  |  |  | 
7667  | 0  |     return GDALDataset::FromHandle(hDS)->ResetReading();  | 
7668  | 0  | }  | 
7669  |  |  | 
7670  |  | /************************************************************************/  | 
7671  |  | /*                          GetNextFeature()                            */  | 
7672  |  | /************************************************************************/  | 
7673  |  |  | 
7674  |  | /**  | 
7675  |  |  \brief Fetch the next available feature from this dataset.  | 
7676  |  |  | 
7677  |  |  This method is intended for the few drivers where OGRLayer::GetNextFeature()  | 
7678  |  |  is not efficient, but in general OGRLayer::GetNextFeature() is a more  | 
7679  |  |  natural API.  | 
7680  |  |  | 
7681  |  |  See GetFeatures() for a C++ iterator version of this method.  | 
7682  |  |  | 
7683  |  |  The returned feature becomes the responsibility of the caller to  | 
7684  |  |  delete with OGRFeature::DestroyFeature().  | 
7685  |  |  | 
7686  |  |  Depending on the driver, this method may return features from layers in a  | 
7687  |  |  non sequential way. This is what may happen when the  | 
7688  |  |  ODsCRandomLayerRead capability is declared (for example for the  | 
7689  |  |  OSM and GMLAS drivers). When datasets declare this capability, it is strongly  | 
7690  |  |  advised to use GDALDataset::GetNextFeature() instead of  | 
7691  |  |  OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub  | 
7692  |  |  implementation.  | 
7693  |  |  | 
7694  |  |  The default implementation, used by most drivers, will  | 
7695  |  |  however iterate over each layer, and then over each feature within this  | 
7696  |  |  layer.  | 
7697  |  |  | 
7698  |  |  This method takes into account spatial and attribute filters set on layers that  | 
7699  |  |  will be iterated upon.  | 
7700  |  |  | 
7701  |  |  The ResetReading() method can be used to start at the beginning again.  | 
7702  |  |  | 
7703  |  |  Depending on drivers, this may also have the side effect of calling  | 
7704  |  |  OGRLayer::GetNextFeature() on the layers of this dataset.  | 
7705  |  |  | 
7706  |  |  This method is the same as the C function GDALDatasetGetNextFeature().  | 
7707  |  |  | 
7708  |  |  @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the  | 
7709  |  |                           layer to which the object belongs to, or NULL.  | 
7710  |  |                           It is possible that the output of *ppoBelongingLayer  | 
7711  |  |                           to be NULL despite the feature not being NULL.  | 
7712  |  |  @param pdfProgressPct    a pointer to a double variable to receive the  | 
7713  |  |                           percentage progress (in [0,1] range), or NULL.  | 
7714  |  |                           On return, the pointed value might be negative if  | 
7715  |  |                           determining the progress is not possible.  | 
7716  |  |  @param pfnProgress       a progress callback to report progress (for  | 
7717  |  |                           GetNextFeature() calls that might have a long  | 
7718  |  |                           duration) and offer cancellation possibility, or NULL.  | 
7719  |  |  @param pProgressData     user data provided to pfnProgress, or NULL  | 
7720  |  |  @return a feature, or NULL if no more features are available.  | 
7721  |  |  @since GDAL 2.2  | 
7722  |  |  @see GetFeatures()  | 
7723  |  | */  | 
7724  |  |  | 
7725  |  | OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,  | 
7726  |  |                                         double *pdfProgressPct,  | 
7727  |  |                                         GDALProgressFunc pfnProgress,  | 
7728  |  |                                         void *pProgressData)  | 
7729  | 0  | { | 
7730  | 0  |     if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)  | 
7731  | 0  |     { | 
7732  | 0  |         if (ppoBelongingLayer != nullptr)  | 
7733  | 0  |             *ppoBelongingLayer = nullptr;  | 
7734  | 0  |         if (pdfProgressPct != nullptr)  | 
7735  | 0  |             *pdfProgressPct = 1.0;  | 
7736  | 0  |         if (pfnProgress != nullptr)  | 
7737  | 0  |             pfnProgress(1.0, "", pProgressData);  | 
7738  | 0  |         return nullptr;  | 
7739  | 0  |     }  | 
7740  |  |  | 
7741  | 0  |     if (m_poPrivate->poCurrentLayer == nullptr &&  | 
7742  | 0  |         (pdfProgressPct != nullptr || pfnProgress != nullptr))  | 
7743  | 0  |     { | 
7744  | 0  |         if (m_poPrivate->nLayerCount < 0)  | 
7745  | 0  |         { | 
7746  | 0  |             m_poPrivate->nLayerCount = GetLayerCount();  | 
7747  | 0  |         }  | 
7748  |  | 
  | 
7749  | 0  |         if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)  | 
7750  | 0  |         { | 
7751  | 0  |             m_poPrivate->nTotalFeatures = 0;  | 
7752  | 0  |             for (int i = 0; i < m_poPrivate->nLayerCount; i++)  | 
7753  | 0  |             { | 
7754  | 0  |                 OGRLayer *poLayer = GetLayer(i);  | 
7755  | 0  |                 if (poLayer == nullptr ||  | 
7756  | 0  |                     !poLayer->TestCapability(OLCFastFeatureCount))  | 
7757  | 0  |                 { | 
7758  | 0  |                     m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;  | 
7759  | 0  |                     break;  | 
7760  | 0  |                 }  | 
7761  | 0  |                 GIntBig nCount = poLayer->GetFeatureCount(FALSE);  | 
7762  | 0  |                 if (nCount < 0)  | 
7763  | 0  |                 { | 
7764  | 0  |                     m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;  | 
7765  | 0  |                     break;  | 
7766  | 0  |                 }  | 
7767  | 0  |                 m_poPrivate->nTotalFeatures += nCount;  | 
7768  | 0  |             }  | 
7769  | 0  |         }  | 
7770  | 0  |     }  | 
7771  |  | 
  | 
7772  | 0  |     while (true)  | 
7773  | 0  |     { | 
7774  | 0  |         if (m_poPrivate->poCurrentLayer == nullptr)  | 
7775  | 0  |         { | 
7776  | 0  |             m_poPrivate->poCurrentLayer =  | 
7777  | 0  |                 GetLayer(m_poPrivate->nCurrentLayerIdx);  | 
7778  | 0  |             if (m_poPrivate->poCurrentLayer == nullptr)  | 
7779  | 0  |             { | 
7780  | 0  |                 m_poPrivate->nCurrentLayerIdx = -1;  | 
7781  | 0  |                 if (ppoBelongingLayer != nullptr)  | 
7782  | 0  |                     *ppoBelongingLayer = nullptr;  | 
7783  | 0  |                 if (pdfProgressPct != nullptr)  | 
7784  | 0  |                     *pdfProgressPct = 1.0;  | 
7785  | 0  |                 return nullptr;  | 
7786  | 0  |             }  | 
7787  | 0  |             m_poPrivate->poCurrentLayer->ResetReading();  | 
7788  | 0  |             m_poPrivate->nFeatureReadInLayer = 0;  | 
7789  | 0  |             if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)  | 
7790  | 0  |             { | 
7791  | 0  |                 if (m_poPrivate->poCurrentLayer->TestCapability(  | 
7792  | 0  |                         OLCFastFeatureCount))  | 
7793  | 0  |                     m_poPrivate->nTotalFeaturesInLayer =  | 
7794  | 0  |                         m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);  | 
7795  | 0  |                 else  | 
7796  | 0  |                     m_poPrivate->nTotalFeaturesInLayer = 0;  | 
7797  | 0  |             }  | 
7798  | 0  |         }  | 
7799  | 0  |         OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();  | 
7800  | 0  |         if (poFeature == nullptr)  | 
7801  | 0  |         { | 
7802  | 0  |             m_poPrivate->nCurrentLayerIdx++;  | 
7803  | 0  |             m_poPrivate->poCurrentLayer = nullptr;  | 
7804  | 0  |             continue;  | 
7805  | 0  |         }  | 
7806  |  |  | 
7807  | 0  |         m_poPrivate->nFeatureReadInLayer++;  | 
7808  | 0  |         m_poPrivate->nFeatureReadInDataset++;  | 
7809  | 0  |         if (pdfProgressPct != nullptr || pfnProgress != nullptr)  | 
7810  | 0  |         { | 
7811  | 0  |             double dfPct = 0.0;  | 
7812  | 0  |             if (m_poPrivate->nTotalFeatures > 0)  | 
7813  | 0  |             { | 
7814  | 0  |                 dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /  | 
7815  | 0  |                         m_poPrivate->nTotalFeatures;  | 
7816  | 0  |             }  | 
7817  | 0  |             else  | 
7818  | 0  |             { | 
7819  | 0  |                 dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /  | 
7820  | 0  |                         m_poPrivate->nLayerCount;  | 
7821  | 0  |                 if (m_poPrivate->nTotalFeaturesInLayer > 0)  | 
7822  | 0  |                 { | 
7823  | 0  |                     dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /  | 
7824  | 0  |                              m_poPrivate->nTotalFeaturesInLayer /  | 
7825  | 0  |                              m_poPrivate->nLayerCount;  | 
7826  | 0  |                 }  | 
7827  | 0  |             }  | 
7828  | 0  |             if (pdfProgressPct)  | 
7829  | 0  |                 *pdfProgressPct = dfPct;  | 
7830  | 0  |             if (pfnProgress)  | 
7831  | 0  |                 pfnProgress(dfPct, "", nullptr);  | 
7832  | 0  |         }  | 
7833  |  | 
  | 
7834  | 0  |         if (ppoBelongingLayer != nullptr)  | 
7835  | 0  |             *ppoBelongingLayer = m_poPrivate->poCurrentLayer;  | 
7836  | 0  |         return poFeature;  | 
7837  | 0  |     }  | 
7838  | 0  | }  | 
7839  |  |  | 
7840  |  | /************************************************************************/  | 
7841  |  | /*                     GDALDatasetGetNextFeature()                      */  | 
7842  |  | /************************************************************************/  | 
7843  |  | /**  | 
7844  |  |  \brief Fetch the next available feature from this dataset.  | 
7845  |  |  | 
7846  |  |  This method is intended for the few drivers where OGR_L_GetNextFeature()  | 
7847  |  |  is not efficient, but in general OGR_L_GetNextFeature() is a more  | 
7848  |  |  natural API.  | 
7849  |  |  | 
7850  |  |  The returned feature becomes the responsibility of the caller to  | 
7851  |  |  delete with OGRFeature::DestroyFeature().  | 
7852  |  |  | 
7853  |  |  Depending on the driver, this method may return features from layers in a  | 
7854  |  |  non sequential way. This is what may happen when the  | 
7855  |  |  ODsCRandomLayerRead capability is declared (for example for the  | 
7856  |  |  OSM and GMLAS drivers). When datasets declare this capability, it is strongly  | 
7857  |  |  advised to use GDALDataset::GetNextFeature() instead of  | 
7858  |  |  OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub  | 
7859  |  |  implementation.  | 
7860  |  |  | 
7861  |  |  The default implementation, used by most drivers, will  | 
7862  |  |  however iterate over each layer, and then over each feature within this  | 
7863  |  |  layer.  | 
7864  |  |  | 
7865  |  |  This method takes into account spatial and attribute filters set on layers that  | 
7866  |  |  will be iterated upon.  | 
7867  |  |  | 
7868  |  |  The ResetReading() method can be used to start at the beginning again.  | 
7869  |  |  | 
7870  |  |  Depending on drivers, this may also have the side effect of calling  | 
7871  |  |  OGRLayer::GetNextFeature() on the layers of this dataset.  | 
7872  |  |  | 
7873  |  |  This method is the same as the C++ method GDALDataset::GetNextFeature()  | 
7874  |  |  | 
7875  |  |  @param hDS               dataset handle.  | 
7876  |  |  @param phBelongingLayer  a pointer to a OGRLayer* variable to receive the  | 
7877  |  |                           layer to which the object belongs to, or NULL.  | 
7878  |  |                           It is possible that the output of *ppoBelongingLayer  | 
7879  |  |                           to be NULL despite the feature not being NULL.  | 
7880  |  |  @param pdfProgressPct    a pointer to a double variable to receive the  | 
7881  |  |                           percentage progress (in [0,1] range), or NULL.  | 
7882  |  |                           On return, the pointed value might be negative if  | 
7883  |  |                           determining the progress is not possible.  | 
7884  |  |  @param pfnProgress       a progress callback to report progress (for  | 
7885  |  |                           GetNextFeature() calls that might have a long  | 
7886  |  |                           duration) and offer cancellation possibility, or NULL  | 
7887  |  |  @param pProgressData     user data provided to pfnProgress, or NULL  | 
7888  |  |  @return a feature, or NULL if no more features are available.  | 
7889  |  |  @since GDAL 2.2  | 
7890  |  | */  | 
7891  |  | OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,  | 
7892  |  |                                               OGRLayerH *phBelongingLayer,  | 
7893  |  |                                               double *pdfProgressPct,  | 
7894  |  |                                               GDALProgressFunc pfnProgress,  | 
7895  |  |                                               void *pProgressData)  | 
7896  | 0  | { | 
7897  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);  | 
7898  |  |  | 
7899  | 0  |     return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(  | 
7900  | 0  |         reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,  | 
7901  | 0  |         pfnProgress, pProgressData));  | 
7902  | 0  | }  | 
7903  |  |  | 
7904  |  | /************************************************************************/  | 
7905  |  | /*                            TestCapability()                          */  | 
7906  |  | /************************************************************************/  | 
7907  |  |  | 
7908  |  | /**  | 
7909  |  |  \fn GDALDataset::TestCapability( const char * pszCap )  | 
7910  |  |  \brief Test if capability is available.  | 
7911  |  |  | 
7912  |  |  One of the following dataset capability names can be passed into this  | 
7913  |  |  method, and a TRUE or FALSE value will be returned indicating whether or not  | 
7914  |  |  the capability is available for this object.  | 
7915  |  |  | 
7916  |  |  <ul>  | 
7917  |  |   <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>  | 
7918  |  |   <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing  | 
7919  |  |           layers.<p>  | 
7920  |  |   <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this  | 
7921  |  |           datasource support CreateGeomField() just after layer creation.<p>  | 
7922  |  |   <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve  | 
7923  |  |           geometries.<p>  | 
7924  |  |   <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)  | 
7925  |  |           transactions.<p>  | 
7926  |  |   <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports  | 
7927  |  |           transactions through emulation.<p>  | 
7928  |  |   <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated  | 
7929  |  |           GetNextFeature() implementation, potentially returning features from  | 
7930  |  |           layers in a non sequential way.<p>  | 
7931  |  |   <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling  | 
7932  |  |          CreateFeature() on layers in a non sequential way.<p>  | 
7933  |  |  </ul>  | 
7934  |  |  | 
7935  |  |  The \#define macro forms of the capability names should be used in preference  | 
7936  |  |  to the strings themselves to avoid misspelling.  | 
7937  |  |  | 
7938  |  |  This method is the same as the C function GDALDatasetTestCapability() and the  | 
7939  |  |  deprecated OGR_DS_TestCapability().  | 
7940  |  |  | 
7941  |  |  In GDAL 1.X, this method used to be in the OGRDataSource class.  | 
7942  |  |  | 
7943  |  |  @param pszCap the capability to test.  | 
7944  |  |  | 
7945  |  |  @return TRUE if capability available otherwise FALSE.  | 
7946  |  | */  | 
7947  |  |  | 
7948  |  | int GDALDataset::TestCapability(CPL_UNUSED const char *pszCap)  | 
7949  | 0  | { | 
7950  | 0  |     return FALSE;  | 
7951  | 0  | }  | 
7952  |  |  | 
7953  |  | /************************************************************************/  | 
7954  |  | /*                     GDALDatasetTestCapability()                      */  | 
7955  |  | /************************************************************************/  | 
7956  |  |  | 
7957  |  | /**  | 
7958  |  |  \brief Test if capability is available.  | 
7959  |  |  | 
7960  |  |  One of the following dataset capability names can be passed into this  | 
7961  |  |  function, and a TRUE or FALSE value will be returned indicating whether or not  | 
7962  |  |  the capability is available for this object.  | 
7963  |  |  | 
7964  |  |  <ul>  | 
7965  |  |   <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>  | 
7966  |  |   <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing  | 
7967  |  |           layers.<p>  | 
7968  |  |   <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this  | 
7969  |  |           datasource support CreateGeomField() just after layer creation.<p>  | 
7970  |  |   <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve  | 
7971  |  |           geometries.<p>  | 
7972  |  |   <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)  | 
7973  |  |           transactions.<p>  | 
7974  |  |   <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports  | 
7975  |  |           transactions through emulation.<p>  | 
7976  |  |   <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated  | 
7977  |  |           GetNextFeature() implementation, potentially returning features from  | 
7978  |  |           layers in a non sequential way.<p>  | 
7979  |  |   <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling  | 
7980  |  |           CreateFeature() on layers in a non sequential way.<p>  | 
7981  |  |  </ul>  | 
7982  |  |  | 
7983  |  |  The \#define macro forms of the capability names should be used in preference  | 
7984  |  |  to the strings themselves to avoid misspelling.  | 
7985  |  |  | 
7986  |  |  This function is the same as the C++ method GDALDataset::TestCapability()  | 
7987  |  |  | 
7988  |  |  @since GDAL 2.0  | 
7989  |  |  | 
7990  |  |  @param hDS the dataset handle.  | 
7991  |  |  @param pszCap the capability to test.  | 
7992  |  |  | 
7993  |  |  @return TRUE if capability available otherwise FALSE.  | 
7994  |  | */  | 
7995  |  | int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)  | 
7996  |  |  | 
7997  | 0  | { | 
7998  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);  | 
7999  | 0  |     VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);  | 
8000  |  |  | 
8001  | 0  |     return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);  | 
8002  | 0  | }  | 
8003  |  |  | 
8004  |  | /************************************************************************/  | 
8005  |  | /*                           StartTransaction()                         */  | 
8006  |  | /************************************************************************/  | 
8007  |  |  | 
8008  |  | /**  | 
8009  |  |  \fn GDALDataset::StartTransaction(int)  | 
8010  |  |  \brief For datasources which support transactions, StartTransaction creates a  | 
8011  |  | `transaction.  | 
8012  |  |  | 
8013  |  |  If starting the transaction fails, will return  | 
8014  |  |  OGRERR_FAILURE. Datasources which do not support transactions will  | 
8015  |  |  always return OGRERR_UNSUPPORTED_OPERATION.  | 
8016  |  |  | 
8017  |  |  Nested transactions are not supported.  | 
8018  |  |  | 
8019  |  |  All changes done after the start of the transaction are definitely applied in  | 
8020  |  |  the datasource if CommitTransaction() is called. They may be canceled by  | 
8021  |  |  calling RollbackTransaction() instead.  | 
8022  |  |  | 
8023  |  |  At the time of writing, transactions only apply on vector layers.  | 
8024  |  |  | 
8025  |  |  Datasets that support transactions will advertise the ODsCTransactions  | 
8026  |  |  capability.  Use of transactions at dataset level is generally preferred to  | 
8027  |  |  transactions at layer level, whose scope is rarely limited to the layer from  | 
8028  |  |  which it was started.  | 
8029  |  |  | 
8030  |  |  In case StartTransaction() fails, neither CommitTransaction() or  | 
8031  |  |  RollbackTransaction() should be called.  | 
8032  |  |  | 
8033  |  |  If an error occurs after a successful StartTransaction(), the whole transaction  | 
8034  |  |  may or may not be implicitly canceled, depending on drivers. (e.g.  the PG  | 
8035  |  |  driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,  | 
8036  |  |  an explicit call to RollbackTransaction() should be done to keep things  | 
8037  |  |  balanced.  | 
8038  |  |  | 
8039  |  |  By default, when bForce is set to FALSE, only "efficient" transactions will be  | 
8040  |  |  attempted. Some drivers may offer an emulation of transactions, but sometimes  | 
8041  |  |  with significant overhead, in which case the user must explicitly allow for  | 
8042  |  |  such an emulation by setting bForce to TRUE. Drivers that offer emulated  | 
8043  |  |  transactions should advertise the ODsCEmulatedTransactions capability (and not  | 
8044  |  |  ODsCTransactions).  | 
8045  |  |  | 
8046  |  |  This function is the same as the C function GDALDatasetStartTransaction().  | 
8047  |  |  | 
8048  |  |  @param bForce can be set to TRUE if an emulation, possibly slow, of a  | 
8049  |  |  transaction  | 
8050  |  |                mechanism is acceptable.  | 
8051  |  |  | 
8052  |  |  @return OGRERR_NONE on success.  | 
8053  |  |  @since GDAL 2.0  | 
8054  |  | */  | 
8055  |  |  | 
8056  |  | OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)  | 
8057  | 0  | { | 
8058  | 0  |     return OGRERR_UNSUPPORTED_OPERATION;  | 
8059  | 0  | }  | 
8060  |  |  | 
8061  |  | /************************************************************************/  | 
8062  |  | /*                      GDALDatasetStartTransaction()                   */  | 
8063  |  | /************************************************************************/  | 
8064  |  |  | 
8065  |  | /**  | 
8066  |  |  \brief For datasources which support transactions, StartTransaction creates a  | 
8067  |  |  transaction.  | 
8068  |  |  | 
8069  |  |  If starting the transaction fails, will return  | 
8070  |  |  OGRERR_FAILURE. Datasources which do not support transactions will  | 
8071  |  |  always return OGRERR_UNSUPPORTED_OPERATION.  | 
8072  |  |  | 
8073  |  |  Nested transactions are not supported.  | 
8074  |  |  | 
8075  |  |  All changes done after the start of the transaction are definitely applied in  | 
8076  |  |  the datasource if CommitTransaction() is called. They may be canceled by  | 
8077  |  |  calling RollbackTransaction() instead.  | 
8078  |  |  | 
8079  |  |  At the time of writing, transactions only apply on vector layers.  | 
8080  |  |  | 
8081  |  |  Datasets that support transactions will advertise the ODsCTransactions  | 
8082  |  |  capability.  | 
8083  |  |  Use of transactions at dataset level is generally preferred to transactions at  | 
8084  |  |  layer level, whose scope is rarely limited to the layer from which it was  | 
8085  |  |  started.  | 
8086  |  |  | 
8087  |  |  In case StartTransaction() fails, neither CommitTransaction() or  | 
8088  |  |  RollbackTransaction() should be called.  | 
8089  |  |  | 
8090  |  |  If an error occurs after a successful StartTransaction(), the whole  | 
8091  |  |  transaction may or may not be implicitly canceled, depending on drivers. (e.g.  | 
8092  |  |  the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an  | 
8093  |  |  error, an explicit call to RollbackTransaction() should be done to keep things  | 
8094  |  |  balanced.  | 
8095  |  |  | 
8096  |  |  By default, when bForce is set to FALSE, only "efficient" transactions will be  | 
8097  |  |  attempted. Some drivers may offer an emulation of transactions, but sometimes  | 
8098  |  |  with significant overhead, in which case the user must explicitly allow for  | 
8099  |  |  such an emulation by setting bForce to TRUE. Drivers that offer emulated  | 
8100  |  |  transactions should advertise the ODsCEmulatedTransactions capability (and not  | 
8101  |  |  ODsCTransactions).  | 
8102  |  |  | 
8103  |  |  This function is the same as the C++ method GDALDataset::StartTransaction()  | 
8104  |  |  | 
8105  |  |  @param hDS the dataset handle.  | 
8106  |  |  @param bForce can be set to TRUE if an emulation, possibly slow, of a  | 
8107  |  |  transaction  | 
8108  |  |                mechanism is acceptable.  | 
8109  |  |  | 
8110  |  |  @return OGRERR_NONE on success.  | 
8111  |  |  @since GDAL 2.0  | 
8112  |  | */  | 
8113  |  | OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)  | 
8114  | 0  | { | 
8115  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",  | 
8116  | 0  |                       OGRERR_INVALID_HANDLE);  | 
8117  |  |  | 
8118  | 0  | #ifdef OGRAPISPY_ENABLED  | 
8119  | 0  |     if (bOGRAPISpyEnabled)  | 
8120  | 0  |         OGRAPISpy_Dataset_StartTransaction(hDS, bForce);  | 
8121  | 0  | #endif  | 
8122  |  | 
  | 
8123  | 0  |     return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);  | 
8124  | 0  | }  | 
8125  |  |  | 
8126  |  | /************************************************************************/  | 
8127  |  | /*                           CommitTransaction()                        */  | 
8128  |  | /************************************************************************/  | 
8129  |  |  | 
8130  |  | /**  | 
8131  |  |  \brief For datasources which support transactions, CommitTransaction commits a  | 
8132  |  |  transaction.  | 
8133  |  |  | 
8134  |  |  If no transaction is active, or the commit fails, will return  | 
8135  |  |  OGRERR_FAILURE. Datasources which do not support transactions will  | 
8136  |  |  always return OGRERR_UNSUPPORTED_OPERATION.  | 
8137  |  |  | 
8138  |  |  Depending on drivers, this may or may not abort layer sequential readings that  | 
8139  |  |  are active.  | 
8140  |  |  | 
8141  |  |  This function is the same as the C function GDALDatasetCommitTransaction().  | 
8142  |  |  | 
8143  |  |  @return OGRERR_NONE on success.  | 
8144  |  |  @since GDAL 2.0  | 
8145  |  | */  | 
8146  |  | OGRErr GDALDataset::CommitTransaction()  | 
8147  | 0  | { | 
8148  | 0  |     return OGRERR_UNSUPPORTED_OPERATION;  | 
8149  | 0  | }  | 
8150  |  |  | 
8151  |  | /************************************************************************/  | 
8152  |  | /*                        GDALDatasetCommitTransaction()                */  | 
8153  |  | /************************************************************************/  | 
8154  |  |  | 
8155  |  | /**  | 
8156  |  |  \brief For datasources which support transactions, CommitTransaction commits a  | 
8157  |  |  transaction.  | 
8158  |  |  | 
8159  |  |  If no transaction is active, or the commit fails, will return  | 
8160  |  |  OGRERR_FAILURE. Datasources which do not support transactions will  | 
8161  |  |  always return OGRERR_UNSUPPORTED_OPERATION.  | 
8162  |  |  | 
8163  |  |  Depending on drivers, this may or may not abort layer sequential readings that  | 
8164  |  |  are active.  | 
8165  |  |  | 
8166  |  |  This function is the same as the C++ method GDALDataset::CommitTransaction()  | 
8167  |  |  | 
8168  |  |  @return OGRERR_NONE on success.  | 
8169  |  |  @since GDAL 2.0  | 
8170  |  | */  | 
8171  |  | OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)  | 
8172  | 0  | { | 
8173  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",  | 
8174  | 0  |                       OGRERR_INVALID_HANDLE);  | 
8175  |  |  | 
8176  | 0  | #ifdef OGRAPISPY_ENABLED  | 
8177  | 0  |     if (bOGRAPISpyEnabled)  | 
8178  | 0  |         OGRAPISpy_Dataset_CommitTransaction(hDS);  | 
8179  | 0  | #endif  | 
8180  |  | 
  | 
8181  | 0  |     return GDALDataset::FromHandle(hDS)->CommitTransaction();  | 
8182  | 0  | }  | 
8183  |  |  | 
8184  |  | /************************************************************************/  | 
8185  |  | /*                           RollbackTransaction()                      */  | 
8186  |  | /************************************************************************/  | 
8187  |  |  | 
8188  |  | /**  | 
8189  |  |  \brief For datasources which support transactions, RollbackTransaction will  | 
8190  |  |  roll back a datasource to its state before the start of the current  | 
8191  |  |  transaction.  | 
8192  |  |  If no transaction is active, or the rollback fails, will return  | 
8193  |  |  OGRERR_FAILURE. Datasources which do not support transactions will  | 
8194  |  |  always return OGRERR_UNSUPPORTED_OPERATION.  | 
8195  |  |  | 
8196  |  |  This function is the same as the C function GDALDatasetRollbackTransaction().  | 
8197  |  |  | 
8198  |  |  @return OGRERR_NONE on success.  | 
8199  |  |  @since GDAL 2.0  | 
8200  |  | */  | 
8201  |  | OGRErr GDALDataset::RollbackTransaction()  | 
8202  | 0  | { | 
8203  | 0  |     return OGRERR_UNSUPPORTED_OPERATION;  | 
8204  | 0  | }  | 
8205  |  |  | 
8206  |  | /************************************************************************/  | 
8207  |  | /*                     GDALDatasetRollbackTransaction()                 */  | 
8208  |  | /************************************************************************/  | 
8209  |  |  | 
8210  |  | /**  | 
8211  |  |  \brief For datasources which support transactions, RollbackTransaction will  | 
8212  |  |  roll back a datasource to its state before the start of the current  | 
8213  |  |  transaction.  | 
8214  |  |  If no transaction is active, or the rollback fails, will return  | 
8215  |  |  OGRERR_FAILURE. Datasources which do not support transactions will  | 
8216  |  |  always return OGRERR_UNSUPPORTED_OPERATION.  | 
8217  |  |  | 
8218  |  |  This function is the same as the C++ method GDALDataset::RollbackTransaction().  | 
8219  |  |  | 
8220  |  |  @return OGRERR_NONE on success.  | 
8221  |  |  @since GDAL 2.0  | 
8222  |  | */  | 
8223  |  | OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)  | 
8224  | 0  | { | 
8225  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",  | 
8226  | 0  |                       OGRERR_INVALID_HANDLE);  | 
8227  |  |  | 
8228  | 0  | #ifdef OGRAPISPY_ENABLED  | 
8229  | 0  |     if (bOGRAPISpyEnabled)  | 
8230  | 0  |         OGRAPISpy_Dataset_RollbackTransaction(hDS);  | 
8231  | 0  | #endif  | 
8232  |  | 
  | 
8233  | 0  |     return GDALDataset::FromHandle(hDS)->RollbackTransaction();  | 
8234  | 0  | }  | 
8235  |  |  | 
8236  |  | //! @cond Doxygen_Suppress  | 
8237  |  |  | 
8238  |  | /************************************************************************/  | 
8239  |  | /*                   ShareLockWithParentDataset()                       */  | 
8240  |  | /************************************************************************/  | 
8241  |  |  | 
8242  |  | /* To be used typically by the GTiff driver to link overview datasets */  | 
8243  |  | /* with their main dataset, so that they share the same lock */  | 
8244  |  | /* Cf https://github.com/OSGeo/gdal/issues/1488 */  | 
8245  |  | /* The parent dataset should remain alive while the this dataset is alive */  | 
8246  |  |  | 
8247  |  | void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)  | 
8248  | 0  | { | 
8249  | 0  |     if (m_poPrivate != nullptr)  | 
8250  | 0  |     { | 
8251  | 0  |         m_poPrivate->poParentDataset = poParentDataset;  | 
8252  | 0  |     }  | 
8253  | 0  | }  | 
8254  |  |  | 
8255  |  | /************************************************************************/  | 
8256  |  | /*                   SetQueryLoggerFunc()                               */  | 
8257  |  | /************************************************************************/  | 
8258  |  |  | 
8259  |  | bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,  | 
8260  |  |                                      CPL_UNUSED void *context)  | 
8261  | 0  | { | 
8262  | 0  |     return false;  | 
8263  | 0  | }  | 
8264  |  |  | 
8265  |  | /************************************************************************/  | 
8266  |  | /*                          EnterReadWrite()                            */  | 
8267  |  | /************************************************************************/  | 
8268  |  |  | 
8269  |  | int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)  | 
8270  | 0  | { | 
8271  | 0  |     if (m_poPrivate == nullptr ||  | 
8272  | 0  |         IsThreadSafe(GDAL_OF_RASTER | (nOpenFlags & GDAL_OF_UPDATE)))  | 
8273  | 0  |         return FALSE;  | 
8274  |  |  | 
8275  | 0  |     if (m_poPrivate->poParentDataset)  | 
8276  | 0  |         return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);  | 
8277  |  |  | 
8278  | 0  |     if (eAccess == GA_Update)  | 
8279  | 0  |     { | 
8280  | 0  |         if (m_poPrivate->eStateReadWriteMutex ==  | 
8281  | 0  |             GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)  | 
8282  | 0  |         { | 
8283  |  |             // In case dead-lock would occur, which is not impossible,  | 
8284  |  |             // this can be used to prevent it, but at the risk of other  | 
8285  |  |             // issues.  | 
8286  | 0  |             if (CPLTestBool(  | 
8287  | 0  |                     CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES"))) | 
8288  | 0  |             { | 
8289  | 0  |                 m_poPrivate->eStateReadWriteMutex =  | 
8290  | 0  |                     GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;  | 
8291  | 0  |             }  | 
8292  | 0  |             else  | 
8293  | 0  |             { | 
8294  | 0  |                 m_poPrivate->eStateReadWriteMutex =  | 
8295  | 0  |                     GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;  | 
8296  | 0  |             }  | 
8297  | 0  |         }  | 
8298  | 0  |         if (m_poPrivate->eStateReadWriteMutex ==  | 
8299  | 0  |             GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)  | 
8300  | 0  |         { | 
8301  |  |             // There should be no race related to creating this mutex since  | 
8302  |  |             // it should be first created through IWriteBlock() / IRasterIO()  | 
8303  |  |             // and then GDALRasterBlock might call it from another thread.  | 
8304  |  | #ifdef DEBUG_VERBOSE  | 
8305  |  |             CPLDebug("GDAL", | 
8306  |  |                      "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",  | 
8307  |  |                      CPLGetPID(), GetDescription());  | 
8308  |  | #endif  | 
8309  | 0  |             CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);  | 
8310  |  | 
  | 
8311  | 0  |             const int nCountMutex =  | 
8312  | 0  |                 m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;  | 
8313  | 0  |             if (nCountMutex == 0 && eRWFlag == GF_Read)  | 
8314  | 0  |             { | 
8315  | 0  |                 CPLReleaseMutex(m_poPrivate->hMutex);  | 
8316  | 0  |                 for (int i = 0; i < nBands; i++)  | 
8317  | 0  |                 { | 
8318  | 0  |                     auto blockCache = papoBands[i]->poBandBlockCache;  | 
8319  | 0  |                     if (blockCache)  | 
8320  | 0  |                         blockCache->WaitCompletionPendingTasks();  | 
8321  | 0  |                 }  | 
8322  | 0  |                 CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);  | 
8323  | 0  |             }  | 
8324  |  | 
  | 
8325  | 0  |             return TRUE;  | 
8326  | 0  |         }  | 
8327  | 0  |     }  | 
8328  | 0  |     return FALSE;  | 
8329  | 0  | }  | 
8330  |  |  | 
8331  |  | /************************************************************************/  | 
8332  |  | /*                         LeaveReadWrite()                             */  | 
8333  |  | /************************************************************************/  | 
8334  |  |  | 
8335  |  | void GDALDataset::LeaveReadWrite()  | 
8336  | 0  | { | 
8337  | 0  |     if (m_poPrivate)  | 
8338  | 0  |     { | 
8339  | 0  |         if (m_poPrivate->poParentDataset)  | 
8340  | 0  |         { | 
8341  | 0  |             m_poPrivate->poParentDataset->LeaveReadWrite();  | 
8342  | 0  |             return;  | 
8343  | 0  |         }  | 
8344  |  |  | 
8345  | 0  |         m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;  | 
8346  | 0  |         CPLReleaseMutex(m_poPrivate->hMutex);  | 
8347  |  | #ifdef DEBUG_VERBOSE  | 
8348  |  |         CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s", | 
8349  |  |                  CPLGetPID(), GetDescription());  | 
8350  |  | #endif  | 
8351  | 0  |     }  | 
8352  | 0  | }  | 
8353  |  |  | 
8354  |  | /************************************************************************/  | 
8355  |  | /*                           InitRWLock()                               */  | 
8356  |  | /************************************************************************/  | 
8357  |  |  | 
8358  |  | void GDALDataset::InitRWLock()  | 
8359  | 0  | { | 
8360  | 0  |     if (m_poPrivate)  | 
8361  | 0  |     { | 
8362  | 0  |         if (m_poPrivate->poParentDataset)  | 
8363  | 0  |         { | 
8364  | 0  |             m_poPrivate->poParentDataset->InitRWLock();  | 
8365  | 0  |             return;  | 
8366  | 0  |         }  | 
8367  |  |  | 
8368  | 0  |         if (m_poPrivate->eStateReadWriteMutex ==  | 
8369  | 0  |             GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)  | 
8370  | 0  |         { | 
8371  | 0  |             if (EnterReadWrite(GF_Write))  | 
8372  | 0  |                 LeaveReadWrite();  | 
8373  | 0  |         }  | 
8374  | 0  |     }  | 
8375  | 0  | }  | 
8376  |  |  | 
8377  |  | /************************************************************************/  | 
8378  |  | /*                       DisableReadWriteMutex()                        */  | 
8379  |  | /************************************************************************/  | 
8380  |  |  | 
8381  |  | // The mutex logic is broken in multi-threaded situations, for example  | 
8382  |  | // with 2 WarpedVRT datasets being read at the same time. In that  | 
8383  |  | // particular case, the mutex is not needed, so allow the VRTWarpedDataset code  | 
8384  |  | // to disable it.  | 
8385  |  | void GDALDataset::DisableReadWriteMutex()  | 
8386  | 0  | { | 
8387  | 0  |     if (m_poPrivate)  | 
8388  | 0  |     { | 
8389  | 0  |         if (m_poPrivate->poParentDataset)  | 
8390  | 0  |         { | 
8391  | 0  |             m_poPrivate->poParentDataset->DisableReadWriteMutex();  | 
8392  | 0  |             return;  | 
8393  | 0  |         }  | 
8394  |  |  | 
8395  | 0  |         m_poPrivate->eStateReadWriteMutex =  | 
8396  | 0  |             GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;  | 
8397  | 0  |     }  | 
8398  | 0  | }  | 
8399  |  |  | 
8400  |  | /************************************************************************/  | 
8401  |  | /*                      TemporarilyDropReadWriteLock()                  */  | 
8402  |  | /************************************************************************/  | 
8403  |  |  | 
8404  |  | void GDALDataset::TemporarilyDropReadWriteLock()  | 
8405  | 0  | { | 
8406  | 0  |     if (m_poPrivate == nullptr)  | 
8407  | 0  |         return;  | 
8408  |  |  | 
8409  | 0  |     if (m_poPrivate->poParentDataset)  | 
8410  | 0  |     { | 
8411  | 0  |         m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();  | 
8412  | 0  |         return;  | 
8413  | 0  |     }  | 
8414  |  |  | 
8415  | 0  |     if (m_poPrivate->hMutex)  | 
8416  | 0  |     { | 
8417  |  | #ifdef DEBUG_VERBOSE  | 
8418  |  |         CPLDebug("GDAL", | 
8419  |  |                  "[Thread " CPL_FRMT_GIB "] "  | 
8420  |  |                  "Temporarily drop RW mutex for %s",  | 
8421  |  |                  CPLGetPID(), GetDescription());  | 
8422  |  | #endif  | 
8423  | 0  |         CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);  | 
8424  | 0  |         const int nCount =  | 
8425  | 0  |             m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];  | 
8426  |  | #ifdef DEBUG_EXTRA  | 
8427  |  |         m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;  | 
8428  |  | #endif  | 
8429  | 0  | #ifndef __COVERITY__  | 
8430  | 0  |         for (int i = 0; i < nCount + 1; i++)  | 
8431  | 0  |         { | 
8432  |  |             // The mutex is recursive  | 
8433  | 0  |             CPLReleaseMutex(m_poPrivate->hMutex);  | 
8434  | 0  |         }  | 
8435  | 0  | #endif  | 
8436  | 0  |     }  | 
8437  | 0  | }  | 
8438  |  |  | 
8439  |  | /************************************************************************/  | 
8440  |  | /*                       ReacquireReadWriteLock()                       */  | 
8441  |  | /************************************************************************/  | 
8442  |  |  | 
8443  |  | void GDALDataset::ReacquireReadWriteLock()  | 
8444  | 0  | { | 
8445  | 0  |     if (m_poPrivate == nullptr)  | 
8446  | 0  |         return;  | 
8447  |  |  | 
8448  | 0  |     if (m_poPrivate->poParentDataset)  | 
8449  | 0  |     { | 
8450  | 0  |         m_poPrivate->poParentDataset->ReacquireReadWriteLock();  | 
8451  | 0  |         return;  | 
8452  | 0  |     }  | 
8453  |  |  | 
8454  | 0  |     if (m_poPrivate->hMutex)  | 
8455  | 0  |     { | 
8456  |  | #ifdef DEBUG_VERBOSE  | 
8457  |  |         CPLDebug("GDAL", | 
8458  |  |                  "[Thread " CPL_FRMT_GIB "] "  | 
8459  |  |                  "Reacquire temporarily dropped RW mutex for %s",  | 
8460  |  |                  CPLGetPID(), GetDescription());  | 
8461  |  | #endif  | 
8462  | 0  |         CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);  | 
8463  | 0  |         const int nCount =  | 
8464  | 0  |             m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];  | 
8465  |  | #ifdef DEBUG_EXTRA  | 
8466  |  |         CPLAssert(nCount ==  | 
8467  |  |                   m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);  | 
8468  |  | #endif  | 
8469  | 0  |         if (nCount == 0)  | 
8470  | 0  |             CPLReleaseMutex(m_poPrivate->hMutex);  | 
8471  | 0  | #ifndef __COVERITY__  | 
8472  | 0  |         for (int i = 0; i < nCount - 1; i++)  | 
8473  | 0  |         { | 
8474  |  |             // The mutex is recursive  | 
8475  | 0  |             CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);  | 
8476  | 0  |         }  | 
8477  | 0  | #endif  | 
8478  | 0  |     }  | 
8479  | 0  | }  | 
8480  |  |  | 
8481  |  | /************************************************************************/  | 
8482  |  | /*                           AcquireMutex()                             */  | 
8483  |  | /************************************************************************/  | 
8484  |  |  | 
8485  |  | int GDALDataset::AcquireMutex()  | 
8486  | 0  | { | 
8487  | 0  |     if (m_poPrivate == nullptr)  | 
8488  | 0  |         return 0;  | 
8489  | 0  |     if (m_poPrivate->poParentDataset)  | 
8490  | 0  |     { | 
8491  | 0  |         return m_poPrivate->poParentDataset->AcquireMutex();  | 
8492  | 0  |     }  | 
8493  |  |  | 
8494  | 0  |     return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);  | 
8495  | 0  | }  | 
8496  |  |  | 
8497  |  | /************************************************************************/  | 
8498  |  | /*                          ReleaseMutex()                              */  | 
8499  |  | /************************************************************************/  | 
8500  |  |  | 
8501  |  | void GDALDataset::ReleaseMutex()  | 
8502  | 0  | { | 
8503  | 0  |     if (m_poPrivate)  | 
8504  | 0  |     { | 
8505  | 0  |         if (m_poPrivate->poParentDataset)  | 
8506  | 0  |         { | 
8507  | 0  |             m_poPrivate->poParentDataset->ReleaseMutex();  | 
8508  | 0  |             return;  | 
8509  | 0  |         }  | 
8510  |  |  | 
8511  | 0  |         CPLReleaseMutex(m_poPrivate->hMutex);  | 
8512  | 0  |     }  | 
8513  | 0  | }  | 
8514  |  |  | 
8515  |  | //! @endcond  | 
8516  |  |  | 
8517  |  | /************************************************************************/  | 
8518  |  | /*              GDALDataset::Features::Iterator::Private                */  | 
8519  |  | /************************************************************************/  | 
8520  |  |  | 
8521  |  | struct GDALDataset::Features::Iterator::Private  | 
8522  |  | { | 
8523  |  |     GDALDataset::FeatureLayerPair m_oPair{}; | 
8524  |  |     GDALDataset *m_poDS = nullptr;  | 
8525  |  |     bool m_bEOF = true;  | 
8526  |  | };  | 
8527  |  |  | 
8528  |  | GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)  | 
8529  | 0  |     : m_poPrivate(new GDALDataset::Features::Iterator::Private())  | 
8530  | 0  | { | 
8531  | 0  |     m_poPrivate->m_poDS = poDS;  | 
8532  | 0  |     if (bStart)  | 
8533  | 0  |     { | 
8534  | 0  |         poDS->ResetReading();  | 
8535  | 0  |         m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(  | 
8536  | 0  |             &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));  | 
8537  | 0  |         m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;  | 
8538  | 0  |     }  | 
8539  | 0  | }  | 
8540  |  |  | 
8541  | 0  | GDALDataset::Features::Iterator::~Iterator() = default;  | 
8542  |  |  | 
8543  |  | const GDALDataset::FeatureLayerPair &  | 
8544  |  | GDALDataset::Features::Iterator::operator*() const  | 
8545  | 0  | { | 
8546  | 0  |     return m_poPrivate->m_oPair;  | 
8547  | 0  | }  | 
8548  |  |  | 
8549  |  | GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()  | 
8550  | 0  | { | 
8551  | 0  |     m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(  | 
8552  | 0  |         &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));  | 
8553  | 0  |     m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;  | 
8554  | 0  |     return *this;  | 
8555  | 0  | }  | 
8556  |  |  | 
8557  |  | bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const  | 
8558  | 0  | { | 
8559  | 0  |     return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;  | 
8560  | 0  | }  | 
8561  |  |  | 
8562  |  | /************************************************************************/  | 
8563  |  | /*                            GetFeatures()                             */  | 
8564  |  | /************************************************************************/  | 
8565  |  |  | 
8566  |  | /** Function that return an iterable object over features in the dataset  | 
8567  |  |  * layer.  | 
8568  |  |  *  | 
8569  |  |  * This is a C++ iterator friendly version of GetNextFeature().  | 
8570  |  |  *  | 
8571  |  |  * Using this iterator for standard range-based loops is safe, but  | 
8572  |  |  * due to implementation limitations, you shouldn't try to access  | 
8573  |  |  * (dereference) more than one iterator step at a time, since the  | 
8574  |  |  * FeatureLayerPair reference which is returned is reused.  | 
8575  |  |  *  | 
8576  |  |  * Typical use is:  | 
8577  |  |  * \code{.cpp} | 
8578  |  |  * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )  | 
8579  |  |  * { | 
8580  |  |  *       std::cout << "Feature of layer " <<  | 
8581  |  |  *               oFeatureLayerPair.layer->GetName() << std::endl;  | 
8582  |  |  *       oFeatureLayerPair.feature->DumpReadable();  | 
8583  |  |  * }  | 
8584  |  |  * \endcode  | 
8585  |  |  *  | 
8586  |  |  * @see GetNextFeature()  | 
8587  |  |  *  | 
8588  |  |  * @since GDAL 2.3  | 
8589  |  |  */  | 
8590  |  | GDALDataset::Features GDALDataset::GetFeatures()  | 
8591  | 0  | { | 
8592  | 0  |     return Features(this);  | 
8593  | 0  | }  | 
8594  |  |  | 
8595  |  | /************************************************************************/  | 
8596  |  | /*                                 begin()                              */  | 
8597  |  | /************************************************************************/  | 
8598  |  |  | 
8599  |  | /**  | 
8600  |  |  \brief Return beginning of feature iterator.  | 
8601  |  |  | 
8602  |  |  @since GDAL 2.3  | 
8603  |  | */  | 
8604  |  |  | 
8605  |  | const GDALDataset::Features::Iterator GDALDataset::Features::begin() const  | 
8606  | 0  | { | 
8607  | 0  |     return {m_poSelf, true}; | 
8608  | 0  | }  | 
8609  |  |  | 
8610  |  | /************************************************************************/  | 
8611  |  | /*                                  end()                               */  | 
8612  |  | /************************************************************************/  | 
8613  |  |  | 
8614  |  | /**  | 
8615  |  |  \brief Return end of feature iterator.  | 
8616  |  |  | 
8617  |  |  @since GDAL 2.3  | 
8618  |  | */  | 
8619  |  |  | 
8620  |  | const GDALDataset::Features::Iterator GDALDataset::Features::end() const  | 
8621  | 0  | { | 
8622  | 0  |     return {m_poSelf, false}; | 
8623  | 0  | }  | 
8624  |  |  | 
8625  |  | /************************************************************************/  | 
8626  |  | /*               GDALDataset::Layers::Iterator::Private                 */  | 
8627  |  | /************************************************************************/  | 
8628  |  |  | 
8629  |  | struct GDALDataset::Layers::Iterator::Private  | 
8630  |  | { | 
8631  |  |     OGRLayer *m_poLayer = nullptr;  | 
8632  |  |     int m_iCurLayer = 0;  | 
8633  |  |     int m_nLayerCount = 0;  | 
8634  |  |     GDALDataset *m_poDS = nullptr;  | 
8635  |  | };  | 
8636  |  |  | 
8637  | 0  | GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())  | 
8638  | 0  | { | 
8639  | 0  | }  | 
8640  |  |  | 
8641  |  | // False positive of cppcheck 1.72  | 
8642  |  | // cppcheck-suppress uninitMemberVar  | 
8643  |  | GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)  | 
8644  | 0  |     : m_poPrivate(new Private(*(oOther.m_poPrivate)))  | 
8645  | 0  | { | 
8646  | 0  | }  | 
8647  |  |  | 
8648  |  | GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept  | 
8649  | 0  |     : m_poPrivate(std::move(oOther.m_poPrivate))  | 
8650  | 0  | { | 
8651  | 0  | }  | 
8652  |  |  | 
8653  |  | GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)  | 
8654  | 0  |     : m_poPrivate(new Private())  | 
8655  | 0  | { | 
8656  | 0  |     m_poPrivate->m_poDS = poDS;  | 
8657  | 0  |     m_poPrivate->m_nLayerCount = poDS->GetLayerCount();  | 
8658  | 0  |     if (bStart)  | 
8659  | 0  |     { | 
8660  | 0  |         if (m_poPrivate->m_nLayerCount)  | 
8661  | 0  |             m_poPrivate->m_poLayer = poDS->GetLayer(0);  | 
8662  | 0  |     }  | 
8663  | 0  |     else  | 
8664  | 0  |     { | 
8665  | 0  |         m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;  | 
8666  | 0  |     }  | 
8667  | 0  | }  | 
8668  |  |  | 
8669  | 0  | GDALDataset::Layers::Iterator::~Iterator() = default;  | 
8670  |  |  | 
8671  |  | // False positive of cppcheck 1.72  | 
8672  |  | // cppcheck-suppress operatorEqVarError  | 
8673  |  | GDALDataset::Layers::Iterator &  | 
8674  |  | GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)  | 
8675  | 0  | { | 
8676  | 0  |     *m_poPrivate = *oOther.m_poPrivate;  | 
8677  | 0  |     return *this;  | 
8678  | 0  | }  | 
8679  |  |  | 
8680  |  | GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(  | 
8681  |  |     GDALDataset::Layers::Iterator &&oOther) noexcept  | 
8682  | 0  | { | 
8683  | 0  |     m_poPrivate = std::move(oOther.m_poPrivate);  | 
8684  | 0  |     return *this;  | 
8685  | 0  | }  | 
8686  |  |  | 
8687  |  | OGRLayer *GDALDataset::Layers::Iterator::operator*() const  | 
8688  | 0  | { | 
8689  | 0  |     return m_poPrivate->m_poLayer;  | 
8690  | 0  | }  | 
8691  |  |  | 
8692  |  | GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()  | 
8693  | 0  | { | 
8694  | 0  |     m_poPrivate->m_iCurLayer++;  | 
8695  | 0  |     if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)  | 
8696  | 0  |     { | 
8697  | 0  |         m_poPrivate->m_poLayer =  | 
8698  | 0  |             m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);  | 
8699  | 0  |     }  | 
8700  | 0  |     else  | 
8701  | 0  |     { | 
8702  | 0  |         m_poPrivate->m_poLayer = nullptr;  | 
8703  | 0  |     }  | 
8704  | 0  |     return *this;  | 
8705  | 0  | }  | 
8706  |  |  | 
8707  |  | GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)  | 
8708  | 0  | { | 
8709  | 0  |     GDALDataset::Layers::Iterator temp = *this;  | 
8710  | 0  |     ++(*this);  | 
8711  | 0  |     return temp;  | 
8712  | 0  | }  | 
8713  |  |  | 
8714  |  | bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const  | 
8715  | 0  | { | 
8716  | 0  |     return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;  | 
8717  | 0  | }  | 
8718  |  |  | 
8719  |  | /************************************************************************/  | 
8720  |  | /*                             GetLayers()                              */  | 
8721  |  | /************************************************************************/  | 
8722  |  |  | 
8723  |  | /** Function that returns an iterable object over layers in the dataset.  | 
8724  |  |  *  | 
8725  |  |  * This is a C++ iterator friendly version of GetLayer().  | 
8726  |  |  *  | 
8727  |  |  * Typical use is:  | 
8728  |  |  * \code{.cpp} | 
8729  |  |  * for( auto&& poLayer: poDS->GetLayers() )  | 
8730  |  |  * { | 
8731  |  |  *       std::cout << "Layer  << poLayer->GetName() << std::endl;  | 
8732  |  |  * }  | 
8733  |  |  * \endcode  | 
8734  |  |  *  | 
8735  |  |  * @see GetLayer()  | 
8736  |  |  *  | 
8737  |  |  * @since GDAL 2.3  | 
8738  |  |  */  | 
8739  |  | GDALDataset::Layers GDALDataset::GetLayers()  | 
8740  | 0  | { | 
8741  | 0  |     return Layers(this);  | 
8742  | 0  | }  | 
8743  |  |  | 
8744  |  | /************************************************************************/  | 
8745  |  | /*                                 begin()                              */  | 
8746  |  | /************************************************************************/  | 
8747  |  |  | 
8748  |  | /**  | 
8749  |  |  \brief Return beginning of layer iterator.  | 
8750  |  |  | 
8751  |  |  @since GDAL 2.3  | 
8752  |  | */  | 
8753  |  |  | 
8754  |  | GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const  | 
8755  | 0  | { | 
8756  | 0  |     return {m_poSelf, true}; | 
8757  | 0  | }  | 
8758  |  |  | 
8759  |  | /************************************************************************/  | 
8760  |  | /*                                  end()                               */  | 
8761  |  | /************************************************************************/  | 
8762  |  |  | 
8763  |  | /**  | 
8764  |  |  \brief Return end of layer iterator.  | 
8765  |  |  | 
8766  |  |  @since GDAL 2.3  | 
8767  |  | */  | 
8768  |  |  | 
8769  |  | GDALDataset::Layers::Iterator GDALDataset::Layers::end() const  | 
8770  | 0  | { | 
8771  | 0  |     return {m_poSelf, false}; | 
8772  | 0  | }  | 
8773  |  |  | 
8774  |  | /************************************************************************/  | 
8775  |  | /*                                  size()                             */  | 
8776  |  | /************************************************************************/  | 
8777  |  |  | 
8778  |  | /**  | 
8779  |  |  \brief Get the number of layers in this dataset.  | 
8780  |  |  | 
8781  |  |  @return layer count.  | 
8782  |  |  | 
8783  |  |  @since GDAL 2.3  | 
8784  |  | */  | 
8785  |  |  | 
8786  |  | size_t GDALDataset::Layers::size() const  | 
8787  | 0  | { | 
8788  | 0  |     return static_cast<size_t>(m_poSelf->GetLayerCount());  | 
8789  | 0  | }  | 
8790  |  |  | 
8791  |  | /************************************************************************/  | 
8792  |  | /*                                operator[]()                          */  | 
8793  |  | /************************************************************************/  | 
8794  |  | /**  | 
8795  |  |  \brief Fetch a layer by index.  | 
8796  |  |  | 
8797  |  |  The returned layer remains owned by the  | 
8798  |  |  GDALDataset and should not be deleted by the application.  | 
8799  |  |  | 
8800  |  |  @param iLayer a layer number between 0 and size()-1.  | 
8801  |  |  | 
8802  |  |  @return the layer, or nullptr if iLayer is out of range or an error occurs.  | 
8803  |  |  | 
8804  |  |  @since GDAL 2.3  | 
8805  |  | */  | 
8806  |  |  | 
8807  |  | OGRLayer *GDALDataset::Layers::operator[](int iLayer)  | 
8808  | 0  | { | 
8809  | 0  |     return m_poSelf->GetLayer(iLayer);  | 
8810  | 0  | }  | 
8811  |  |  | 
8812  |  | /************************************************************************/  | 
8813  |  | /*                                operator[]()                          */  | 
8814  |  | /************************************************************************/  | 
8815  |  | /**  | 
8816  |  |  \brief Fetch a layer by index.  | 
8817  |  |  | 
8818  |  |  The returned layer remains owned by the  | 
8819  |  |  GDALDataset and should not be deleted by the application.  | 
8820  |  |  | 
8821  |  |  @param iLayer a layer number between 0 and size()-1.  | 
8822  |  |  | 
8823  |  |  @return the layer, or nullptr if iLayer is out of range or an error occurs.  | 
8824  |  |  | 
8825  |  |  @since GDAL 2.3  | 
8826  |  | */  | 
8827  |  |  | 
8828  |  | OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)  | 
8829  | 0  | { | 
8830  | 0  |     return m_poSelf->GetLayer(static_cast<int>(iLayer));  | 
8831  | 0  | }  | 
8832  |  |  | 
8833  |  | /************************************************************************/  | 
8834  |  | /*                                operator[]()                          */  | 
8835  |  | /************************************************************************/  | 
8836  |  | /**  | 
8837  |  |  \brief Fetch a layer by name.  | 
8838  |  |  | 
8839  |  |  The returned layer remains owned by the  | 
8840  |  |  GDALDataset and should not be deleted by the application.  | 
8841  |  |  | 
8842  |  |  @param pszLayerName layer name  | 
8843  |  |  | 
8844  |  |  @return the layer, or nullptr if pszLayerName does not match with a layer  | 
8845  |  |  | 
8846  |  |  @since GDAL 2.3  | 
8847  |  | */  | 
8848  |  |  | 
8849  |  | OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)  | 
8850  | 0  | { | 
8851  | 0  |     return m_poSelf->GetLayerByName(pszLayerName);  | 
8852  | 0  | }  | 
8853  |  |  | 
8854  |  | /************************************************************************/  | 
8855  |  | /*               GDALDataset::Bands::Iterator::Private                 */  | 
8856  |  | /************************************************************************/  | 
8857  |  |  | 
8858  |  | struct GDALDataset::Bands::Iterator::Private  | 
8859  |  | { | 
8860  |  |     GDALRasterBand *m_poBand = nullptr;  | 
8861  |  |     int m_iCurBand = 0;  | 
8862  |  |     int m_nBandCount = 0;  | 
8863  |  |     GDALDataset *m_poDS = nullptr;  | 
8864  |  | };  | 
8865  |  |  | 
8866  |  | GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)  | 
8867  | 0  |     : m_poPrivate(new GDALDataset::Bands::Iterator::Private())  | 
8868  | 0  | { | 
8869  | 0  |     m_poPrivate->m_poDS = poDS;  | 
8870  | 0  |     m_poPrivate->m_nBandCount = poDS->GetRasterCount();  | 
8871  | 0  |     if (bStart)  | 
8872  | 0  |     { | 
8873  | 0  |         if (m_poPrivate->m_nBandCount)  | 
8874  | 0  |             m_poPrivate->m_poBand = poDS->GetRasterBand(1);  | 
8875  | 0  |     }  | 
8876  | 0  |     else  | 
8877  | 0  |     { | 
8878  | 0  |         m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;  | 
8879  | 0  |     }  | 
8880  | 0  | }  | 
8881  |  |  | 
8882  | 0  | GDALDataset::Bands::Iterator::~Iterator() = default;  | 
8883  |  |  | 
8884  |  | GDALRasterBand *GDALDataset::Bands::Iterator::operator*()  | 
8885  | 0  | { | 
8886  | 0  |     return m_poPrivate->m_poBand;  | 
8887  | 0  | }  | 
8888  |  |  | 
8889  |  | GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()  | 
8890  | 0  | { | 
8891  | 0  |     m_poPrivate->m_iCurBand++;  | 
8892  | 0  |     if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)  | 
8893  | 0  |     { | 
8894  | 0  |         m_poPrivate->m_poBand =  | 
8895  | 0  |             m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);  | 
8896  | 0  |     }  | 
8897  | 0  |     else  | 
8898  | 0  |     { | 
8899  | 0  |         m_poPrivate->m_poBand = nullptr;  | 
8900  | 0  |     }  | 
8901  | 0  |     return *this;  | 
8902  | 0  | }  | 
8903  |  |  | 
8904  |  | bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const  | 
8905  | 0  | { | 
8906  | 0  |     return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;  | 
8907  | 0  | }  | 
8908  |  |  | 
8909  |  | /************************************************************************/  | 
8910  |  | /*                            GetBands()                           */  | 
8911  |  | /************************************************************************/  | 
8912  |  |  | 
8913  |  | /** Function that returns an iterable object over GDALRasterBand in the dataset.  | 
8914  |  |  *  | 
8915  |  |  * This is a C++ iterator friendly version of GetRasterBand().  | 
8916  |  |  *  | 
8917  |  |  * Typical use is:  | 
8918  |  |  * \code{.cpp} | 
8919  |  |  * for( auto&& poBand: poDS->GetBands() )  | 
8920  |  |  * { | 
8921  |  |  *       std::cout << "Band  << poBand->GetDescription() << std::endl;  | 
8922  |  |  * }  | 
8923  |  |  * \endcode  | 
8924  |  |  *  | 
8925  |  |  * @see GetRasterBand()  | 
8926  |  |  *  | 
8927  |  |  * @since GDAL 2.3  | 
8928  |  |  */  | 
8929  |  | GDALDataset::Bands GDALDataset::GetBands()  | 
8930  | 0  | { | 
8931  | 0  |     return Bands(this);  | 
8932  | 0  | }  | 
8933  |  |  | 
8934  |  | /************************************************************************/  | 
8935  |  | /*                                 begin()                              */  | 
8936  |  | /************************************************************************/  | 
8937  |  |  | 
8938  |  | /**  | 
8939  |  |  \brief Return beginning of band iterator.  | 
8940  |  |  | 
8941  |  |  @since GDAL 2.3  | 
8942  |  | */  | 
8943  |  |  | 
8944  |  | const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const  | 
8945  | 0  | { | 
8946  | 0  |     return {m_poSelf, true}; | 
8947  | 0  | }  | 
8948  |  |  | 
8949  |  | /************************************************************************/  | 
8950  |  | /*                                  end()                               */  | 
8951  |  | /************************************************************************/  | 
8952  |  |  | 
8953  |  | /**  | 
8954  |  |  \brief Return end of band iterator.  | 
8955  |  |  | 
8956  |  |  @since GDAL 2.3  | 
8957  |  | */  | 
8958  |  |  | 
8959  |  | const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const  | 
8960  | 0  | { | 
8961  | 0  |     return {m_poSelf, false}; | 
8962  | 0  | }  | 
8963  |  |  | 
8964  |  | /************************************************************************/  | 
8965  |  | /*                                  size()                             */  | 
8966  |  | /************************************************************************/  | 
8967  |  |  | 
8968  |  | /**  | 
8969  |  |  \brief Get the number of raster bands in this dataset.  | 
8970  |  |  | 
8971  |  |  @return raster band count.  | 
8972  |  |  | 
8973  |  |  @since GDAL 2.3  | 
8974  |  | */  | 
8975  |  |  | 
8976  |  | size_t GDALDataset::Bands::size() const  | 
8977  | 0  | { | 
8978  | 0  |     return static_cast<size_t>(m_poSelf->GetRasterCount());  | 
8979  | 0  | }  | 
8980  |  |  | 
8981  |  | /************************************************************************/  | 
8982  |  | /*                                operator[]()                          */  | 
8983  |  | /************************************************************************/  | 
8984  |  | /**  | 
8985  |  |  \brief Fetch a raster band by index.  | 
8986  |  |  | 
8987  |  |  The returned band remains owned by the  | 
8988  |  |  GDALDataset and should not be deleted by the application.  | 
8989  |  |  | 
8990  |  |  @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is  | 
8991  |  |  consistent with the conventions of C/C++, i.e. starting at 0.  | 
8992  |  |  | 
8993  |  |  @param iBand a band index between 0 and size()-1.  | 
8994  |  |  | 
8995  |  |  @return the band, or nullptr if iBand is out of range or an error occurs.  | 
8996  |  |  | 
8997  |  |  @since GDAL 2.3  | 
8998  |  | */  | 
8999  |  |  | 
9000  |  | GDALRasterBand *GDALDataset::Bands::operator[](int iBand)  | 
9001  | 0  | { | 
9002  | 0  |     return m_poSelf->GetRasterBand(1 + iBand);  | 
9003  | 0  | }  | 
9004  |  |  | 
9005  |  | /************************************************************************/  | 
9006  |  | /*                                operator[]()                          */  | 
9007  |  | /************************************************************************/  | 
9008  |  |  | 
9009  |  | /**  | 
9010  |  |  \brief Fetch a raster band by index.  | 
9011  |  |  | 
9012  |  |  The returned band remains owned by the  | 
9013  |  |  GDALDataset and should not be deleted by the application.  | 
9014  |  |  | 
9015  |  |  @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is  | 
9016  |  |  consistent with the conventions of C/C++, i.e. starting at 0.  | 
9017  |  |  | 
9018  |  |  @param iBand a band index between 0 and size()-1.  | 
9019  |  |  | 
9020  |  |  @return the band, or nullptr if iBand is out of range or an error occurs.  | 
9021  |  |  | 
9022  |  |  @since GDAL 2.3  | 
9023  |  | */  | 
9024  |  |  | 
9025  |  | GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)  | 
9026  | 0  | { | 
9027  | 0  |     return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));  | 
9028  | 0  | }  | 
9029  |  |  | 
9030  |  | /************************************************************************/  | 
9031  |  | /*                           GetRootGroup()                             */  | 
9032  |  | /************************************************************************/  | 
9033  |  |  | 
9034  |  | /**  | 
9035  |  |  \brief Return the root GDALGroup of this dataset.  | 
9036  |  |  | 
9037  |  |  Only valid for multidimensional datasets.  | 
9038  |  |  | 
9039  |  |  This is the same as the C function GDALDatasetGetRootGroup().  | 
9040  |  |  | 
9041  |  |  @since GDAL 3.1  | 
9042  |  | */  | 
9043  |  |  | 
9044  |  | std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const  | 
9045  | 0  | { | 
9046  | 0  |     return nullptr;  | 
9047  | 0  | }  | 
9048  |  |  | 
9049  |  | /************************************************************************/  | 
9050  |  | /*                        GetRawBinaryLayout()                          */  | 
9051  |  | /************************************************************************/  | 
9052  |  |  | 
9053  |  | //! @cond Doxygen_Suppress  | 
9054  |  | /**  | 
9055  |  |  \brief Return the layout of a dataset that can be considered as a raw binary  | 
9056  |  |  format.  | 
9057  |  |  | 
9058  |  |  @param sLayout Structure that will be set if the dataset is a raw binary one.  | 
9059  |  |  @return true if the dataset is a raw binary one.  | 
9060  |  |  @since GDAL 3.1  | 
9061  |  | */  | 
9062  |  |  | 
9063  |  | bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)  | 
9064  | 0  | { | 
9065  | 0  |     CPL_IGNORE_RET_VAL(sLayout);  | 
9066  | 0  |     return false;  | 
9067  | 0  | }  | 
9068  |  |  | 
9069  |  | //! @endcond  | 
9070  |  |  | 
9071  |  | /************************************************************************/  | 
9072  |  | /*                          ClearStatistics()                           */  | 
9073  |  | /************************************************************************/  | 
9074  |  |  | 
9075  |  | /**  | 
9076  |  |  \brief Clear statistics  | 
9077  |  |  | 
9078  |  |  Only implemented for now in PAM supported datasets  | 
9079  |  |  | 
9080  |  |  This is the same as the C function GDALDatasetClearStatistics().  | 
9081  |  |  | 
9082  |  |  @since GDAL 3.2  | 
9083  |  | */  | 
9084  |  |  | 
9085  |  | void GDALDataset::ClearStatistics()  | 
9086  | 0  | { | 
9087  | 0  |     auto poRootGroup = GetRootGroup();  | 
9088  | 0  |     if (poRootGroup)  | 
9089  | 0  |         poRootGroup->ClearStatistics();  | 
9090  | 0  | }  | 
9091  |  |  | 
9092  |  | /************************************************************************/  | 
9093  |  | /*                        GDALDatasetClearStatistics()                  */  | 
9094  |  | /************************************************************************/  | 
9095  |  |  | 
9096  |  | /**  | 
9097  |  |  \brief Clear statistics  | 
9098  |  |  | 
9099  |  |  This is the same as the C++ method GDALDataset::ClearStatistics().  | 
9100  |  |  | 
9101  |  |  @since GDAL 3.2  | 
9102  |  | */  | 
9103  |  |  | 
9104  |  | void GDALDatasetClearStatistics(GDALDatasetH hDS)  | 
9105  | 0  | { | 
9106  | 0  |     VALIDATE_POINTER0(hDS, __func__);  | 
9107  | 0  |     GDALDataset::FromHandle(hDS)->ClearStatistics();  | 
9108  | 0  | }  | 
9109  |  |  | 
9110  |  | /************************************************************************/  | 
9111  |  | /*                        GetFieldDomainNames()                         */  | 
9112  |  | /************************************************************************/  | 
9113  |  |  | 
9114  |  | /** Returns a list of the names of all field domains stored in the dataset.  | 
9115  |  |  *  | 
9116  |  |  * @note The default implementation assumes that drivers fully populate  | 
9117  |  |  * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect  | 
9118  |  |  * then a specialized implementation of GetFieldDomainNames() must be  | 
9119  |  |  * implemented.  | 
9120  |  |  *  | 
9121  |  |  * @param papszOptions Driver specific options determining how attributes  | 
9122  |  |  * should be retrieved. Pass nullptr for default behavior.  | 
9123  |  |  *  | 
9124  |  |  * @return list of field domain names  | 
9125  |  |  * @since GDAL 3.5  | 
9126  |  |  */  | 
9127  |  | std::vector<std::string>  | 
9128  |  | GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const  | 
9129  | 0  | { | 
9130  |  | 
  | 
9131  | 0  |     std::vector<std::string> names;  | 
9132  | 0  |     names.reserve(m_oMapFieldDomains.size());  | 
9133  | 0  |     for (const auto &it : m_oMapFieldDomains)  | 
9134  | 0  |     { | 
9135  | 0  |         names.emplace_back(it.first);  | 
9136  | 0  |     }  | 
9137  | 0  |     return names;  | 
9138  | 0  | }  | 
9139  |  |  | 
9140  |  | /************************************************************************/  | 
9141  |  | /*                      GDALDatasetGetFieldDomainNames()                */  | 
9142  |  | /************************************************************************/  | 
9143  |  |  | 
9144  |  | /** Returns a list of the names of all field domains stored in the dataset.  | 
9145  |  |  *  | 
9146  |  |  * This is the same as the C++ method GDALDataset::GetFieldDomainNames().  | 
9147  |  |  *  | 
9148  |  |  * @param hDS Dataset handle.  | 
9149  |  |  * @param papszOptions Driver specific options determining how attributes  | 
9150  |  |  * should be retrieved. Pass nullptr for default behavior.  | 
9151  |  |  *  | 
9152  |  |  * @return list of field domain names, to be freed with CSLDestroy()  | 
9153  |  |  * @since GDAL 3.5  | 
9154  |  |  */  | 
9155  |  | char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,  | 
9156  |  |                                       CSLConstList papszOptions)  | 
9157  | 0  | { | 
9158  | 0  |     VALIDATE_POINTER1(hDS, __func__, nullptr);  | 
9159  | 0  |     auto names =  | 
9160  | 0  |         GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);  | 
9161  | 0  |     CPLStringList res;  | 
9162  | 0  |     for (const auto &name : names)  | 
9163  | 0  |     { | 
9164  | 0  |         res.AddString(name.c_str());  | 
9165  | 0  |     }  | 
9166  | 0  |     return res.StealList();  | 
9167  | 0  | }  | 
9168  |  |  | 
9169  |  | /************************************************************************/  | 
9170  |  | /*                        GetFieldDomain()                              */  | 
9171  |  | /************************************************************************/  | 
9172  |  |  | 
9173  |  | /** Get a field domain from its name.  | 
9174  |  |  *  | 
9175  |  |  * @return the field domain, or nullptr if not found.  | 
9176  |  |  * @since GDAL 3.3  | 
9177  |  |  */  | 
9178  |  | const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const  | 
9179  | 0  | { | 
9180  | 0  |     const auto iter = m_oMapFieldDomains.find(name);  | 
9181  | 0  |     if (iter == m_oMapFieldDomains.end())  | 
9182  | 0  |         return nullptr;  | 
9183  | 0  |     return iter->second.get();  | 
9184  | 0  | }  | 
9185  |  |  | 
9186  |  | /************************************************************************/  | 
9187  |  | /*                      GDALDatasetGetFieldDomain()                     */  | 
9188  |  | /************************************************************************/  | 
9189  |  |  | 
9190  |  | /** Get a field domain from its name.  | 
9191  |  |  *  | 
9192  |  |  * This is the same as the C++ method GDALDataset::GetFieldDomain().  | 
9193  |  |  *  | 
9194  |  |  * @param hDS Dataset handle.  | 
9195  |  |  * @param pszName Name of field domain.  | 
9196  |  |  * @return the field domain (ownership remains to the dataset), or nullptr if  | 
9197  |  |  * not found.  | 
9198  |  |  * @since GDAL 3.3  | 
9199  |  |  */  | 
9200  |  | OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)  | 
9201  | 0  | { | 
9202  | 0  |     VALIDATE_POINTER1(hDS, __func__, nullptr);  | 
9203  | 0  |     VALIDATE_POINTER1(pszName, __func__, nullptr);  | 
9204  | 0  |     return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(  | 
9205  | 0  |         GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));  | 
9206  | 0  | }  | 
9207  |  |  | 
9208  |  | /************************************************************************/  | 
9209  |  | /*                         AddFieldDomain()                             */  | 
9210  |  | /************************************************************************/  | 
9211  |  |  | 
9212  |  | /** Add a field domain to the dataset.  | 
9213  |  |  *  | 
9214  |  |  * Only a few drivers will support this operation, and some of them might only  | 
9215  |  |  * support it only for some types of field domains.  | 
9216  |  |  * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers  | 
9217  |  |  * support this operation. A dataset having at least some support for this  | 
9218  |  |  * operation should report the ODsCAddFieldDomain dataset capability.  | 
9219  |  |  *  | 
9220  |  |  * Anticipated failures will not be emitted through the CPLError()  | 
9221  |  |  * infrastructure, but will be reported in the failureReason output parameter.  | 
9222  |  |  *  | 
9223  |  |  * @note Drivers should make sure to update m_oMapFieldDomains in order for the  | 
9224  |  |  * default implementation of GetFieldDomainNames() to work correctly, or  | 
9225  |  |  * alternatively a specialized implementation of GetFieldDomainNames() should be  | 
9226  |  |  * implemented.  | 
9227  |  |  *  | 
9228  |  |  * @param domain The domain definition.  | 
9229  |  |  * @param failureReason      Output parameter. Will contain an error message if  | 
9230  |  |  *                           an error occurs.  | 
9231  |  |  * @return true in case of success.  | 
9232  |  |  * @since GDAL 3.3  | 
9233  |  |  */  | 
9234  |  | bool GDALDataset::AddFieldDomain(  | 
9235  |  |     CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,  | 
9236  |  |     std::string &failureReason)  | 
9237  | 0  | { | 
9238  | 0  |     failureReason = "AddFieldDomain not supported by this driver";  | 
9239  | 0  |     return false;  | 
9240  | 0  | }  | 
9241  |  |  | 
9242  |  | /************************************************************************/  | 
9243  |  | /*                     GDALDatasetAddFieldDomain()                      */  | 
9244  |  | /************************************************************************/  | 
9245  |  |  | 
9246  |  | /** Add a field domain to the dataset.  | 
9247  |  |  *  | 
9248  |  |  * Only a few drivers will support this operation, and some of them might only  | 
9249  |  |  * support it only for some types of field domains.  | 
9250  |  |  * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers  | 
9251  |  |  * support this operation. A dataset having at least some support for this  | 
9252  |  |  * operation should report the ODsCAddFieldDomain dataset capability.  | 
9253  |  |  *  | 
9254  |  |  * Anticipated failures will not be emitted through the CPLError()  | 
9255  |  |  * infrastructure, but will be reported in the ppszFailureReason output  | 
9256  |  |  * parameter.  | 
9257  |  |  *  | 
9258  |  |  * @param hDS                Dataset handle.  | 
9259  |  |  * @param hFieldDomain       The domain definition. Contrary to the C++ version,  | 
9260  |  |  *                           the passed object is copied.  | 
9261  |  |  * @param ppszFailureReason  Output parameter. Will contain an error message if  | 
9262  |  |  *                           an error occurs (*ppszFailureReason to be freed  | 
9263  |  |  *                           with CPLFree). May be NULL.  | 
9264  |  |  * @return true in case of success.  | 
9265  |  |  * @since GDAL 3.3  | 
9266  |  |  */  | 
9267  |  | bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,  | 
9268  |  |                                char **ppszFailureReason)  | 
9269  | 0  | { | 
9270  | 0  |     VALIDATE_POINTER1(hDS, __func__, false);  | 
9271  | 0  |     VALIDATE_POINTER1(hFieldDomain, __func__, false);  | 
9272  | 0  |     auto poDomain = std::unique_ptr<OGRFieldDomain>(  | 
9273  | 0  |         OGRFieldDomain::FromHandle(hFieldDomain)->Clone());  | 
9274  | 0  |     if (poDomain == nullptr)  | 
9275  | 0  |         return false;  | 
9276  | 0  |     std::string failureReason;  | 
9277  | 0  |     const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(  | 
9278  | 0  |         std::move(poDomain), failureReason);  | 
9279  | 0  |     if (ppszFailureReason)  | 
9280  | 0  |     { | 
9281  | 0  |         *ppszFailureReason =  | 
9282  | 0  |             failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());  | 
9283  | 0  |     }  | 
9284  | 0  |     return bRet;  | 
9285  | 0  | }  | 
9286  |  |  | 
9287  |  | /************************************************************************/  | 
9288  |  | /*                        DeleteFieldDomain()                           */  | 
9289  |  | /************************************************************************/  | 
9290  |  |  | 
9291  |  | /** Removes a field domain from the dataset.  | 
9292  |  |  *  | 
9293  |  |  * Only a few drivers will support this operation.  | 
9294  |  |  *  | 
9295  |  |  * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers  | 
9296  |  |  * support this operation. A dataset having at least some support for this  | 
9297  |  |  * operation should report the ODsCDeleteFieldDomain dataset capability.  | 
9298  |  |  *  | 
9299  |  |  * Anticipated failures will not be emitted through the CPLError()  | 
9300  |  |  * infrastructure, but will be reported in the failureReason output parameter.  | 
9301  |  |  *  | 
9302  |  |  * @note Drivers should make sure to update m_oMapFieldDomains in order for the  | 
9303  |  |  * default implementation of GetFieldDomainNames() to work correctly, or  | 
9304  |  |  * alternatively a specialized implementation of GetFieldDomainNames() should be  | 
9305  |  |  * implemented.  | 
9306  |  |  *  | 
9307  |  |  * @param name The domain name.  | 
9308  |  |  * @param failureReason      Output parameter. Will contain an error message if  | 
9309  |  |  *                           an error occurs.  | 
9310  |  |  * @return true in case of success.  | 
9311  |  |  * @since GDAL 3.5  | 
9312  |  |  */  | 
9313  |  | bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,  | 
9314  |  |                                     std::string &failureReason)  | 
9315  | 0  | { | 
9316  | 0  |     failureReason = "DeleteFieldDomain not supported by this driver";  | 
9317  | 0  |     return false;  | 
9318  | 0  | }  | 
9319  |  |  | 
9320  |  | /************************************************************************/  | 
9321  |  | /*                  GDALDatasetDeleteFieldDomain()                      */  | 
9322  |  | /************************************************************************/  | 
9323  |  |  | 
9324  |  | /** Removes a field domain from the dataset.  | 
9325  |  |  *  | 
9326  |  |  * Only a few drivers will support this operation.  | 
9327  |  |  *  | 
9328  |  |  * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers  | 
9329  |  |  * support this operation. A dataset having at least some support for this  | 
9330  |  |  * operation should report the ODsCDeleteFieldDomain dataset capability.  | 
9331  |  |  *  | 
9332  |  |  * Anticipated failures will not be emitted through the CPLError()  | 
9333  |  |  * infrastructure, but will be reported in the ppszFailureReason output  | 
9334  |  |  * parameter.  | 
9335  |  |  *  | 
9336  |  |  * @param hDS                Dataset handle.  | 
9337  |  |  * @param pszName            The domain name.  | 
9338  |  |  * @param ppszFailureReason  Output parameter. Will contain an error message if  | 
9339  |  |  *                           an error occurs (*ppszFailureReason to be freed  | 
9340  |  |  *                           with CPLFree). May be NULL.  | 
9341  |  |  * @return true in case of success.  | 
9342  |  |  * @since GDAL 3.3  | 
9343  |  |  */  | 
9344  |  | bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,  | 
9345  |  |                                   char **ppszFailureReason)  | 
9346  | 0  | { | 
9347  | 0  |     VALIDATE_POINTER1(hDS, __func__, false);  | 
9348  | 0  |     VALIDATE_POINTER1(pszName, __func__, false);  | 
9349  | 0  |     std::string failureReason;  | 
9350  | 0  |     const bool bRet =  | 
9351  | 0  |         GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);  | 
9352  | 0  |     if (ppszFailureReason)  | 
9353  | 0  |     { | 
9354  | 0  |         *ppszFailureReason =  | 
9355  | 0  |             failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());  | 
9356  | 0  |     }  | 
9357  | 0  |     return bRet;  | 
9358  | 0  | }  | 
9359  |  |  | 
9360  |  | /************************************************************************/  | 
9361  |  | /*                       UpdateFieldDomain()                            */  | 
9362  |  | /************************************************************************/  | 
9363  |  |  | 
9364  |  | /** Updates an existing field domain by replacing its definition.  | 
9365  |  |  *  | 
9366  |  |  * The existing field domain with matching name will be replaced.  | 
9367  |  |  *  | 
9368  |  |  * Only a few drivers will support this operation, and some of them might only  | 
9369  |  |  * support it only for some types of field domains.  | 
9370  |  |  * At the time of writing (GDAL 3.5), only the Memory driver  | 
9371  |  |  * supports this operation. A dataset having at least some support for this  | 
9372  |  |  * operation should report the ODsCUpdateFieldDomain dataset capability.  | 
9373  |  |  *  | 
9374  |  |  * Anticipated failures will not be emitted through the CPLError()  | 
9375  |  |  * infrastructure, but will be reported in the failureReason output parameter.  | 
9376  |  |  *  | 
9377  |  |  * @param domain The domain definition.  | 
9378  |  |  * @param failureReason      Output parameter. Will contain an error message if  | 
9379  |  |  *                           an error occurs.  | 
9380  |  |  * @return true in case of success.  | 
9381  |  |  * @since GDAL 3.5  | 
9382  |  |  */  | 
9383  |  | bool GDALDataset::UpdateFieldDomain(  | 
9384  |  |     CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,  | 
9385  |  |     std::string &failureReason)  | 
9386  | 0  | { | 
9387  | 0  |     failureReason = "UpdateFieldDomain not supported by this driver";  | 
9388  | 0  |     return false;  | 
9389  | 0  | }  | 
9390  |  |  | 
9391  |  | /************************************************************************/  | 
9392  |  | /*                  GDALDatasetUpdateFieldDomain()                      */  | 
9393  |  | /************************************************************************/  | 
9394  |  |  | 
9395  |  | /** Updates an existing field domain by replacing its definition.  | 
9396  |  |  *  | 
9397  |  |  * The existing field domain with matching name will be replaced.  | 
9398  |  |  *  | 
9399  |  |  * Only a few drivers will support this operation, and some of them might only  | 
9400  |  |  * support it only for some types of field domains.  | 
9401  |  |  * At the time of writing (GDAL 3.5), only the Memory driver  | 
9402  |  |  * supports this operation. A dataset having at least some support for this  | 
9403  |  |  * operation should report the ODsCUpdateFieldDomain dataset capability.  | 
9404  |  |  *  | 
9405  |  |  * Anticipated failures will not be emitted through the CPLError()  | 
9406  |  |  * infrastructure, but will be reported in the failureReason output parameter.  | 
9407  |  |  *  | 
9408  |  |  * @param hDS                Dataset handle.  | 
9409  |  |  * @param hFieldDomain       The domain definition. Contrary to the C++ version,  | 
9410  |  |  *                           the passed object is copied.  | 
9411  |  |  * @param ppszFailureReason  Output parameter. Will contain an error message if  | 
9412  |  |  *                           an error occurs (*ppszFailureReason to be freed  | 
9413  |  |  *                           with CPLFree). May be NULL.  | 
9414  |  |  * @return true in case of success.  | 
9415  |  |  * @since GDAL 3.5  | 
9416  |  |  */  | 
9417  |  | bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,  | 
9418  |  |                                   OGRFieldDomainH hFieldDomain,  | 
9419  |  |                                   char **ppszFailureReason)  | 
9420  | 0  | { | 
9421  | 0  |     VALIDATE_POINTER1(hDS, __func__, false);  | 
9422  | 0  |     VALIDATE_POINTER1(hFieldDomain, __func__, false);  | 
9423  | 0  |     auto poDomain = std::unique_ptr<OGRFieldDomain>(  | 
9424  | 0  |         OGRFieldDomain::FromHandle(hFieldDomain)->Clone());  | 
9425  | 0  |     if (poDomain == nullptr)  | 
9426  | 0  |         return false;  | 
9427  | 0  |     std::string failureReason;  | 
9428  | 0  |     const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(  | 
9429  | 0  |         std::move(poDomain), failureReason);  | 
9430  | 0  |     if (ppszFailureReason)  | 
9431  | 0  |     { | 
9432  | 0  |         *ppszFailureReason =  | 
9433  | 0  |             failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());  | 
9434  | 0  |     }  | 
9435  | 0  |     return bRet;  | 
9436  | 0  | }  | 
9437  |  |  | 
9438  |  | /************************************************************************/  | 
9439  |  | /*                        GetRelationshipNames()                        */  | 
9440  |  | /************************************************************************/  | 
9441  |  |  | 
9442  |  | /** Returns a list of the names of all relationships stored in the dataset.  | 
9443  |  |  *  | 
9444  |  |  * @param papszOptions Driver specific options determining how relationships  | 
9445  |  |  * should be retrieved. Pass nullptr for default behavior.  | 
9446  |  |  *  | 
9447  |  |  * @return list of relationship names  | 
9448  |  |  * @since GDAL 3.6  | 
9449  |  |  */  | 
9450  |  | std::vector<std::string>  | 
9451  |  | GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const  | 
9452  | 0  | { | 
9453  | 0  |     return {}; | 
9454  | 0  | }  | 
9455  |  |  | 
9456  |  | /************************************************************************/  | 
9457  |  | /*                     GDALDatasetGetRelationshipNames()                */  | 
9458  |  | /************************************************************************/  | 
9459  |  |  | 
9460  |  | /** Returns a list of the names of all relationships stored in the dataset.  | 
9461  |  |  *  | 
9462  |  |  * This is the same as the C++ method GDALDataset::GetRelationshipNames().  | 
9463  |  |  *  | 
9464  |  |  * @param hDS Dataset handle.  | 
9465  |  |  * @param papszOptions Driver specific options determining how relationships  | 
9466  |  |  * should be retrieved. Pass nullptr for default behavior.  | 
9467  |  |  *  | 
9468  |  |  * @return list of relationship names, to be freed with CSLDestroy()  | 
9469  |  |  * @since GDAL 3.6  | 
9470  |  |  */  | 
9471  |  | char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,  | 
9472  |  |                                        CSLConstList papszOptions)  | 
9473  | 0  | { | 
9474  | 0  |     VALIDATE_POINTER1(hDS, __func__, nullptr);  | 
9475  | 0  |     auto names =  | 
9476  | 0  |         GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);  | 
9477  | 0  |     CPLStringList res;  | 
9478  | 0  |     for (const auto &name : names)  | 
9479  | 0  |     { | 
9480  | 0  |         res.AddString(name.c_str());  | 
9481  | 0  |     }  | 
9482  | 0  |     return res.StealList();  | 
9483  | 0  | }  | 
9484  |  |  | 
9485  |  | /************************************************************************/  | 
9486  |  | /*                        GetRelationship()                             */  | 
9487  |  | /************************************************************************/  | 
9488  |  |  | 
9489  |  | /** Get a relationship from its name.  | 
9490  |  |  *  | 
9491  |  |  * @return the relationship, or nullptr if not found.  | 
9492  |  |  * @since GDAL 3.6  | 
9493  |  |  */  | 
9494  |  | const GDALRelationship *  | 
9495  |  | GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const  | 
9496  | 0  | { | 
9497  | 0  |     return nullptr;  | 
9498  | 0  | }  | 
9499  |  |  | 
9500  |  | /************************************************************************/  | 
9501  |  | /*                      GDALDatasetGetRelationship()                    */  | 
9502  |  | /************************************************************************/  | 
9503  |  |  | 
9504  |  | /** Get a relationship from its name.  | 
9505  |  |  *  | 
9506  |  |  * This is the same as the C++ method GDALDataset::GetRelationship().  | 
9507  |  |  *  | 
9508  |  |  * @param hDS Dataset handle.  | 
9509  |  |  * @param pszName Name of relationship.  | 
9510  |  |  * @return the relationship (ownership remains to the dataset), or nullptr if  | 
9511  |  |  * not found.  | 
9512  |  |  * @since GDAL 3.6  | 
9513  |  |  */  | 
9514  |  | GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,  | 
9515  |  |                                              const char *pszName)  | 
9516  | 0  | { | 
9517  | 0  |     VALIDATE_POINTER1(hDS, __func__, nullptr);  | 
9518  | 0  |     VALIDATE_POINTER1(pszName, __func__, nullptr);  | 
9519  | 0  |     return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(  | 
9520  | 0  |         GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));  | 
9521  | 0  | }  | 
9522  |  |  | 
9523  |  | /************************************************************************/  | 
9524  |  | /*                         AddRelationship()                            */  | 
9525  |  | /************************************************************************/  | 
9526  |  |  | 
9527  |  | /** Add a relationship to the dataset.  | 
9528  |  |  *  | 
9529  |  |  * Only a few drivers will support this operation, and some of them might only  | 
9530  |  |  * support it only for some types of relationships.  | 
9531  |  |  *  | 
9532  |  |  * A dataset having at least some support for this  | 
9533  |  |  * operation should report the GDsCAddRelationship dataset capability.  | 
9534  |  |  *  | 
9535  |  |  * Anticipated failures will not be emitted through the CPLError()  | 
9536  |  |  * infrastructure, but will be reported in the failureReason output parameter.  | 
9537  |  |  *  | 
9538  |  |  * When adding a many-to-many relationship  | 
9539  |  |  * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the  | 
9540  |  |  * mapping table name (see GDALRelationship::GetMappingTableName) to instruct  | 
9541  |  |  * the driver to create an appropriately named and structured mapping table.  | 
9542  |  |  * Some dataset formats require particular naming conventions and field  | 
9543  |  |  * structures for the mapping table, and delegating the construction of the  | 
9544  |  |  * mapping table to the driver will avoid these pitfalls.  | 
9545  |  |  *  | 
9546  |  |  * @param relationship The relationship definition.  | 
9547  |  |  * @param failureReason      Output parameter. Will contain an error message if  | 
9548  |  |  *                           an error occurs.  | 
9549  |  |  * @return true in case of success.  | 
9550  |  |  * @since GDAL 3.6  | 
9551  |  |  */  | 
9552  |  | bool GDALDataset::AddRelationship(  | 
9553  |  |     CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,  | 
9554  |  |     std::string &failureReason)  | 
9555  | 0  | { | 
9556  | 0  |     failureReason = "AddRelationship not supported by this driver";  | 
9557  | 0  |     return false;  | 
9558  | 0  | }  | 
9559  |  |  | 
9560  |  | /************************************************************************/  | 
9561  |  | /*                     GDALDatasetAddRelationship()                     */  | 
9562  |  | /************************************************************************/  | 
9563  |  |  | 
9564  |  | /** Add a relationship to the dataset.  | 
9565  |  |  *  | 
9566  |  |  * Only a few drivers will support this operation, and some of them might only  | 
9567  |  |  * support it only for some types of relationships.  | 
9568  |  |  *  | 
9569  |  |  * A dataset having at least some support for this  | 
9570  |  |  * operation should report the GDsCAddRelationship dataset capability.  | 
9571  |  |  *  | 
9572  |  |  * Anticipated failures will not be emitted through the CPLError()  | 
9573  |  |  * infrastructure, but will be reported in the failureReason output parameter.  | 
9574  |  |  *  | 
9575  |  |  * When adding a many-to-many relationship  | 
9576  |  |  * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the  | 
9577  |  |  * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the  | 
9578  |  |  * driver to create an appropriately named and structured mapping table. Some  | 
9579  |  |  * dataset formats require particular naming conventions and field structures  | 
9580  |  |  * for the mapping table, and delegating the construction of the mapping table  | 
9581  |  |  * to the driver will avoid these pitfalls.  | 
9582  |  |  *  | 
9583  |  |  * @param hDS                Dataset handle.  | 
9584  |  |  * @param hRelationship      The relationship definition. Contrary to the C++  | 
9585  |  |  * version, the passed object is copied.  | 
9586  |  |  * @param ppszFailureReason  Output parameter. Will contain an error message if  | 
9587  |  |  *                           an error occurs (*ppszFailureReason to be freed  | 
9588  |  |  *                           with CPLFree). May be NULL.  | 
9589  |  |  * @return true in case of success.  | 
9590  |  |  * @since GDAL 3.6  | 
9591  |  |  */  | 
9592  |  | bool GDALDatasetAddRelationship(GDALDatasetH hDS,  | 
9593  |  |                                 GDALRelationshipH hRelationship,  | 
9594  |  |                                 char **ppszFailureReason)  | 
9595  | 0  | { | 
9596  | 0  |     VALIDATE_POINTER1(hDS, __func__, false);  | 
9597  | 0  |     VALIDATE_POINTER1(hRelationship, __func__, false);  | 
9598  | 0  |     std::unique_ptr<GDALRelationship> poRelationship(  | 
9599  | 0  |         new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));  | 
9600  | 0  |     std::string failureReason;  | 
9601  | 0  |     const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(  | 
9602  | 0  |         std::move(poRelationship), failureReason);  | 
9603  | 0  |     if (ppszFailureReason)  | 
9604  | 0  |     { | 
9605  | 0  |         *ppszFailureReason =  | 
9606  | 0  |             failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());  | 
9607  | 0  |     }  | 
9608  | 0  |     return bRet;  | 
9609  | 0  | }  | 
9610  |  |  | 
9611  |  | /************************************************************************/  | 
9612  |  | /*                        DeleteRelationship()                          */  | 
9613  |  | /************************************************************************/  | 
9614  |  |  | 
9615  |  | /** Removes a relationship from the dataset.  | 
9616  |  |  *  | 
9617  |  |  * Only a few drivers will support this operation.  | 
9618  |  |  *  | 
9619  |  |  * A dataset having at least some support for this  | 
9620  |  |  * operation should report the GDsCDeleteRelationship dataset capability.  | 
9621  |  |  *  | 
9622  |  |  * Anticipated failures will not be emitted through the CPLError()  | 
9623  |  |  * infrastructure, but will be reported in the failureReason output parameter.  | 
9624  |  |  *  | 
9625  |  |  * @param name The relationship name.  | 
9626  |  |  * @param failureReason      Output parameter. Will contain an error message if  | 
9627  |  |  *                           an error occurs.  | 
9628  |  |  * @return true in case of success.  | 
9629  |  |  * @since GDAL 3.6  | 
9630  |  |  */  | 
9631  |  | bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,  | 
9632  |  |                                      std::string &failureReason)  | 
9633  | 0  | { | 
9634  | 0  |     failureReason = "DeleteRelationship not supported by this driver";  | 
9635  | 0  |     return false;  | 
9636  | 0  | }  | 
9637  |  |  | 
9638  |  | /************************************************************************/  | 
9639  |  | /*                  GDALDatasetDeleteRelationship()                     */  | 
9640  |  | /************************************************************************/  | 
9641  |  |  | 
9642  |  | /** Removes a relationship from the dataset.  | 
9643  |  |  *  | 
9644  |  |  * Only a few drivers will support this operation.  | 
9645  |  |  *  | 
9646  |  |  * A dataset having at least some support for this  | 
9647  |  |  * operation should report the GDsCDeleteRelationship dataset capability.  | 
9648  |  |  *  | 
9649  |  |  * Anticipated failures will not be emitted through the CPLError()  | 
9650  |  |  * infrastructure, but will be reported in the ppszFailureReason output  | 
9651  |  |  * parameter.  | 
9652  |  |  *  | 
9653  |  |  * @param hDS                Dataset handle.  | 
9654  |  |  * @param pszName            The relationship name.  | 
9655  |  |  * @param ppszFailureReason  Output parameter. Will contain an error message if  | 
9656  |  |  *                           an error occurs (*ppszFailureReason to be freed  | 
9657  |  |  *                           with CPLFree). May be NULL.  | 
9658  |  |  * @return true in case of success.  | 
9659  |  |  * @since GDAL 3.6  | 
9660  |  |  */  | 
9661  |  | bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,  | 
9662  |  |                                    char **ppszFailureReason)  | 
9663  | 0  | { | 
9664  | 0  |     VALIDATE_POINTER1(hDS, __func__, false);  | 
9665  | 0  |     VALIDATE_POINTER1(pszName, __func__, false);  | 
9666  | 0  |     std::string failureReason;  | 
9667  | 0  |     const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(  | 
9668  | 0  |         pszName, failureReason);  | 
9669  | 0  |     if (ppszFailureReason)  | 
9670  | 0  |     { | 
9671  | 0  |         *ppszFailureReason =  | 
9672  | 0  |             failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());  | 
9673  | 0  |     }  | 
9674  | 0  |     return bRet;  | 
9675  | 0  | }  | 
9676  |  |  | 
9677  |  | /************************************************************************/  | 
9678  |  | /*                       UpdateRelationship()                           */  | 
9679  |  | /************************************************************************/  | 
9680  |  |  | 
9681  |  | /** Updates an existing relationship by replacing its definition.  | 
9682  |  |  *  | 
9683  |  |  * The existing relationship with matching name will be replaced.  | 
9684  |  |  *  | 
9685  |  |  * Only a few drivers will support this operation, and some of them might only  | 
9686  |  |  * support it only for some types of relationships.  | 
9687  |  |  * A dataset having at least some support for this  | 
9688  |  |  * operation should report the GDsCUpdateRelationship dataset capability.  | 
9689  |  |  *  | 
9690  |  |  * Anticipated failures will not be emitted through the CPLError()  | 
9691  |  |  * infrastructure, but will be reported in the failureReason output parameter.  | 
9692  |  |  *  | 
9693  |  |  * @param relationship   The relationship definition.  | 
9694  |  |  * @param failureReason  Output parameter. Will contain an error message if  | 
9695  |  |  *                       an error occurs.  | 
9696  |  |  * @return true in case of success.  | 
9697  |  |  * @since GDAL 3.6  | 
9698  |  |  */  | 
9699  |  | bool GDALDataset::UpdateRelationship(  | 
9700  |  |     CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,  | 
9701  |  |     std::string &failureReason)  | 
9702  | 0  | { | 
9703  | 0  |     failureReason = "UpdateRelationship not supported by this driver";  | 
9704  | 0  |     return false;  | 
9705  | 0  | }  | 
9706  |  |  | 
9707  |  | /************************************************************************/  | 
9708  |  | /*                  GDALDatasetUpdateRelationship()                     */  | 
9709  |  | /************************************************************************/  | 
9710  |  |  | 
9711  |  | /** Updates an existing relationship by replacing its definition.  | 
9712  |  |  *  | 
9713  |  |  * The existing relationship with matching name will be replaced.  | 
9714  |  |  *  | 
9715  |  |  * Only a few drivers will support this operation, and some of them might only  | 
9716  |  |  * support it only for some types of relationships.  | 
9717  |  |  * A dataset having at least some support for this  | 
9718  |  |  * operation should report the GDsCUpdateRelationship dataset capability.  | 
9719  |  |  *  | 
9720  |  |  * Anticipated failures will not be emitted through the CPLError()  | 
9721  |  |  * infrastructure, but will be reported in the failureReason output parameter.  | 
9722  |  |  *  | 
9723  |  |  * @param hDS                Dataset handle.  | 
9724  |  |  * @param hRelationship      The relationship definition. Contrary to the C++  | 
9725  |  |  * version, the passed object is copied.  | 
9726  |  |  * @param ppszFailureReason  Output parameter. Will contain an error message if  | 
9727  |  |  *                           an error occurs (*ppszFailureReason to be freed  | 
9728  |  |  *                           with CPLFree). May be NULL.  | 
9729  |  |  * @return true in case of success.  | 
9730  |  |  * @since GDAL 3.5  | 
9731  |  |  */  | 
9732  |  | bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,  | 
9733  |  |                                    GDALRelationshipH hRelationship,  | 
9734  |  |                                    char **ppszFailureReason)  | 
9735  | 0  | { | 
9736  | 0  |     VALIDATE_POINTER1(hDS, __func__, false);  | 
9737  | 0  |     VALIDATE_POINTER1(hRelationship, __func__, false);  | 
9738  | 0  |     std::unique_ptr<GDALRelationship> poRelationship(  | 
9739  | 0  |         new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));  | 
9740  | 0  |     std::string failureReason;  | 
9741  | 0  |     const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(  | 
9742  | 0  |         std::move(poRelationship), failureReason);  | 
9743  | 0  |     if (ppszFailureReason)  | 
9744  | 0  |     { | 
9745  | 0  |         *ppszFailureReason =  | 
9746  | 0  |             failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());  | 
9747  | 0  |     }  | 
9748  | 0  |     return bRet;  | 
9749  | 0  | }  | 
9750  |  |  | 
9751  |  | /************************************************************************/  | 
9752  |  | /*                  GDALDatasetSetQueryLoggerFunc()                     */  | 
9753  |  | /************************************************************************/  | 
9754  |  |  | 
9755  |  | /**  | 
9756  |  |  * Sets the SQL query logger callback.  | 
9757  |  |  *  | 
9758  |  |  * When supported by the driver, the callback will be called with  | 
9759  |  |  * the executed SQL text, the error message, the execution time in milliseconds,  | 
9760  |  |  * the number of records fetched/affected and the client status data.  | 
9761  |  |  *  | 
9762  |  |  * A value of -1 in the execution time or in the number of records indicates  | 
9763  |  |  * that the values are unknown.  | 
9764  |  |  *  | 
9765  |  |  * @param hDS                   Dataset handle.  | 
9766  |  |  * @param pfnQueryLoggerFunc    Callback function  | 
9767  |  |  * @param poQueryLoggerArg      Opaque client status data  | 
9768  |  |  * @return                      true in case of success.  | 
9769  |  |  * @since                       GDAL 3.7  | 
9770  |  |  */  | 
9771  |  | bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,  | 
9772  |  |                                    GDALQueryLoggerFunc pfnQueryLoggerFunc,  | 
9773  |  |                                    void *poQueryLoggerArg)  | 
9774  | 0  | { | 
9775  | 0  |     VALIDATE_POINTER1(hDS, __func__, false);  | 
9776  | 0  |     return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,  | 
9777  | 0  |                                                             poQueryLoggerArg);  | 
9778  | 0  | }  | 
9779  |  |  | 
9780  |  | //! @cond Doxygen_Suppress  | 
9781  |  |  | 
9782  |  | /************************************************************************/  | 
9783  |  | /*                       SetEnableOverviews()                           */  | 
9784  |  | /************************************************************************/  | 
9785  |  |  | 
9786  |  | void GDALDataset::SetEnableOverviews(bool bEnable)  | 
9787  | 0  | { | 
9788  | 0  |     if (m_poPrivate)  | 
9789  | 0  |     { | 
9790  | 0  |         m_poPrivate->m_bOverviewsEnabled = bEnable;  | 
9791  | 0  |     }  | 
9792  | 0  | }  | 
9793  |  |  | 
9794  |  | /************************************************************************/  | 
9795  |  | /*                      AreOverviewsEnabled()                           */  | 
9796  |  | /************************************************************************/  | 
9797  |  |  | 
9798  |  | bool GDALDataset::AreOverviewsEnabled() const  | 
9799  | 0  | { | 
9800  | 0  |     return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;  | 
9801  | 0  | }  | 
9802  |  |  | 
9803  |  | /************************************************************************/  | 
9804  |  | /*                             IsAllBands()                             */  | 
9805  |  | /************************************************************************/  | 
9806  |  |  | 
9807  |  | bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const  | 
9808  | 0  | { | 
9809  | 0  |     if (nBands != nBandCount)  | 
9810  | 0  |         return false;  | 
9811  | 0  |     if (panBandList)  | 
9812  | 0  |     { | 
9813  | 0  |         for (int i = 0; i < nBandCount; ++i)  | 
9814  | 0  |         { | 
9815  | 0  |             if (panBandList[i] != i + 1)  | 
9816  | 0  |                 return false;  | 
9817  | 0  |         }  | 
9818  | 0  |     }  | 
9819  | 0  |     return true;  | 
9820  | 0  | }  | 
9821  |  |  | 
9822  |  | //! @endcond  | 
9823  |  |  | 
9824  |  | /************************************************************************/  | 
9825  |  | /*                       GetCompressionFormats()                        */  | 
9826  |  | /************************************************************************/  | 
9827  |  |  | 
9828  |  | /** Return the compression formats that can be natively obtained for the  | 
9829  |  |  * window of interest and requested bands.  | 
9830  |  |  *  | 
9831  |  |  * For example, a tiled dataset may be able to return data in a compressed  | 
9832  |  |  * format if the window of interest matches exactly a tile. For some formats,  | 
9833  |  |  * drivers may also be able to merge several tiles together (not currently  | 
9834  |  |  * implemented though).  | 
9835  |  |  *  | 
9836  |  |  * Each format string is a pseudo MIME type, whose first part can be passed  | 
9837  |  |  * as the pszFormat argument of ReadCompressedData(), with additional  | 
9838  |  |  * parameters specified as key=value with a semi-colon separator.  | 
9839  |  |  *  | 
9840  |  |  * The amount and types of optional parameters passed after the MIME type is  | 
9841  |  |  * format dependent, and driver dependent (some drivers might not be able to  | 
9842  |  |  * return those extra information without doing a rather costly processing).  | 
9843  |  |  *  | 
9844  |  |  * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"  | 
9845  |  |  * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and  | 
9846  |  |  * consequently "JPEG" can be passed as the pszFormat argument of  | 
9847  |  |  * ReadCompressedData(). For JPEG, implementations can use the  | 
9848  |  |  * GDALGetCompressionFormatForJPEG() helper method to generate a string like  | 
9849  |  |  * above from a JPEG codestream.  | 
9850  |  |  *  | 
9851  |  |  * Several values might be returned. For example,  | 
9852  |  |  * the JPEGXL driver will return "JXL", but also potentially "JPEG"  | 
9853  |  |  * if the JPEGXL codestream includes a JPEG reconstruction box.  | 
9854  |  |  *  | 
9855  |  |  * In the general case this method will return an empty list.  | 
9856  |  |  *  | 
9857  |  |  * This is the same as C function GDALDatasetGetCompressionFormats().  | 
9858  |  |  *  | 
9859  |  |  * @param nXOff The pixel offset to the top left corner of the region  | 
9860  |  |  * of the band to be accessed.  This would be zero to start from the left side.  | 
9861  |  |  *  | 
9862  |  |  * @param nYOff The line offset to the top left corner of the region  | 
9863  |  |  * of the band to be accessed.  This would be zero to start from the top.  | 
9864  |  |  *  | 
9865  |  |  * @param nXSize The width of the region of the band to be accessed in pixels.  | 
9866  |  |  *  | 
9867  |  |  * @param nYSize The height of the region of the band to be accessed in lines.  | 
9868  |  |  *  | 
9869  |  |  * @param nBandCount the number of bands being requested.  | 
9870  |  |  *  | 
9871  |  |  * @param panBandList the list of nBandCount band numbers.  | 
9872  |  |  * Note band numbers are 1 based. This may be NULL to select the first  | 
9873  |  |  * nBandCount bands.  | 
9874  |  |  *  | 
9875  |  |  * @return a list of compatible formats (which may be empty)  | 
9876  |  |  *  | 
9877  |  |  * For example, to check if native compression format(s) are available on the  | 
9878  |  |  * whole image:  | 
9879  |  |  * \code{.cpp} | 
9880  |  |  *   const CPLStringList aosFormats =  | 
9881  |  |  *      poDataset->GetCompressionFormats(0, 0,  | 
9882  |  |  *                                       poDataset->GetRasterXSize(),  | 
9883  |  |  *                                       poDataset->GetRasterYSize(),  | 
9884  |  |  *                                       poDataset->GetRasterCount(),  | 
9885  |  |  *                                       nullptr);  | 
9886  |  |  *   for( const char* pszFormat: aosFormats )  | 
9887  |  |  *   { | 
9888  |  |  *      // Remove optional parameters and just print out the MIME type.  | 
9889  |  |  *      const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));  | 
9890  |  |  *      printf("Found format %s\n, aosTokens[0]); | 
9891  |  |  *   }  | 
9892  |  |  * \endcode  | 
9893  |  |  *  | 
9894  |  |  * @since GDAL 3.7  | 
9895  |  |  */  | 
9896  |  | CPLStringList  | 
9897  |  | GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,  | 
9898  |  |                                    CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,  | 
9899  |  |                                    CPL_UNUSED int nBandCount,  | 
9900  |  |                                    CPL_UNUSED const int *panBandList)  | 
9901  | 0  | { | 
9902  | 0  |     return CPLStringList();  | 
9903  | 0  | }  | 
9904  |  |  | 
9905  |  | /************************************************************************/  | 
9906  |  | /*                 GDALDatasetGetCompressionFormats()                   */  | 
9907  |  | /************************************************************************/  | 
9908  |  |  | 
9909  |  | /** Return the compression formats that can be natively obtained for the  | 
9910  |  |  * window of interest and requested bands.  | 
9911  |  |  *  | 
9912  |  |  * For example, a tiled dataset may be able to return data in a compressed  | 
9913  |  |  * format if the window of interest matches exactly a tile. For some formats,  | 
9914  |  |  * drivers may also be able to merge several tiles together (not currently  | 
9915  |  |  * implemented though).  | 
9916  |  |  *  | 
9917  |  |  * Each format string is a pseudo MIME type, whose first part can be passed  | 
9918  |  |  * as the pszFormat argument of ReadCompressedData(), with additional  | 
9919  |  |  * parameters specified as key=value with a semi-colon separator.  | 
9920  |  |  *  | 
9921  |  |  * The amount and types of optional parameters passed after the MIME type is  | 
9922  |  |  * format dependent, and driver dependent (some drivers might not be able to  | 
9923  |  |  * return those extra information without doing a rather costly processing).  | 
9924  |  |  *  | 
9925  |  |  * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"  | 
9926  |  |  * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and  | 
9927  |  |  * consequently "JPEG" can be passed as the pszFormat argument of  | 
9928  |  |  * ReadCompressedData(). For JPEG, implementations can use the  | 
9929  |  |  * GDALGetCompressionFormatForJPEG() helper method to generate a string like  | 
9930  |  |  * above from a JPEG codestream.  | 
9931  |  |  *  | 
9932  |  |  * Several values might be returned. For example,  | 
9933  |  |  * the JPEGXL driver will return "JXL", but also potentially "JPEG"  | 
9934  |  |  * if the JPEGXL codestream includes a JPEG reconstruction box.  | 
9935  |  |  *  | 
9936  |  |  * In the general case this method will return an empty list.  | 
9937  |  |  *  | 
9938  |  |  * This is the same as C++ method GDALDataset::GetCompressionFormats().  | 
9939  |  |  *  | 
9940  |  |  * @param hDS Dataset handle.  | 
9941  |  |  *  | 
9942  |  |  * @param nXOff The pixel offset to the top left corner of the region  | 
9943  |  |  * of the band to be accessed.  This would be zero to start from the left side.  | 
9944  |  |  *  | 
9945  |  |  * @param nYOff The line offset to the top left corner of the region  | 
9946  |  |  * of the band to be accessed.  This would be zero to start from the top.  | 
9947  |  |  *  | 
9948  |  |  * @param nXSize The width of the region of the band to be accessed in pixels.  | 
9949  |  |  *  | 
9950  |  |  * @param nYSize The height of the region of the band to be accessed in lines.  | 
9951  |  |  *  | 
9952  |  |  * @param nBandCount the number of bands being requested.  | 
9953  |  |  *  | 
9954  |  |  * @param panBandList the list of nBandCount band numbers.  | 
9955  |  |  * Note band numbers are 1 based. This may be NULL to select the first  | 
9956  |  |  * nBandCount bands.  | 
9957  |  |  *  | 
9958  |  |  * @return a list of compatible formats (which may be empty) that should be  | 
9959  |  |  * freed with CSLDestroy(), or nullptr.  | 
9960  |  |  *  | 
9961  |  |  * @since GDAL 3.7  | 
9962  |  |  */  | 
9963  |  | char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,  | 
9964  |  |                                         int nXSize, int nYSize, int nBandCount,  | 
9965  |  |                                         const int *panBandList)  | 
9966  | 0  | { | 
9967  | 0  |     VALIDATE_POINTER1(hDS, __func__, nullptr);  | 
9968  | 0  |     return GDALDataset::FromHandle(hDS)  | 
9969  | 0  |         ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,  | 
9970  | 0  |                                 panBandList)  | 
9971  | 0  |         .StealList();  | 
9972  | 0  | }  | 
9973  |  |  | 
9974  |  | /************************************************************************/  | 
9975  |  | /*                         ReadCompressedData()                         */  | 
9976  |  | /************************************************************************/  | 
9977  |  |  | 
9978  |  | /** Return the compressed content that can be natively obtained for the  | 
9979  |  |  * window of interest and requested bands.  | 
9980  |  |  *  | 
9981  |  |  * For example, a tiled dataset may be able to return data in compressed format  | 
9982  |  |  * if the window of interest matches exactly a tile. For some formats, drivers  | 
9983  |  |  * may also be example to merge several tiles together (not currently  | 
9984  |  |  * implemented though).  | 
9985  |  |  *  | 
9986  |  |  * The implementation should make sure that the content returned forms a valid  | 
9987  |  |  * standalone file. For example, for the GeoTIFF implementation of this method,  | 
9988  |  |  * when extracting a JPEG tile, the method will automatically add the content  | 
9989  |  |  * of the JPEG Huffman and/or quantization tables that might be stored in the  | 
9990  |  |  * TIFF JpegTables tag, and not in tile data itself.  | 
9991  |  |  *  | 
9992  |  |  * In the general case this method will return CE_Failure.  | 
9993  |  |  *  | 
9994  |  |  * This is the same as C function GDALDatasetReadCompressedData().  | 
9995  |  |  *  | 
9996  |  |  * @param pszFormat Requested compression format (e.g. "JPEG",  | 
9997  |  |  * "WEBP", "JXL"). This is the MIME type of one of the values  | 
9998  |  |  * returned by GetCompressionFormats(). The format string is designed to  | 
9999  |  |  * potentially include at a later point key=value optional parameters separated  | 
10000  |  |  * by a semi-colon character. At time of writing, none are implemented.  | 
10001  |  |  * ReadCompressedData() implementations should verify optional parameters and  | 
10002  |  |  * return CE_Failure if they cannot support one of them.  | 
10003  |  |  *  | 
10004  |  |  * @param nXOff The pixel offset to the top left corner of the region  | 
10005  |  |  * of the band to be accessed.  This would be zero to start from the left side.  | 
10006  |  |  *  | 
10007  |  |  * @param nYOff The line offset to the top left corner of the region  | 
10008  |  |  * of the band to be accessed.  This would be zero to start from the top.  | 
10009  |  |  *  | 
10010  |  |  * @param nXSize The width of the region of the band to be accessed in pixels.  | 
10011  |  |  *  | 
10012  |  |  * @param nYSize The height of the region of the band to be accessed in lines.  | 
10013  |  |  *  | 
10014  |  |  * @param nBandCount the number of bands being requested.  | 
10015  |  |  *  | 
10016  |  |  * @param panBandList the list of nBandCount band numbers.  | 
10017  |  |  * Note band numbers are 1 based. This may be NULL to select the first  | 
10018  |  |  * nBandCount bands.  | 
10019  |  |  *  | 
10020  |  |  * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.  | 
10021  |  |  * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.  | 
10022  |  |  * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided  | 
10023  |  |  * buffer will be filled with the compressed data, provided that pnBufferSize  | 
10024  |  |  * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size  | 
10025  |  |  * of *ppBuffer, is sufficiently large to hold the data.  | 
10026  |  |  * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will  | 
10027  |  |  * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to  | 
10028  |  |  * free it with VSIFree().  | 
10029  |  |  * If ppBuffer is nullptr, then the compressed data itself will not be returned,  | 
10030  |  |  * but *pnBufferSize will be updated with an upper bound of the size that would  | 
10031  |  |  * be necessary to hold it (if pnBufferSize != nullptr).  | 
10032  |  |  *  | 
10033  |  |  * @param pnBufferSize Output buffer size, or nullptr.  | 
10034  |  |  * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should  | 
10035  |  |  * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the  | 
10036  |  |  * method is successful, *pnBufferSize will be updated with the actual size  | 
10037  |  |  * used.  | 
10038  |  |  *  | 
10039  |  |  * @param ppszDetailedFormat Pointer to an output string, or nullptr.  | 
10040  |  |  * If ppszDetailedFormat is not nullptr, then, on success, the method will  | 
10041  |  |  * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())  | 
10042  |  |  * *ppszDetailedFormat might contain strings like  | 
10043  |  |  * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"  | 
10044  |  |  * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.  | 
10045  |  |  * The string will contain at least as much information as what  | 
10046  |  |  * GetCompressionFormats() returns, and potentially more when  | 
10047  |  |  * ppBuffer != nullptr.  | 
10048  |  |  *  | 
10049  |  |  * @return CE_None in case of success, CE_Failure otherwise.  | 
10050  |  |  *  | 
10051  |  |  * For example, to request JPEG content on the whole image and let GDAL deal  | 
10052  |  |  * with the buffer allocation.  | 
10053  |  |  * \code{.cpp} | 
10054  |  |  *   void* pBuffer = nullptr;  | 
10055  |  |  *   size_t nBufferSize = 0;  | 
10056  |  |  *   CPLErr eErr =  | 
10057  |  |  *      poDataset->ReadCompressedData("JPEG", | 
10058  |  |  *                                    0, 0,  | 
10059  |  |  *                                    poDataset->GetRasterXSize(),  | 
10060  |  |  *                                    poDataset->GetRasterYSize(),  | 
10061  |  |  *                                    poDataset->GetRasterCount(),  | 
10062  |  |  *                                    nullptr, // panBandList  | 
10063  |  |  *                                    &pBuffer,  | 
10064  |  |  *                                    &nBufferSize,  | 
10065  |  |  *                                    nullptr // ppszDetailedFormat  | 
10066  |  |  *                                   );  | 
10067  |  |  *   if (eErr == CE_None)  | 
10068  |  |  *   { | 
10069  |  |  *       CPLAssert(pBuffer != nullptr);  | 
10070  |  |  *       CPLAssert(nBufferSize > 0);  | 
10071  |  |  *       VSILFILE* fp = VSIFOpenL("my.jpeg", "wb"); | 
10072  |  |  *       if (fp)  | 
10073  |  |  *       { | 
10074  |  |  *           VSIFWriteL(pBuffer, nBufferSize, 1, fp);  | 
10075  |  |  *           VSIFCloseL(fp);  | 
10076  |  |  *       }  | 
10077  |  |  *       VSIFree(pBuffer);  | 
10078  |  |  *   }  | 
10079  |  |  * \endcode  | 
10080  |  |  *  | 
10081  |  |  * Or to manage the buffer allocation on your side:  | 
10082  |  |  * \code{.cpp} | 
10083  |  |  *   size_t nUpperBoundBufferSize = 0;  | 
10084  |  |  *   CPLErr eErr =  | 
10085  |  |  *      poDataset->ReadCompressedData("JPEG", | 
10086  |  |  *                                    0, 0,  | 
10087  |  |  *                                    poDataset->GetRasterXSize(),  | 
10088  |  |  *                                    poDataset->GetRasterYSize(),  | 
10089  |  |  *                                    poDataset->GetRasterCount(),  | 
10090  |  |  *                                    nullptr, // panBandList  | 
10091  |  |  *                                    nullptr, // ppBuffer,  | 
10092  |  |  *                                    &nUpperBoundBufferSize,  | 
10093  |  |  *                                    nullptr // ppszDetailedFormat  | 
10094  |  |  *                                   );  | 
10095  |  |  *   if (eErr == CE_None)  | 
10096  |  |  *   { | 
10097  |  |  *       std::vector<uint8_t> myBuffer;  | 
10098  |  |  *       myBuffer.resize(nUpperBoundBufferSize);  | 
10099  |  |  *       void* pBuffer = myBuffer.data();  | 
10100  |  |  *       size_t nActualSize = nUpperBoundBufferSize;  | 
10101  |  |  *       char* pszDetailedFormat = nullptr;  | 
10102  |  |  *       // We also request detailed format, but we could have passed it to  | 
10103  |  |  *       // nullptr as well.  | 
10104  |  |  *       eErr =  | 
10105  |  |  *         poDataset->ReadCompressedData("JPEG", | 
10106  |  |  *                                       0, 0,  | 
10107  |  |  *                                       poDataset->GetRasterXSize(),  | 
10108  |  |  *                                       poDataset->GetRasterYSize(),  | 
10109  |  |  *                                       poDataset->GetRasterCount(),  | 
10110  |  |  *                                       nullptr, // panBandList  | 
10111  |  |  *                                       &pBuffer,  | 
10112  |  |  *                                       &nActualSize,  | 
10113  |  |  *                                       &pszDetailedFormat);  | 
10114  |  |  *       if (eErr == CE_None)  | 
10115  |  |  *       { | 
10116  |  |  *          CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified  | 
10117  |  |  *          CPLAssert(nActualSize <= nUpperBoundBufferSize);  | 
10118  |  |  *          myBuffer.resize(nActualSize);  | 
10119  |  |  *          // do something useful  | 
10120  |  |  *          VSIFree(pszDetailedFormat);  | 
10121  |  |  *       }  | 
10122  |  |  *   }  | 
10123  |  |  * \endcode  | 
10124  |  |  *  | 
10125  |  |  * @since GDAL 3.7  | 
10126  |  |  */  | 
10127  |  | CPLErr GDALDataset::ReadCompressedData(  | 
10128  |  |     CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,  | 
10129  |  |     CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,  | 
10130  |  |     CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,  | 
10131  |  |     CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,  | 
10132  |  |     CPL_UNUSED char **ppszDetailedFormat)  | 
10133  | 0  | { | 
10134  | 0  |     return CE_Failure;  | 
10135  | 0  | }  | 
10136  |  |  | 
10137  |  | /************************************************************************/  | 
10138  |  | /*                  GDALDatasetReadCompressedData()                     */  | 
10139  |  | /************************************************************************/  | 
10140  |  |  | 
10141  |  | /** Return the compressed content that can be natively obtained for the  | 
10142  |  |  * window of interest and requested bands.  | 
10143  |  |  *  | 
10144  |  |  * For example, a tiled dataset may be able to return data in compressed format  | 
10145  |  |  * if the window of interest matches exactly a tile. For some formats, drivers  | 
10146  |  |  * may also be example to merge several tiles together (not currently  | 
10147  |  |  * implemented though).  | 
10148  |  |  *  | 
10149  |  |  * The implementation should make sure that the content returned forms a valid  | 
10150  |  |  * standalone file. For example, for the GeoTIFF implementation of this method,  | 
10151  |  |  * when extracting a JPEG tile, the method will automatically adds the content  | 
10152  |  |  * of the JPEG Huffman and/or quantization tables that might be stored in the  | 
10153  |  |  * TIFF JpegTables tag, and not in tile data itself.  | 
10154  |  |  *  | 
10155  |  |  * In the general case this method will return CE_Failure.  | 
10156  |  |  *  | 
10157  |  |  * This is the same as C++ method GDALDataset:ReadCompressedData().  | 
10158  |  |  *  | 
10159  |  |  * @param hDS Dataset handle.  | 
10160  |  |  *  | 
10161  |  |  * @param pszFormat Requested compression format (e.g. "JPEG",  | 
10162  |  |  * "WEBP", "JXL"). This is the MIME type of one of the values  | 
10163  |  |  * returned by GetCompressionFormats(). The format string is designed to  | 
10164  |  |  * potentially include at a later point key=value optional parameters separated  | 
10165  |  |  * by a semi-colon character. At time of writing, none are implemented.  | 
10166  |  |  * ReadCompressedData() implementations should verify optional parameters and  | 
10167  |  |  * return CE_Failure if they cannot support one of them.  | 
10168  |  |  *  | 
10169  |  |  * @param nXOff The pixel offset to the top left corner of the region  | 
10170  |  |  * of the band to be accessed.  This would be zero to start from the left side.  | 
10171  |  |  *  | 
10172  |  |  * @param nYOff The line offset to the top left corner of the region  | 
10173  |  |  * of the band to be accessed.  This would be zero to start from the top.  | 
10174  |  |  *  | 
10175  |  |  * @param nXSize The width of the region of the band to be accessed in pixels.  | 
10176  |  |  *  | 
10177  |  |  * @param nYSize The height of the region of the band to be accessed in lines.  | 
10178  |  |  *  | 
10179  |  |  * @param nBandCount the number of bands being requested.  | 
10180  |  |  *  | 
10181  |  |  * @param panBandList the list of nBandCount band numbers.  | 
10182  |  |  * Note band numbers are 1 based. This may be NULL to select the first  | 
10183  |  |  * nBandCount bands.  | 
10184  |  |  *  | 
10185  |  |  * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.  | 
10186  |  |  * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.  | 
10187  |  |  * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided  | 
10188  |  |  * buffer will be filled with the compressed data, provided that pnBufferSize  | 
10189  |  |  * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size  | 
10190  |  |  * of *ppBuffer, is sufficiently large to hold the data.  | 
10191  |  |  * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will  | 
10192  |  |  * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to  | 
10193  |  |  * free it with VSIFree().  | 
10194  |  |  * If ppBuffer is nullptr, then the compressed data itself will not be returned,  | 
10195  |  |  * but *pnBufferSize will be updated with an upper bound of the size that would  | 
10196  |  |  * be necessary to hold it (if pnBufferSize != nullptr).  | 
10197  |  |  *  | 
10198  |  |  * @param pnBufferSize Output buffer size, or nullptr.  | 
10199  |  |  * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should  | 
10200  |  |  * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the  | 
10201  |  |  * method is successful, *pnBufferSize will be updated with the actual size  | 
10202  |  |  * used.  | 
10203  |  |  *  | 
10204  |  |  * @param ppszDetailedFormat Pointer to an output string, or nullptr.  | 
10205  |  |  * If ppszDetailedFormat is not nullptr, then, on success, the method will  | 
10206  |  |  * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())  | 
10207  |  |  * *ppszDetailedFormat might contain strings like  | 
10208  |  |  * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"  | 
10209  |  |  * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.  | 
10210  |  |  * The string will contain at least as much information as what  | 
10211  |  |  * GetCompressionFormats() returns, and potentially more when  | 
10212  |  |  * ppBuffer != nullptr.  | 
10213  |  |  *  | 
10214  |  |  * @return CE_None in case of success, CE_Failure otherwise.  | 
10215  |  |  *  | 
10216  |  |  * @since GDAL 3.7  | 
10217  |  |  */  | 
10218  |  | CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,  | 
10219  |  |                                      int nXOff, int nYOff, int nXSize,  | 
10220  |  |                                      int nYSize, int nBandCount,  | 
10221  |  |                                      const int *panBandList, void **ppBuffer,  | 
10222  |  |                                      size_t *pnBufferSize,  | 
10223  |  |                                      char **ppszDetailedFormat)  | 
10224  | 0  | { | 
10225  | 0  |     VALIDATE_POINTER1(hDS, __func__, CE_Failure);  | 
10226  | 0  |     return GDALDataset::FromHandle(hDS)->ReadCompressedData(  | 
10227  | 0  |         pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,  | 
10228  | 0  |         ppBuffer, pnBufferSize, ppszDetailedFormat);  | 
10229  | 0  | }  | 
10230  |  |  | 
10231  |  | /************************************************************************/  | 
10232  |  | /*                           CanBeCloned()                              */  | 
10233  |  | /************************************************************************/  | 
10234  |  |  | 
10235  |  | //! @cond Doxygen_Suppress  | 
10236  |  |  | 
10237  |  | /** This method is called by GDALThreadSafeDataset::Create() to determine if  | 
10238  |  |  * it is possible to create a thread-safe wrapper for a dataset, which involves  | 
10239  |  |  * the ability to Clone() it.  | 
10240  |  |  *  | 
10241  |  |  * Implementations of this method must be thread-safe.  | 
10242  |  |  *  | 
10243  |  |  * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,  | 
10244  |  |  *                    expressing the intended use for thread-safety.  | 
10245  |  |  *                    Currently, the only valid scope is in the base  | 
10246  |  |  *                    implementation is GDAL_OF_RASTER.  | 
10247  |  |  * @param bCanShareState Determines if cloned datasets are allowed to share  | 
10248  |  |  *                       state with the dataset they have been cloned from.  | 
10249  |  |  *                       If set to true, the dataset from which they have been  | 
10250  |  |  *                       cloned from must remain opened during the lifetime of  | 
10251  |  |  *                       its clones.  | 
10252  |  |  * @return true if the Clone() method is expected to succeed with the same values  | 
10253  |  |  *         of nScopeFlags and bCanShareState.  | 
10254  |  |  */  | 
10255  |  | bool GDALDataset::CanBeCloned(int nScopeFlags,  | 
10256  |  |                               [[maybe_unused]] bool bCanShareState) const  | 
10257  | 0  | { | 
10258  | 0  |     return m_bCanBeReopened && nScopeFlags == GDAL_OF_RASTER;  | 
10259  | 0  | }  | 
10260  |  |  | 
10261  |  | //! @endcond  | 
10262  |  |  | 
10263  |  | /************************************************************************/  | 
10264  |  | /*                               Clone()                                */  | 
10265  |  | /************************************************************************/  | 
10266  |  |  | 
10267  |  | //! @cond Doxygen_Suppress  | 
10268  |  |  | 
10269  |  | /** This method "clones" the current dataset, that is it returns a new instance  | 
10270  |  |  * that is opened on the same underlying "file".  | 
10271  |  |  *  | 
10272  |  |  * The base implementation uses GDALDataset::Open() to re-open the dataset.  | 
10273  |  |  * The MEM driver has a specialized implementation that returns a new instance,  | 
10274  |  |  * but which shares the same memory buffer as this.  | 
10275  |  |  *  | 
10276  |  |  * Implementations of this method must be thread-safe.  | 
10277  |  |  *  | 
10278  |  |  * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,  | 
10279  |  |  *                    expressing the intended use for thread-safety.  | 
10280  |  |  *                    Currently, the only valid scope is in the base  | 
10281  |  |  *                    implementation is GDAL_OF_RASTER.  | 
10282  |  |  * @param bCanShareState Determines if cloned datasets are allowed to share  | 
10283  |  |  *                       state with the dataset they have been cloned from.  | 
10284  |  |  *                       If set to true, the dataset from which they have been  | 
10285  |  |  *                       cloned from must remain opened during the lifetime of  | 
10286  |  |  *                       its clones.  | 
10287  |  |  * @return a new instance, or nullptr in case of error.  | 
10288  |  |  */  | 
10289  |  | std::unique_ptr<GDALDataset>  | 
10290  |  | GDALDataset::Clone(int nScopeFlags, [[maybe_unused]] bool bCanShareState) const  | 
10291  | 0  | { | 
10292  | 0  |     CPLStringList aosAllowedDrivers;  | 
10293  | 0  |     if (poDriver)  | 
10294  | 0  |         aosAllowedDrivers.AddString(poDriver->GetDescription());  | 
10295  | 0  |     return std::unique_ptr<GDALDataset>(GDALDataset::Open(  | 
10296  | 0  |         GetDescription(),  | 
10297  | 0  |         nScopeFlags | GDAL_OF_INTERNAL | GDAL_OF_VERBOSE_ERROR,  | 
10298  | 0  |         aosAllowedDrivers.List(), papszOpenOptions));  | 
10299  | 0  | }  | 
10300  |  |  | 
10301  |  | //! @endcond  | 
10302  |  |  | 
10303  |  | /************************************************************************/  | 
10304  |  | /*                    GeolocationToPixelLine()                          */  | 
10305  |  | /************************************************************************/  | 
10306  |  |  | 
10307  |  | /** Transform georeferenced coordinates to pixel/line coordinates.  | 
10308  |  |  *  | 
10309  |  |  * When poSRS is null, those georeferenced coordinates (dfGeolocX, dfGeolocY)  | 
10310  |  |  * must be in the "natural" SRS of the dataset, that is the one returned by  | 
10311  |  |  * GetSpatialRef() if there is a geotransform, GetGCPSpatialRef() if there are  | 
10312  |  |  * GCPs, WGS 84 if there are RPC coefficients, or the SRS of the geolocation  | 
10313  |  |  * array (generally WGS 84) if there is a geolocation array.  | 
10314  |  |  * If that natural SRS is a geographic one, dfGeolocX must be a longitude, and  | 
10315  |  |  * dfGeolocY a latitude. If that natural SRS is a projected one, dfGeolocX must  | 
10316  |  |  * be a easting, and dfGeolocY a northing.  | 
10317  |  |  *  | 
10318  |  |  * When poSRS is set to a non-null value, (dfGeolocX, dfGeolocY) must be  | 
10319  |  |  * expressed in that CRS, and that tuple must be conformant with the  | 
10320  |  |  * data-axis-to-crs-axis setting of poSRS, that is the one returned by  | 
10321  |  |  * the OGRSpatialReference::GetDataAxisToSRSAxisMapping(). If you want to be sure  | 
10322  |  |  * of the axis order, then make sure to call poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER)  | 
10323  |  |  * before calling this method, and in that case, dfGeolocX must be a longitude  | 
10324  |  |  * or an easting value, and dfGeolocX a latitude or a northing value.  | 
10325  |  |  *  | 
10326  |  |  * This method uses GDALCreateGenImgProjTransformer2() underneath.  | 
10327  |  |  *  | 
10328  |  |  * @param dfGeolocX X coordinate of the position (longitude or easting if poSRS  | 
10329  |  |  * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),  | 
10330  |  |  * where interpolation should be done.  | 
10331  |  |  * @param dfGeolocY Y coordinate of the position (latitude or northing if poSRS  | 
10332  |  |  * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),  | 
10333  |  |  * where interpolation should be done.  | 
10334  |  |  * @param poSRS If set, override the natural CRS in which dfGeolocX, dfGeolocY are expressed  | 
10335  |  |  * @param[out] pdfPixel Pointer to the variable where to the store the pixel/column coordinate.  | 
10336  |  |  * @param[out] pdfLine Pointer to the variable where to the store the line coordinate.  | 
10337  |  |  * @param papszTransformerOptions Options accepted by GDALCreateGenImgProjTransformer2(), or nullptr.  | 
10338  |  |  *  | 
10339  |  |  * @return CE_None on success, or an error code on failure.  | 
10340  |  |  * @since GDAL 3.11  | 
10341  |  |  */  | 
10342  |  |  | 
10343  |  | CPLErr  | 
10344  |  | GDALDataset::GeolocationToPixelLine(double dfGeolocX, double dfGeolocY,  | 
10345  |  |                                     const OGRSpatialReference *poSRS,  | 
10346  |  |                                     double *pdfPixel, double *pdfLine,  | 
10347  |  |                                     CSLConstList papszTransformerOptions) const  | 
10348  | 0  | { | 
10349  | 0  |     CPLStringList aosTO(papszTransformerOptions);  | 
10350  |  | 
  | 
10351  | 0  |     if (poSRS)  | 
10352  | 0  |     { | 
10353  | 0  |         const char *const apszOptions[] = {"FORMAT=WKT2", nullptr}; | 
10354  | 0  |         const std::string osWKT = poSRS->exportToWkt(apszOptions);  | 
10355  | 0  |         aosTO.SetNameValue("DST_SRS", osWKT.c_str()); | 
10356  | 0  |         const auto eAxisMappingStrategy = poSRS->GetAxisMappingStrategy();  | 
10357  | 0  |         if (eAxisMappingStrategy == OAMS_TRADITIONAL_GIS_ORDER)  | 
10358  | 0  |             aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY", | 
10359  | 0  |                                "TRADITIONAL_GIS_ORDER");  | 
10360  | 0  |         else if (eAxisMappingStrategy == OAMS_AUTHORITY_COMPLIANT)  | 
10361  | 0  |             aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY", | 
10362  | 0  |                                "AUTHORITY_COMPLIANT");  | 
10363  | 0  |         else  | 
10364  | 0  |         { | 
10365  | 0  |             const auto &anValues = poSRS->GetDataAxisToSRSAxisMapping();  | 
10366  | 0  |             std::string osVal;  | 
10367  | 0  |             for (int v : anValues)  | 
10368  | 0  |             { | 
10369  | 0  |                 if (!osVal.empty())  | 
10370  | 0  |                     osVal += ',';  | 
10371  | 0  |                 osVal += std::to_string(v);  | 
10372  | 0  |             }  | 
10373  | 0  |             aosTO.SetNameValue("DST_SRS_DATA_AXIS_TO_SRS_AXIS_MAPPING", | 
10374  | 0  |                                osVal.c_str());  | 
10375  | 0  |         }  | 
10376  | 0  |     }  | 
10377  |  | 
  | 
10378  | 0  |     auto hTransformer = GDALCreateGenImgProjTransformer2(  | 
10379  | 0  |         GDALDataset::ToHandle(const_cast<GDALDataset *>(this)), nullptr,  | 
10380  | 0  |         aosTO.List());  | 
10381  | 0  |     if (hTransformer == nullptr)  | 
10382  | 0  |     { | 
10383  | 0  |         return CE_Failure;  | 
10384  | 0  |     }  | 
10385  |  |  | 
10386  | 0  |     double z = 0;  | 
10387  | 0  |     int bSuccess = 0;  | 
10388  | 0  |     GDALGenImgProjTransform(hTransformer, TRUE, 1, &dfGeolocX, &dfGeolocY, &z,  | 
10389  | 0  |                             &bSuccess);  | 
10390  | 0  |     GDALDestroyTransformer(hTransformer);  | 
10391  | 0  |     if (bSuccess)  | 
10392  | 0  |     { | 
10393  | 0  |         if (pdfPixel)  | 
10394  | 0  |             *pdfPixel = dfGeolocX;  | 
10395  | 0  |         if (pdfLine)  | 
10396  | 0  |             *pdfLine = dfGeolocY;  | 
10397  | 0  |         return CE_None;  | 
10398  | 0  |     }  | 
10399  | 0  |     else  | 
10400  | 0  |     { | 
10401  | 0  |         return CE_Failure;  | 
10402  | 0  |     }  | 
10403  | 0  | }  | 
10404  |  |  | 
10405  |  | /************************************************************************/  | 
10406  |  | /*                  GDALDatasetGeolocationToPixelLine()                 */  | 
10407  |  | /************************************************************************/  | 
10408  |  |  | 
10409  |  | /** Transform georeferenced coordinates to pixel/line coordinates.  | 
10410  |  |  *  | 
10411  |  |  * @see GDALDataset::GeolocationToPixelLine()  | 
10412  |  |  * @since GDAL 3.11  | 
10413  |  |  */  | 
10414  |  |  | 
10415  |  | CPLErr GDALDatasetGeolocationToPixelLine(GDALDatasetH hDS, double dfGeolocX,  | 
10416  |  |                                          double dfGeolocY,  | 
10417  |  |                                          OGRSpatialReferenceH hSRS,  | 
10418  |  |                                          double *pdfPixel, double *pdfLine,  | 
10419  |  |                                          CSLConstList papszTransformerOptions)  | 
10420  | 0  | { | 
10421  | 0  |     VALIDATE_POINTER1(hDS, "GDALDatasetGeolocationToPixelLine", CE_Failure);  | 
10422  |  |  | 
10423  | 0  |     GDALDataset *poDS = GDALDataset::FromHandle(hDS);  | 
10424  | 0  |     return poDS->GeolocationToPixelLine(  | 
10425  | 0  |         dfGeolocX, dfGeolocY, OGRSpatialReference::FromHandle(hSRS), pdfPixel,  | 
10426  | 0  |         pdfLine, papszTransformerOptions);  | 
10427  | 0  | }  | 
10428  |  |  | 
10429  |  | /************************************************************************/  | 
10430  |  | /*                  ReportUpdateNotSupportedByDriver()                  */  | 
10431  |  | /************************************************************************/  | 
10432  |  |  | 
10433  |  | //! @cond Doxygen_Suppress  | 
10434  |  |  | 
10435  |  | /* static */  | 
10436  |  | void GDALDataset::ReportUpdateNotSupportedByDriver(const char *pszDriverName)  | 
10437  | 0  | { | 
10438  | 0  |     CPLError(CE_Failure, CPLE_NotSupported,  | 
10439  | 0  |              "The %s driver does not support update access to existing "  | 
10440  | 0  |              "datasets.",  | 
10441  | 0  |              pszDriverName);  | 
10442  | 0  | }  | 
10443  |  |  | 
10444  |  | //! @endcond  | 
10445  |  |  | 
10446  |  | /************************************************************************/  | 
10447  |  | /*                         BuildFilename()                              */  | 
10448  |  | /************************************************************************/  | 
10449  |  |  | 
10450  |  | /** Generates a filename, potentially relative to another one.  | 
10451  |  |  *  | 
10452  |  |  * Given the path to a reference directory, and a path to a file  | 
10453  |  |  * referenced from it, build a path to the file that the current application  | 
10454  |  |  * can use. If the file path is already absolute, rather than relative, or if  | 
10455  |  |  * bRelativeToReferencePath is false, then the filename of interest will be  | 
10456  |  |  * returned unaltered.  | 
10457  |  |  *  | 
10458  |  |  * This is enhanced version of CPLProjectRelativeFilenameSafe() that takes  | 
10459  |  |  * into account the subdataset syntax.  | 
10460  |  |  *  | 
10461  |  |  * Examples:  | 
10462  |  |  * \code{.cpp} | 
10463  |  |  * BuildFilename("tmp/abc.gif", "abc/def", true) == "abc/def/tmp/abc.gif" | 
10464  |  |  * BuildFilename("../abc.gif", "/abc/def") == "/abc/abc.gif" | 
10465  |  |  * BuildFilename("abc.gif", "C:\WIN", true) == "C:\WIN\abc.gif" | 
10466  |  |  * BuildFilename("abc.gif", "C:\WIN", false) == "abc.gif" | 
10467  |  |  * BuildFilename("/home/even/foo.tif", "/home/even/workdir", true) == "/home/even/foo.tif" | 
10468  |  |  * \endcode  | 
10469  |  |  *  | 
10470  |  |  * @param pszFilename Filename of interest.  | 
10471  |  |  * @param pszReferencePath Path to a reference directory.  | 
10472  |  |  * @param bRelativeToReferencePath Whether pszFilename, if a relative path, is  | 
10473  |  |  *                                 relative to pszReferencePath  | 
10474  |  |  * @since 3.11  | 
10475  |  |  */  | 
10476  |  |  | 
10477  |  | /* static */  | 
10478  |  | std::string GDALDataset::BuildFilename(const char *pszFilename,  | 
10479  |  |                                        const char *pszReferencePath,  | 
10480  |  |                                        bool bRelativeToReferencePath)  | 
10481  | 0  | { | 
10482  | 0  |     std::string osSrcDSName;  | 
10483  | 0  |     if (pszReferencePath != nullptr && bRelativeToReferencePath)  | 
10484  | 0  |     { | 
10485  |  |         // Try subdatasetinfo API first  | 
10486  |  |         // Note: this will become the only branch when subdatasetinfo will become  | 
10487  |  |         //       available for NITF_IM, RASTERLITE and TILEDB  | 
10488  | 0  |         const auto oSubDSInfo{GDALGetSubdatasetInfo(pszFilename)}; | 
10489  | 0  |         if (oSubDSInfo && !oSubDSInfo->GetPathComponent().empty())  | 
10490  | 0  |         { | 
10491  | 0  |             auto path{oSubDSInfo->GetPathComponent()}; | 
10492  | 0  |             osSrcDSName = oSubDSInfo->ModifyPathComponent(  | 
10493  | 0  |                 CPLProjectRelativeFilenameSafe(pszReferencePath, path.c_str())  | 
10494  | 0  |                     .c_str());  | 
10495  | 0  |             GDALDestroySubdatasetInfo(oSubDSInfo);  | 
10496  | 0  |         }  | 
10497  | 0  |         else  | 
10498  | 0  |         { | 
10499  | 0  |             bool bDone = false;  | 
10500  | 0  |             for (const char *pszSyntax : apszSpecialSubDatasetSyntax)  | 
10501  | 0  |             { | 
10502  | 0  |                 CPLString osPrefix(pszSyntax);  | 
10503  | 0  |                 osPrefix.resize(strchr(pszSyntax, ':') - pszSyntax + 1);  | 
10504  | 0  |                 if (pszSyntax[osPrefix.size()] == '"')  | 
10505  | 0  |                     osPrefix += '"';  | 
10506  | 0  |                 if (EQUALN(pszFilename, osPrefix, osPrefix.size()))  | 
10507  | 0  |                 { | 
10508  | 0  |                     if (STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}")) | 
10509  | 0  |                     { | 
10510  | 0  |                         const char *pszLastPart = strrchr(pszFilename, ':') + 1;  | 
10511  |  |                         // CSV:z:/foo.xyz  | 
10512  | 0  |                         if ((pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&  | 
10513  | 0  |                             pszLastPart - pszFilename >= 3 &&  | 
10514  | 0  |                             pszLastPart[-3] == ':')  | 
10515  | 0  |                         { | 
10516  | 0  |                             pszLastPart -= 2;  | 
10517  | 0  |                         }  | 
10518  | 0  |                         CPLString osPrefixFilename = pszFilename;  | 
10519  | 0  |                         osPrefixFilename.resize(pszLastPart - pszFilename);  | 
10520  | 0  |                         osSrcDSName = osPrefixFilename +  | 
10521  | 0  |                                       CPLProjectRelativeFilenameSafe(  | 
10522  | 0  |                                           pszReferencePath, pszLastPart);  | 
10523  | 0  |                         bDone = true;  | 
10524  | 0  |                     }  | 
10525  | 0  |                     else if (STARTS_WITH_CI(pszSyntax + osPrefix.size(),  | 
10526  | 0  |                                             "{FILENAME}")) | 
10527  | 0  |                     { | 
10528  | 0  |                         CPLString osFilename(pszFilename + osPrefix.size());  | 
10529  | 0  |                         size_t nPos = 0;  | 
10530  | 0  |                         if (osFilename.size() >= 3 && osFilename[1] == ':' &&  | 
10531  | 0  |                             (osFilename[2] == '\\' || osFilename[2] == '/'))  | 
10532  | 0  |                             nPos = 2;  | 
10533  | 0  |                         nPos = osFilename.find(  | 
10534  | 0  |                             pszSyntax[osPrefix.size() + strlen("{FILENAME}")], | 
10535  | 0  |                             nPos);  | 
10536  | 0  |                         if (nPos != std::string::npos)  | 
10537  | 0  |                         { | 
10538  | 0  |                             const CPLString osSuffix = osFilename.substr(nPos);  | 
10539  | 0  |                             osFilename.resize(nPos);  | 
10540  | 0  |                             osSrcDSName = osPrefix +  | 
10541  | 0  |                                           CPLProjectRelativeFilenameSafe(  | 
10542  | 0  |                                               pszReferencePath, osFilename) +  | 
10543  | 0  |                                           osSuffix;  | 
10544  | 0  |                             bDone = true;  | 
10545  | 0  |                         }  | 
10546  | 0  |                     }  | 
10547  | 0  |                     break;  | 
10548  | 0  |                 }  | 
10549  | 0  |             }  | 
10550  | 0  |             if (!bDone)  | 
10551  | 0  |             { | 
10552  | 0  |                 std::string osReferencePath = pszReferencePath;  | 
10553  | 0  |                 if (!CPLIsFilenameRelative(pszReferencePath))  | 
10554  | 0  |                 { | 
10555  |  |                     // Simplify path by replacing "foo/a/../b" with "foo/b"  | 
10556  | 0  |                     while (STARTS_WITH(pszFilename, "../"))  | 
10557  | 0  |                     { | 
10558  | 0  |                         osReferencePath =  | 
10559  | 0  |                             CPLGetPathSafe(osReferencePath.c_str());  | 
10560  | 0  |                         pszFilename += strlen("../"); | 
10561  | 0  |                     }  | 
10562  | 0  |                 }  | 
10563  |  | 
  | 
10564  | 0  |                 osSrcDSName = CPLProjectRelativeFilenameSafe(  | 
10565  | 0  |                     osReferencePath.c_str(), pszFilename);  | 
10566  | 0  |             }  | 
10567  | 0  |         }  | 
10568  | 0  |     }  | 
10569  | 0  |     else  | 
10570  | 0  |     { | 
10571  | 0  |         osSrcDSName = pszFilename;  | 
10572  | 0  |     }  | 
10573  | 0  |     return osSrcDSName;  | 
10574  | 0  | }  |