1 /******************************************************************************
2  *
3  * Project:  Virtual GDAL Datasets
4  * Purpose:  Implementation of VRTDataset
5  * Author:   Frank Warmerdam <warmerdam@pobox.com>
6  *
7  ******************************************************************************
8  * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.com>
9  * Copyright (c) 2007-2014, Even Rouault <even dot rouault at spatialys.com>
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  ****************************************************************************/
29 
30 #include "vrtdataset.h"
31 
32 #include "cpl_minixml.h"
33 #include "cpl_string.h"
34 #include "gdal_frmts.h"
35 #include "ogr_spatialref.h"
36 #include "gdal_utils.h"
37 
38 #include <algorithm>
39 #include <typeinfo>
40 #include "gdal_proxy.h"
41 
42 /*! @cond Doxygen_Suppress */
43 
44 CPL_CVSID("$Id: vrtdataset.cpp 9c76f54836aeca57bc60bfd7ef7f75664317bb15 2020-11-13 17:04:02 +0100 Even Rouault $")
45 
46 #define VRT_PROTOCOL_PREFIX "vrt://"
47 
48 /************************************************************************/
49 /*                            VRTDataset()                             */
50 /************************************************************************/
51 
VRTDataset(int nXSize,int nYSize)52 VRTDataset::VRTDataset( int nXSize, int nYSize )
53 {
54     nRasterXSize = nXSize;
55     nRasterYSize = nYSize;
56 
57     m_adfGeoTransform[0] = 0.0;
58     m_adfGeoTransform[1] = 1.0;
59     m_adfGeoTransform[2] = 0.0;
60     m_adfGeoTransform[3] = 0.0;
61     m_adfGeoTransform[4] = 0.0;
62     m_adfGeoTransform[5] = 1.0;
63 
64     GDALRegister_VRT();
65 
66     poDriver = static_cast<GDALDriver *>( GDALGetDriverByName( "VRT" ) );
67 }
68 
69 /*! @endcond */
70 
71 /************************************************************************/
72 /*                              VRTCreate()                             */
73 /************************************************************************/
74 
75 /**
76  * @see VRTDataset::VRTDataset()
77  */
78 
VRTCreate(int nXSize,int nYSize)79 VRTDatasetH CPL_STDCALL VRTCreate(int nXSize, int nYSize)
80 
81 {
82     auto poDS = new VRTDataset(nXSize, nYSize);
83     poDS->eAccess = GA_Update;
84     return poDS;
85 }
86 
87 /*! @cond Doxygen_Suppress */
88 
89 /************************************************************************/
90 /*                            ~VRTDataset()                            */
91 /************************************************************************/
92 
~VRTDataset()93 VRTDataset::~VRTDataset()
94 
95 {
96     VRTDataset::FlushCache();
97     if( m_poSRS )
98         m_poSRS->Release();
99     if( m_poGCP_SRS )
100         m_poGCP_SRS->Release();
101     if( m_nGCPCount > 0 )
102     {
103         GDALDeinitGCPs( m_nGCPCount, m_pasGCPList );
104         CPLFree( m_pasGCPList );
105     }
106     CPLFree( m_pszVRTPath );
107 
108     delete m_poMaskBand;
109 
110     for(size_t i=0;i<m_apoOverviews.size();i++)
111         delete m_apoOverviews[i];
112     for(size_t i=0;i<m_apoOverviewsBak.size();i++)
113         delete m_apoOverviewsBak[i];
114     CSLDestroy( m_papszXMLVRTMetadata );
115 }
116 
117 /************************************************************************/
118 /*                             FlushCache()                             */
119 /************************************************************************/
120 
FlushCache()121 void VRTDataset::FlushCache()
122 
123 {
124     if( m_poRootGroup )
125         m_poRootGroup->Serialize();
126     else
127         VRTFlushCacheStruct<VRTDataset>::FlushCache(*this);
128 }
129 
130 /************************************************************************/
131 /*                             FlushCache()                             */
132 /************************************************************************/
133 
FlushCache()134 void VRTWarpedDataset::FlushCache()
135 
136 {
137     VRTFlushCacheStruct<VRTWarpedDataset>::FlushCache(*this);
138 }
139 
140 /************************************************************************/
141 /*                             FlushCache()                             */
142 /************************************************************************/
143 
FlushCache()144 void VRTPansharpenedDataset::FlushCache()
145 
146 {
147     VRTFlushCacheStruct<VRTPansharpenedDataset>::FlushCache(*this);
148 }
149 
150 /************************************************************************/
151 /*                             FlushCache()                             */
152 /************************************************************************/
153 
FlushCache(T & obj)154 template<class T> void VRTFlushCacheStruct<T>::FlushCache(T& obj)
155 {
156     obj.GDALDataset::FlushCache();
157 
158     if( !obj.m_bNeedsFlush || !obj.m_bWritable )
159         return;
160 
161     obj.m_bNeedsFlush = false;
162 
163     // We don't write to disk if there is no filename.  This is a
164     // memory only dataset.
165     if( strlen(obj.GetDescription()) == 0
166         || STARTS_WITH_CI(obj.GetDescription(), "<VRTDataset") )
167         return;
168 
169     /* -------------------------------------------------------------------- */
170     /*      Create the output file.                                         */
171     /* -------------------------------------------------------------------- */
172     VSILFILE *fpVRT = VSIFOpenL( obj.GetDescription(), "w" );
173     if( fpVRT == nullptr )
174     {
175         CPLError( CE_Failure, CPLE_AppDefined,
176                 "Failed to write .vrt file in FlushCache()." );
177         return;
178     }
179 
180     /* -------------------------------------------------------------------- */
181     /*      Convert tree to a single block of XML text.                     */
182     /* -------------------------------------------------------------------- */
183     const char* pszDescription = obj.GetDescription();
184     char *l_pszVRTPath = CPLStrdup(
185         pszDescription[0] && !STARTS_WITH(pszDescription, "<VRTDataset") ?
186             CPLGetPath(pszDescription): "" );
187     CPLXMLNode *psDSTree = obj.T::SerializeToXML( l_pszVRTPath );
188     char *pszXML = CPLSerializeXMLTree( psDSTree );
189 
190     CPLDestroyXMLNode( psDSTree );
191 
192     CPLFree( l_pszVRTPath );
193     bool bOK = true;
194     if( pszXML )
195     {
196         /* ------------------------------------------------------------------ */
197         /*      Write to disk.                                                */
198         /* ------------------------------------------------------------------ */
199         bOK &=
200             VSIFWriteL( pszXML, 1, strlen(pszXML), fpVRT )
201             == strlen(pszXML);
202         CPLFree(pszXML);
203     }
204     if( VSIFCloseL( fpVRT ) != 0 )
205         bOK = false;
206     if( !bOK )
207     {
208         CPLError( CE_Failure, CPLE_AppDefined,
209                 "Failed to write .vrt file in FlushCache()." );
210         return;
211     }
212 }
213 
214 /************************************************************************/
215 /*                            GetMetadata()                             */
216 /************************************************************************/
217 
GetMetadata(const char * pszDomain)218 char** VRTDataset::GetMetadata( const char *pszDomain )
219 {
220     if( pszDomain != nullptr && EQUAL(pszDomain, "xml:VRT") )
221     {
222         /* ------------------------------------------------------------------ */
223         /*      Convert tree to a single block of XML text.                   */
224         /* ------------------------------------------------------------------ */
225         const char* pszDescription = GetDescription();
226         char *l_pszVRTPath = CPLStrdup(
227             pszDescription[0] && !STARTS_WITH(pszDescription, "<VRTDataset") ?
228                 CPLGetPath(pszDescription): "" );
229         CPLXMLNode *psDSTree = SerializeToXML( l_pszVRTPath );
230         char *pszXML = CPLSerializeXMLTree( psDSTree );
231 
232         CPLDestroyXMLNode( psDSTree );
233 
234         CPLFree( l_pszVRTPath );
235 
236         CSLDestroy(m_papszXMLVRTMetadata);
237         m_papszXMLVRTMetadata = static_cast<char**>(CPLMalloc(2 * sizeof(char*)));
238         m_papszXMLVRTMetadata[0] = pszXML;
239         m_papszXMLVRTMetadata[1] = nullptr;
240         return m_papszXMLVRTMetadata;
241     }
242 
243     return GDALDataset::GetMetadata(pszDomain);
244 }
245 
246 /*! @endcond */
247 
248 /************************************************************************/
249 /*                            VRTFlushCache()                           */
250 /************************************************************************/
251 
252 /**
253  * @see VRTDataset::FlushCache()
254  */
255 
VRTFlushCache(VRTDatasetH hDataset)256 void CPL_STDCALL VRTFlushCache( VRTDatasetH hDataset )
257 {
258     VALIDATE_POINTER0( hDataset, "VRTFlushCache" );
259 
260     static_cast<VRTDataset *>(GDALDataset::FromHandle(hDataset))->FlushCache();
261 }
262 
263 /*! @cond Doxygen_Suppress */
264 
265 /************************************************************************/
266 /*                           SerializeToXML()                           */
267 /************************************************************************/
268 
SerializeToXML(const char * pszVRTPathIn)269 CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPathIn )
270 
271 {
272     if( m_poRootGroup )
273         return m_poRootGroup->SerializeToXML(pszVRTPathIn);
274 
275     /* -------------------------------------------------------------------- */
276     /*      Setup root node and attributes.                                 */
277     /* -------------------------------------------------------------------- */
278     CPLXMLNode *psDSTree = CPLCreateXMLNode( nullptr, CXT_Element, "VRTDataset" );
279 
280     char szNumber[128] = { '\0' };
281     snprintf( szNumber, sizeof(szNumber), "%d", GetRasterXSize() );
282     CPLSetXMLValue( psDSTree, "#rasterXSize", szNumber );
283 
284     snprintf( szNumber, sizeof(szNumber), "%d", GetRasterYSize() );
285     CPLSetXMLValue( psDSTree, "#rasterYSize", szNumber );
286 
287  /* -------------------------------------------------------------------- */
288  /*      SRS                                                             */
289  /* -------------------------------------------------------------------- */
290     if( m_poSRS && !m_poSRS->IsEmpty() )
291     {
292         char* pszWKT = nullptr;
293         m_poSRS->exportToWkt(&pszWKT);
294         CPLXMLNode* psSRSNode = CPLCreateXMLElementAndValue( psDSTree, "SRS", pszWKT );
295         CPLFree(pszWKT);
296         const auto& mapping = m_poSRS->GetDataAxisToSRSAxisMapping();
297         CPLString osMapping;
298         for( size_t i = 0; i < mapping.size(); ++i )
299         {
300             if( !osMapping.empty() )
301                 osMapping += ",";
302             osMapping += CPLSPrintf("%d", mapping[i]);
303         }
304         CPLAddXMLAttributeAndValue(psSRSNode, "dataAxisToSRSAxisMapping",
305                                    osMapping.c_str());
306     }
307 
308  /* -------------------------------------------------------------------- */
309  /*      Geotransform.                                                   */
310  /* -------------------------------------------------------------------- */
311     if( m_bGeoTransformSet )
312     {
313         CPLSetXMLValue(
314             psDSTree, "GeoTransform",
315             CPLSPrintf( "%24.16e,%24.16e,%24.16e,%24.16e,%24.16e,%24.16e",
316                         m_adfGeoTransform[0],
317                         m_adfGeoTransform[1],
318                         m_adfGeoTransform[2],
319                         m_adfGeoTransform[3],
320                         m_adfGeoTransform[4],
321                         m_adfGeoTransform[5] ) );
322     }
323 
324 /* -------------------------------------------------------------------- */
325 /*      Metadata                                                        */
326 /* -------------------------------------------------------------------- */
327     CPLXMLNode *psMD = oMDMD.Serialize();
328     if( psMD != nullptr )
329     {
330         CPLAddXMLChild( psDSTree, psMD );
331     }
332 
333  /* -------------------------------------------------------------------- */
334  /*      GCPs                                                            */
335  /* -------------------------------------------------------------------- */
336     if( m_nGCPCount > 0 )
337     {
338         GDALSerializeGCPListToXML( psDSTree,
339                                    m_pasGCPList,
340                                    m_nGCPCount,
341                                    m_poGCP_SRS );
342     }
343 
344     /* -------------------------------------------------------------------- */
345     /*      Serialize bands.                                                */
346     /* -------------------------------------------------------------------- */
347     CPLXMLNode* psLastChild = psDSTree->psChild;
348     for( ; psLastChild != nullptr && psLastChild->psNext;
349                                     psLastChild = psLastChild->psNext )
350     {
351     }
352     CPLAssert(psLastChild); // we have at least rasterXSize
353     for( int iBand = 0; iBand < nBands; iBand++ )
354     {
355         CPLXMLNode *psBandTree =
356             static_cast<VRTRasterBand *>(
357                 papoBands[iBand])->SerializeToXML( pszVRTPathIn );
358 
359         if( psBandTree != nullptr )
360         {
361             psLastChild->psNext = psBandTree;
362             psLastChild = psBandTree;
363         }
364     }
365 
366     /* -------------------------------------------------------------------- */
367     /*      Serialize dataset mask band.                                    */
368     /* -------------------------------------------------------------------- */
369     if( m_poMaskBand )
370     {
371         CPLXMLNode *psBandTree =
372             m_poMaskBand->SerializeToXML(pszVRTPathIn);
373 
374         if( psBandTree != nullptr )
375         {
376             CPLXMLNode *psMaskBandElement
377                 = CPLCreateXMLNode( psDSTree, CXT_Element, "MaskBand" );
378             CPLAddXMLChild( psMaskBandElement, psBandTree );
379         }
380     }
381 
382     /* -------------------------------------------------------------------- */
383     /*      Overview factors.                                               */
384     /* -------------------------------------------------------------------- */
385     if( !m_anOverviewFactors.empty() )
386     {
387         CPLString osOverviewList;
388         for( int nOvFactor: m_anOverviewFactors )
389         {
390             if( !osOverviewList.empty() )
391                 osOverviewList += " ";
392             osOverviewList += CPLSPrintf("%d", nOvFactor);
393         }
394         CPLXMLNode* psOverviewList = CPLCreateXMLElementAndValue(
395             psDSTree, "OverviewList", osOverviewList);
396         if( !m_osOverviewResampling.empty() )
397         {
398             CPLAddXMLAttributeAndValue( psOverviewList,
399                                         "resampling",
400                                         m_osOverviewResampling );
401         }
402     }
403 
404     return psDSTree;
405 }
406 
407 /*! @endcond */
408 /************************************************************************/
409 /*                          VRTSerializeToXML()                         */
410 /************************************************************************/
411 
412 /**
413  * @see VRTDataset::SerializeToXML()
414  */
415 
VRTSerializeToXML(VRTDatasetH hDataset,const char * pszVRTPath)416 CPLXMLNode * CPL_STDCALL VRTSerializeToXML( VRTDatasetH hDataset,
417                                             const char *pszVRTPath )
418 {
419     VALIDATE_POINTER1( hDataset, "VRTSerializeToXML", nullptr );
420 
421     return static_cast<VRTDataset *>(GDALDataset::FromHandle(
422         hDataset))->SerializeToXML(pszVRTPath);
423 }
424 /*! @cond Doxygen_Suppress */
425 
426 
427 /************************************************************************/
428 /*                             InitBand()                               */
429 /************************************************************************/
430 
InitBand(const char * pszSubclass,int nBand,bool bAllowPansharpened)431 VRTRasterBand* VRTDataset::InitBand(const char* pszSubclass, int nBand,
432                                     bool bAllowPansharpened)
433 {
434     VRTRasterBand  *poBand = nullptr;
435     if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
436         poBand = new VRTSourcedRasterBand( this, nBand );
437     else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
438         poBand = new VRTDerivedRasterBand( this, nBand );
439     else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
440         poBand = new VRTRawRasterBand( this, nBand );
441     else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") &&
442                 dynamic_cast<VRTWarpedDataset*>(this) != nullptr )
443         poBand = new VRTWarpedRasterBand( this, nBand );
444     else if( bAllowPansharpened &&
445              EQUAL(pszSubclass, "VRTPansharpenedRasterBand") &&
446                 dynamic_cast<VRTPansharpenedDataset*>(this) != nullptr )
447         poBand = new VRTPansharpenedRasterBand( this, nBand);
448     else
449         CPLError( CE_Failure, CPLE_AppDefined,
450                     "VRTRasterBand of unrecognized subclass '%s'.",
451                     pszSubclass );
452     return poBand;
453 }
454 
455 /************************************************************************/
456 /*                              XMLInit()                               */
457 /************************************************************************/
458 
XMLInit(CPLXMLNode * psTree,const char * pszVRTPathIn)459 CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn )
460 
461 {
462     if( pszVRTPathIn != nullptr )
463         m_pszVRTPath = CPLStrdup(pszVRTPathIn);
464 
465 /* -------------------------------------------------------------------- */
466 /*      Check for an SRS node.                                          */
467 /* -------------------------------------------------------------------- */
468     CPLXMLNode* psSRSNode = CPLGetXMLNode(psTree, "SRS");
469     if( psSRSNode )
470     {
471         if( m_poSRS )
472             m_poSRS->Release();
473         m_poSRS = new OGRSpatialReference();
474         m_poSRS->SetFromUserInput( CPLGetXMLValue(psSRSNode, nullptr, "") );
475         const char* pszMapping =
476             CPLGetXMLValue(psSRSNode, "dataAxisToSRSAxisMapping", nullptr);
477         if( pszMapping )
478         {
479             char** papszTokens = CSLTokenizeStringComplex( pszMapping, ",", FALSE, FALSE);
480             std::vector<int> anMapping;
481             for( int i = 0; papszTokens && papszTokens[i]; i++ )
482             {
483                 anMapping.push_back(atoi(papszTokens[i]));
484             }
485             CSLDestroy(papszTokens);
486             m_poSRS->SetDataAxisToSRSAxisMapping(anMapping);
487         }
488         else
489         {
490             m_poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
491         }
492     }
493 
494 /* -------------------------------------------------------------------- */
495 /*      Check for a GeoTransform node.                                  */
496 /* -------------------------------------------------------------------- */
497     if( strlen(CPLGetXMLValue(psTree, "GeoTransform", "")) > 0 )
498     {
499         const char *pszGT = CPLGetXMLValue(psTree, "GeoTransform", "");
500         char **papszTokens
501             = CSLTokenizeStringComplex( pszGT, ",", FALSE, FALSE );
502         if( CSLCount(papszTokens) != 6 )
503         {
504             CPLError( CE_Warning, CPLE_AppDefined,
505                       "GeoTransform node does not have expected six values.");
506         }
507         else
508         {
509             for( int iTA = 0; iTA < 6; iTA++ )
510                 m_adfGeoTransform[iTA] = CPLAtof(papszTokens[iTA]);
511             m_bGeoTransformSet = TRUE;
512         }
513 
514         CSLDestroy( papszTokens );
515     }
516 
517 /* -------------------------------------------------------------------- */
518 /*      Check for GCPs.                                                 */
519 /* -------------------------------------------------------------------- */
520     CPLXMLNode *psGCPList = CPLGetXMLNode( psTree, "GCPList" );
521 
522     if( psGCPList != nullptr )
523     {
524         GDALDeserializeGCPListFromXML( psGCPList,
525                                        &m_pasGCPList,
526                                        &m_nGCPCount,
527                                        &m_poGCP_SRS );
528     }
529 
530 /* -------------------------------------------------------------------- */
531 /*      Apply any dataset level metadata.                               */
532 /* -------------------------------------------------------------------- */
533     oMDMD.XMLInit( psTree, TRUE );
534 
535 /* -------------------------------------------------------------------- */
536 /*      Create dataset mask band.                                       */
537 /* -------------------------------------------------------------------- */
538 
539     /* Parse dataset mask band first */
540     CPLXMLNode* psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
541 
542     CPLXMLNode *psChild = nullptr;
543     if( psMaskBandNode )
544         psChild = psMaskBandNode->psChild;
545     else
546         psChild = nullptr;
547 
548     for( ; psChild != nullptr; psChild=psChild->psNext )
549     {
550         if( psChild->eType == CXT_Element
551             && EQUAL(psChild->pszValue,"VRTRasterBand") )
552         {
553             const char *pszSubclass = CPLGetXMLValue( psChild, "subclass",
554                                                       "VRTSourcedRasterBand" );
555 
556             VRTRasterBand  *poBand = InitBand(pszSubclass, 0, false);
557             if( poBand != nullptr
558                 && poBand->XMLInit( psChild, pszVRTPathIn, this,
559                                     m_oMapSharedSources ) == CE_None )
560             {
561                 SetMaskBand(poBand);
562                 break;
563             }
564             else
565             {
566                 delete poBand;
567                 return CE_Failure;
568             }
569         }
570     }
571 
572 /* -------------------------------------------------------------------- */
573 /*      Create band information objects.                                */
574 /* -------------------------------------------------------------------- */
575     int l_nBands = 0;
576     for( psChild=psTree->psChild; psChild != nullptr; psChild=psChild->psNext )
577     {
578         if( psChild->eType == CXT_Element
579             && EQUAL(psChild->pszValue,"VRTRasterBand") )
580         {
581             const char *pszSubclass = CPLGetXMLValue( psChild, "subclass",
582                                                       "VRTSourcedRasterBand" );
583 
584             VRTRasterBand  *poBand = InitBand(pszSubclass, l_nBands+1, true);
585             if( poBand != nullptr
586                 && poBand->XMLInit( psChild, pszVRTPathIn, this,
587                                     m_oMapSharedSources ) == CE_None )
588             {
589                 l_nBands ++;
590                 SetBand( l_nBands, poBand );
591             }
592             else
593             {
594                 delete poBand;
595                 return CE_Failure;
596             }
597         }
598     }
599 
600     CPLXMLNode* psGroup = CPLGetXMLNode(psTree, "Group");
601     if( psGroup )
602     {
603         const char* pszName = CPLGetXMLValue(psGroup, "name", nullptr);
604         if( pszName == nullptr || !EQUAL(pszName, "/") )
605         {
606             CPLError(CE_Failure, CPLE_AppDefined,
607                     "Missing name or not equal to '/'");
608             return CE_Failure;
609         }
610 
611         m_poRootGroup = std::make_shared<VRTGroup>(std::string(), "/");
612         m_poRootGroup->SetIsRootGroup();
613         if( !m_poRootGroup->XMLInit( m_poRootGroup, m_poRootGroup,
614                                      psGroup, pszVRTPathIn ) )
615         {
616             return CE_Failure;
617         }
618     }
619 
620 /* -------------------------------------------------------------------- */
621 /*      Create virtual overviews.                                       */
622 /* -------------------------------------------------------------------- */
623     const char* pszSubClass = CPLGetXMLValue(psTree, "subClass", "");
624     if( EQUAL(pszSubClass, "") )
625     {
626         CPLStringList aosTokens(CSLTokenizeString(
627             CPLGetXMLValue( psTree, "OverviewList", "" ) ));
628         m_osOverviewResampling =
629             CPLGetXMLValue( psTree, "OverviewList.resampling", "" );
630         for( int iOverview = 0; iOverview < aosTokens.size(); iOverview++ )
631         {
632             const int nOvFactor = atoi(aosTokens[iOverview]);
633             if( nOvFactor <= 1 )
634             {
635                 CPLError(CE_Failure, CPLE_AppDefined,
636                         "Invalid overview factor");
637                 return CE_Failure;
638             }
639 
640             AddVirtualOverview(nOvFactor, m_osOverviewResampling.empty() ?
641                                     "nearest" : m_osOverviewResampling.c_str());
642         }
643     }
644 
645     return CE_None;
646 }
647 
648 /************************************************************************/
649 /*                            GetGCPCount()                             */
650 /************************************************************************/
651 
GetGCPCount()652 int VRTDataset::GetGCPCount()
653 
654 {
655     return m_nGCPCount;
656 }
657 
658 /************************************************************************/
659 /*                               GetGCPs()                              */
660 /************************************************************************/
661 
GetGCPs()662 const GDAL_GCP *VRTDataset::GetGCPs()
663 
664 {
665     return m_pasGCPList;
666 }
667 
668 /************************************************************************/
669 /*                              SetGCPs()                               */
670 /************************************************************************/
671 
SetGCPs(int nGCPCountIn,const GDAL_GCP * pasGCPListIn,const OGRSpatialReference * poGCP_SRS)672 CPLErr VRTDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
673                              const OGRSpatialReference* poGCP_SRS )
674 
675 {
676     if( m_poGCP_SRS )
677         m_poGCP_SRS->Release();
678     if( m_nGCPCount > 0 )
679     {
680         GDALDeinitGCPs( m_nGCPCount, m_pasGCPList );
681         CPLFree( m_pasGCPList );
682     }
683 
684     m_poGCP_SRS = poGCP_SRS ? poGCP_SRS->Clone(): nullptr;
685 
686     m_nGCPCount = nGCPCountIn;
687 
688     m_pasGCPList = GDALDuplicateGCPs( nGCPCountIn, pasGCPListIn );
689 
690     SetNeedsFlush();
691 
692     return CE_None;
693 }
694 
695 /************************************************************************/
696 /*                           SetSpatialRef()                            */
697 /************************************************************************/
698 
SetSpatialRef(const OGRSpatialReference * poSRS)699 CPLErr VRTDataset::SetSpatialRef(const OGRSpatialReference* poSRS)
700 
701 {
702     if( m_poSRS )
703         m_poSRS->Release();
704     if( poSRS )
705         m_poSRS = poSRS->Clone();
706     else
707         m_poSRS = nullptr;
708 
709     SetNeedsFlush();
710 
711     return CE_None;
712 }
713 
714 /************************************************************************/
715 /*                          SetGeoTransform()                           */
716 /************************************************************************/
717 
SetGeoTransform(double * padfGeoTransformIn)718 CPLErr VRTDataset::SetGeoTransform( double *padfGeoTransformIn )
719 
720 {
721     memcpy( m_adfGeoTransform, padfGeoTransformIn, sizeof(double) * 6 );
722     m_bGeoTransformSet = TRUE;
723 
724     SetNeedsFlush();
725 
726     return CE_None;
727 }
728 
729 /************************************************************************/
730 /*                          GetGeoTransform()                           */
731 /************************************************************************/
732 
GetGeoTransform(double * padfGeoTransform)733 CPLErr VRTDataset::GetGeoTransform( double * padfGeoTransform )
734 
735 {
736     memcpy( padfGeoTransform, m_adfGeoTransform, sizeof(double) * 6 );
737 
738     return m_bGeoTransformSet ? CE_None : CE_Failure;
739 }
740 
741 /************************************************************************/
742 /*                            SetMetadata()                             */
743 /************************************************************************/
744 
SetMetadata(char ** papszMetadata,const char * pszDomain)745 CPLErr VRTDataset::SetMetadata( char **papszMetadata,
746                                 const char *pszDomain )
747 
748 {
749     SetNeedsFlush();
750 
751     return GDALDataset::SetMetadata( papszMetadata, pszDomain );
752 }
753 
754 /************************************************************************/
755 /*                          SetMetadataItem()                           */
756 /************************************************************************/
757 
SetMetadataItem(const char * pszName,const char * pszValue,const char * pszDomain)758 CPLErr VRTDataset::SetMetadataItem( const char *pszName,
759                                     const char *pszValue,
760                                     const char *pszDomain )
761 
762 {
763     SetNeedsFlush();
764 
765     return GDALDataset::SetMetadataItem( pszName, pszValue, pszDomain );
766 }
767 
768 /************************************************************************/
769 /*                              Identify()                              */
770 /************************************************************************/
771 
Identify(GDALOpenInfo * poOpenInfo)772 int VRTDataset::Identify( GDALOpenInfo * poOpenInfo )
773 
774 {
775     if( poOpenInfo->nHeaderBytes > 20
776          && strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader),"<VRTDataset") != nullptr )
777         return TRUE;
778 
779     if( strstr(poOpenInfo->pszFilename,"<VRTDataset") != nullptr )
780         return TRUE;
781 
782     if( STARTS_WITH_CI(poOpenInfo->pszFilename, VRT_PROTOCOL_PREFIX) )
783         return TRUE;
784 
785     return FALSE;
786 }
787 
788 /************************************************************************/
789 /*                                Open()                                */
790 /************************************************************************/
791 
Open(GDALOpenInfo * poOpenInfo)792 GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
793 
794 {
795 /* -------------------------------------------------------------------- */
796 /*      Does this appear to be a virtual dataset definition XML         */
797 /*      file?                                                           */
798 /* -------------------------------------------------------------------- */
799     if( !Identify( poOpenInfo ) )
800         return nullptr;
801 
802     if( STARTS_WITH_CI(poOpenInfo->pszFilename, VRT_PROTOCOL_PREFIX) )
803         return OpenVRTProtocol(poOpenInfo->pszFilename);
804 
805 /* -------------------------------------------------------------------- */
806 /*      Try to read the whole file into memory.                         */
807 /* -------------------------------------------------------------------- */
808     char *pszXML = nullptr;
809     VSILFILE *fp = poOpenInfo->fpL;
810 
811     char *pszVRTPath = nullptr;
812     if( fp != nullptr )
813     {
814         poOpenInfo->fpL = nullptr;
815 
816         GByte* pabyOut = nullptr;
817         if( !VSIIngestFile( fp, poOpenInfo->pszFilename, &pabyOut,
818                             nullptr, INT_MAX - 1 ) )
819         {
820             CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
821             return nullptr;
822         }
823         pszXML = reinterpret_cast<char*>(pabyOut);
824 
825         char* pszCurDir = CPLGetCurrentDir();
826         const char *currentVrtFilename
827             = CPLProjectRelativeFilename(pszCurDir, poOpenInfo->pszFilename);
828         CPLString osInitialCurrentVrtFilename(currentVrtFilename);
829         CPLFree(pszCurDir);
830 
831 #if defined(HAVE_READLINK) && defined(HAVE_LSTAT)
832         char filenameBuffer[2048];
833 
834         while( true ) {
835             VSIStatBuf statBuffer;
836             int lstatCode = lstat( currentVrtFilename, &statBuffer );
837             if( lstatCode == -1 ) {
838                 if( errno == ENOENT )
839                 {
840                     // File could be a virtual file, let later checks handle it.
841                     break;
842                 }
843                 else
844                 {
845                     CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
846                     CPLFree( pszXML );
847                     CPLError( CE_Failure, CPLE_FileIO,
848                               "Failed to lstat %s: %s",
849                               currentVrtFilename,
850                               VSIStrerror(errno) );
851                     return nullptr;
852                 }
853             }
854 
855             if( !VSI_ISLNK(statBuffer.st_mode) ) {
856                 break;
857             }
858 
859             const int bufferSize = static_cast<int>(
860                 readlink( currentVrtFilename,
861                           filenameBuffer,
862                           sizeof(filenameBuffer) ) );
863             if( bufferSize != -1 )
864             {
865                 filenameBuffer[std::min(bufferSize, static_cast<int>(
866                     sizeof(filenameBuffer) ) - 1)] = 0;
867                 // The filename in filenameBuffer might be a relative path
868                 // from the linkfile resolve it before looping
869                 currentVrtFilename = CPLProjectRelativeFilename(
870                     CPLGetDirname( currentVrtFilename ), filenameBuffer);
871             }
872             else
873             {
874                 CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
875                 CPLFree( pszXML );
876                 CPLError( CE_Failure, CPLE_FileIO,
877                           "Failed to read filename from symlink %s: %s",
878                           currentVrtFilename,
879                           VSIStrerror(errno) );
880                 return nullptr;
881             }
882         }
883 #endif  // HAVE_READLINK && HAVE_LSTAT
884 
885         if( osInitialCurrentVrtFilename == currentVrtFilename )
886             pszVRTPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
887         else
888             pszVRTPath = CPLStrdup(CPLGetPath(currentVrtFilename));
889 
890         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
891     }
892 /* -------------------------------------------------------------------- */
893 /*      Or use the filename as the XML input.                           */
894 /* -------------------------------------------------------------------- */
895     else
896     {
897         pszXML = CPLStrdup( poOpenInfo->pszFilename );
898     }
899 
900     if( CSLFetchNameValue(poOpenInfo->papszOpenOptions, "ROOT_PATH") != nullptr )
901     {
902         CPLFree(pszVRTPath);
903         pszVRTPath = CPLStrdup(
904             CSLFetchNameValue( poOpenInfo->papszOpenOptions, "ROOT_PATH" ) );
905     }
906 
907 /* -------------------------------------------------------------------- */
908 /*      Turn the XML representation into a VRTDataset.                  */
909 /* -------------------------------------------------------------------- */
910     VRTDataset *poDS = static_cast<VRTDataset *>(
911         OpenXML( pszXML, pszVRTPath, poOpenInfo->eAccess ) );
912 
913     if( poDS != nullptr )
914         poDS->m_bNeedsFlush =false;
915 
916     if( poDS != nullptr )
917     {
918         if( poDS->GetRasterCount() == 0 &&
919             (poOpenInfo->nOpenFlags & GDAL_OF_MULTIDIM_RASTER) == 0 &&
920             strstr(pszXML, "VRTPansharpenedDataset") == nullptr )
921         {
922             delete poDS;
923             poDS = nullptr;
924         }
925         else if( poDS->GetRootGroup() == nullptr &&
926             (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) == 0 &&
927             (poOpenInfo->nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 )
928         {
929             delete poDS;
930             poDS = nullptr;
931         }
932     }
933 
934     CPLFree( pszXML );
935     CPLFree( pszVRTPath );
936 
937 /* -------------------------------------------------------------------- */
938 /*      Initialize info for later overview discovery.                   */
939 /* -------------------------------------------------------------------- */
940 
941     if( poDS != nullptr )
942     {
943         if( fp != nullptr )
944         {
945             poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
946             if( poOpenInfo->AreSiblingFilesLoaded() )
947                 poDS->oOvManager.TransferSiblingFiles(
948                     poOpenInfo->StealSiblingFiles() );
949         }
950 
951         if (poDS->eAccess == GA_Update &&
952             poDS->m_poRootGroup && !STARTS_WITH_CI(poOpenInfo->pszFilename, "<VRT") )
953         {
954             poDS->m_poRootGroup->SetFilename(poOpenInfo->pszFilename);
955         }
956     }
957 
958     return poDS;
959 }
960 
961 /************************************************************************/
962 /*                         OpenVRTProtocol()                            */
963 /*                                                                      */
964 /*      Create an open VRTDataset from a vrt:// string.                 */
965 /************************************************************************/
966 
OpenVRTProtocol(const char * pszSpec)967 GDALDataset *VRTDataset::OpenVRTProtocol( const char* pszSpec )
968 
969 {
970     CPLAssert( STARTS_WITH_CI(pszSpec, VRT_PROTOCOL_PREFIX) );
971     CPLString osFilename(pszSpec + strlen(VRT_PROTOCOL_PREFIX) );
972     const auto nPosQuotationMark = osFilename.find('?');
973     CPLString osQueryString;
974     if( nPosQuotationMark != std::string::npos )
975     {
976         osQueryString = osFilename.substr(nPosQuotationMark+1);
977         osFilename.resize(nPosQuotationMark);
978     }
979     auto poSrcDS =
980         GDALDataset::Open(osFilename, GDAL_OF_RASTER | GDAL_OF_SHARED,
981                           nullptr, nullptr, nullptr);
982     if( poSrcDS == nullptr )
983     {
984         return nullptr;
985     }
986 
987     // Parse query string
988     CPLStringList aosTokens(CSLTokenizeString2(osQueryString, "&", 0));
989     std::vector<int> anBands;
990     for( int i = 0; i < aosTokens.size(); i++ )
991     {
992         char* pszKey = nullptr;
993         const char* pszValue = CPLParseNameValue(aosTokens[i], &pszKey);
994         if( pszKey && pszValue )
995         {
996             if( EQUAL(pszKey, "bands") )
997             {
998                 CPLStringList aosBands(CSLTokenizeString2(pszValue, ",", 0));
999                 for( int j = 0; j < aosBands.size(); j++ )
1000                 {
1001                     if( EQUAL(aosBands[j], "mask") )
1002                     {
1003                         anBands.push_back(0);
1004                     }
1005                     else
1006                     {
1007                         const int nBand = atoi(aosBands[j]);
1008                         if( nBand <= 0 || nBand > poSrcDS->GetRasterCount() )
1009                         {
1010                             CPLError(CE_Failure, CPLE_IllegalArg,
1011                                     "Invalid band number: %s", aosBands[j]);
1012                             poSrcDS->ReleaseRef();
1013                             CPLFree(pszKey);
1014                             return nullptr;
1015                         }
1016                         anBands.push_back(nBand);
1017                     }
1018                 }
1019             }
1020             else
1021             {
1022                 CPLError(CE_Failure, CPLE_NotSupported,
1023                          "Unknown option: %s", pszKey);
1024                 poSrcDS->ReleaseRef();
1025                 CPLFree(pszKey);
1026                 return nullptr;
1027             }
1028         }
1029         CPLFree(pszKey);
1030     }
1031 
1032     CPLStringList argv;
1033     argv.AddString("-of");
1034     argv.AddString("VRT");
1035 
1036     for( const int nBand: anBands )
1037     {
1038         argv.AddString("-b");
1039         argv.AddString(nBand == 0 ? "mask" : CPLSPrintf("%d", nBand));
1040     }
1041 
1042     GDALTranslateOptions* psOptions = GDALTranslateOptionsNew(argv.List(), nullptr);
1043 
1044     auto hRet = GDALTranslate("", GDALDataset::ToHandle(poSrcDS),
1045                               psOptions, nullptr);
1046 
1047     GDALTranslateOptionsFree( psOptions );
1048 
1049     poSrcDS->ReleaseRef();
1050 
1051     auto poDS = cpl::down_cast<VRTDataset*>(GDALDataset::FromHandle(hRet));
1052     if( poDS )
1053     {
1054         poDS->SetDescription(pszSpec);
1055         poDS->SetWritable(false);
1056     }
1057     return poDS;
1058 }
1059 
1060 /************************************************************************/
1061 /*                              OpenXML()                               */
1062 /*                                                                      */
1063 /*      Create an open VRTDataset from a supplied XML representation    */
1064 /*      of the dataset.                                                 */
1065 /************************************************************************/
1066 
OpenXML(const char * pszXML,const char * pszVRTPath,GDALAccess eAccess)1067 GDALDataset *VRTDataset::OpenXML( const char *pszXML, const char *pszVRTPath,
1068                                   GDALAccess eAccess)
1069 
1070 {
1071  /* -------------------------------------------------------------------- */
1072  /*      Parse the XML.                                                  */
1073  /* -------------------------------------------------------------------- */
1074     CPLXMLTreeCloser psTree(CPLParseXMLString( pszXML ));
1075     if( psTree == nullptr )
1076         return nullptr;
1077 
1078     CPLXMLNode *psRoot = CPLGetXMLNode( psTree.get(), "=VRTDataset" );
1079     if( psRoot == nullptr )
1080     {
1081         CPLError( CE_Failure, CPLE_AppDefined,
1082                   "Missing VRTDataset element." );
1083         return nullptr;
1084     }
1085 
1086     const char* pszSubClass = CPLGetXMLValue(psRoot, "subClass", "");
1087 
1088     const bool bIsPansharpened =
1089         strcmp(pszSubClass, "VRTPansharpenedDataset" ) == 0;
1090 
1091     if( !bIsPansharpened &&
1092         CPLGetXMLNode( psRoot, "Group" ) == nullptr &&
1093         (CPLGetXMLNode( psRoot, "rasterXSize" ) == nullptr
1094         || CPLGetXMLNode( psRoot, "rasterYSize" ) == nullptr
1095         || CPLGetXMLNode( psRoot, "VRTRasterBand" ) == nullptr) )
1096     {
1097         CPLError( CE_Failure, CPLE_AppDefined,
1098                   "Missing one of rasterXSize, rasterYSize or bands on"
1099                   " VRTDataset." );
1100         return nullptr;
1101     }
1102 
1103 /* -------------------------------------------------------------------- */
1104 /*      Create the new virtual dataset object.                          */
1105 /* -------------------------------------------------------------------- */
1106     const int nXSize = atoi(CPLGetXMLValue(psRoot, "rasterXSize","0"));
1107     const int nYSize = atoi(CPLGetXMLValue(psRoot, "rasterYSize","0"));
1108 
1109     if( !bIsPansharpened &&
1110         CPLGetXMLNode( psRoot, "VRTRasterBand" ) != nullptr &&
1111         !GDALCheckDatasetDimensions( nXSize, nYSize ) )
1112     {
1113         return nullptr;
1114     }
1115 
1116     VRTDataset *poDS = nullptr;
1117     if( strcmp(pszSubClass, "VRTWarpedDataset") == 0 )
1118         poDS = new VRTWarpedDataset( nXSize, nYSize );
1119     else if( bIsPansharpened )
1120         poDS = new VRTPansharpenedDataset( nXSize, nYSize );
1121     else
1122     {
1123         poDS = new VRTDataset( nXSize, nYSize );
1124         poDS->eAccess = eAccess;
1125     }
1126 
1127     if( poDS->XMLInit( psRoot, pszVRTPath ) != CE_None )
1128     {
1129         delete poDS;
1130         poDS = nullptr;
1131     }
1132 
1133 /* -------------------------------------------------------------------- */
1134 /*      Try to return a regular handle on the file.                     */
1135 /* -------------------------------------------------------------------- */
1136 
1137     return poDS;
1138 }
1139 
1140 /************************************************************************/
1141 /*                              AddBand()                               */
1142 /************************************************************************/
1143 
AddBand(GDALDataType eType,char ** papszOptions)1144 CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
1145 
1146 {
1147     SetNeedsFlush();
1148 
1149 /* ==================================================================== */
1150 /*      Handle a new raw band.                                          */
1151 /* ==================================================================== */
1152     const char *pszSubClass = CSLFetchNameValue(papszOptions, "subclass");
1153 
1154     if( pszSubClass != nullptr && EQUAL(pszSubClass,"VRTRawRasterBand") )
1155     {
1156         const int nWordDataSize = GDALGetDataTypeSizeBytes( eType );
1157 
1158 /* -------------------------------------------------------------------- */
1159 /*      Collect required information.                                   */
1160 /* -------------------------------------------------------------------- */
1161         const char* pszImageOffset =
1162             CSLFetchNameValueDef(papszOptions, "ImageOffset", "0");
1163         vsi_l_offset nImageOffset = CPLScanUIntBig(
1164             pszImageOffset, static_cast<int>(strlen(pszImageOffset)) );
1165 
1166         int nPixelOffset = nWordDataSize;
1167         const char* pszPixelOffset =
1168                             CSLFetchNameValue(papszOptions, "PixelOffset");
1169         if( pszPixelOffset != nullptr )
1170             nPixelOffset = atoi(pszPixelOffset);
1171 
1172         int nLineOffset;
1173         const char* pszLineOffset =
1174                                 CSLFetchNameValue(papszOptions, "LineOffset");
1175         if( pszLineOffset != nullptr )
1176             nLineOffset = atoi(pszLineOffset);
1177         else
1178         {
1179             if( nPixelOffset > INT_MAX / GetRasterXSize() ||
1180                 nPixelOffset < INT_MIN / GetRasterXSize() )
1181             {
1182                 CPLError( CE_Failure, CPLE_AppDefined, "Int overflow");
1183                 return CE_Failure;
1184             }
1185             nLineOffset = nPixelOffset * GetRasterXSize();
1186         }
1187 
1188         const char *pszByteOrder =
1189                                 CSLFetchNameValue(papszOptions, "ByteOrder");
1190 
1191         const char *pszFilename =
1192                             CSLFetchNameValue(papszOptions, "SourceFilename");
1193         if( pszFilename == nullptr )
1194         {
1195             CPLError( CE_Failure, CPLE_AppDefined,
1196                       "AddBand() requires a SourceFilename option for "
1197                       "VRTRawRasterBands." );
1198             return CE_Failure;
1199         }
1200 
1201         const bool bRelativeToVRT =
1202             CPLFetchBool( papszOptions, "relativeToVRT", false );
1203 
1204 /* -------------------------------------------------------------------- */
1205 /*      Create and initialize the band.                                 */
1206 /* -------------------------------------------------------------------- */
1207 
1208         VRTRawRasterBand *poBand =
1209             new VRTRawRasterBand( this, GetRasterCount() + 1, eType );
1210 
1211         char* l_pszVRTPath = CPLStrdup(CPLGetPath(GetDescription()));
1212         if( EQUAL(l_pszVRTPath, "") )
1213         {
1214             CPLFree(l_pszVRTPath);
1215             l_pszVRTPath = nullptr;
1216         }
1217 
1218         const CPLErr eErr =
1219             poBand->SetRawLink( pszFilename, l_pszVRTPath, bRelativeToVRT,
1220                                 nImageOffset, nPixelOffset, nLineOffset,
1221                                 pszByteOrder );
1222         CPLFree(l_pszVRTPath);
1223         if( eErr != CE_None )
1224         {
1225             delete poBand;
1226             return eErr;
1227         }
1228 
1229         SetBand( GetRasterCount() + 1, poBand );
1230 
1231         return CE_None;
1232     }
1233 
1234 /* ==================================================================== */
1235 /*      Handle a new "sourced" band.                                    */
1236 /* ==================================================================== */
1237     else
1238     {
1239         VRTSourcedRasterBand *poBand = nullptr;
1240 
1241         /* ---- Check for our sourced band 'derived' subclass ---- */
1242         if(pszSubClass != nullptr && EQUAL(pszSubClass,"VRTDerivedRasterBand")) {
1243 
1244             /* We'll need a pointer to the subclass in case we need */
1245             /* to set the new band's pixel function below. */
1246             VRTDerivedRasterBand* poDerivedBand = new VRTDerivedRasterBand(
1247                 this, GetRasterCount() + 1, eType,
1248                 GetRasterXSize(), GetRasterYSize());
1249 
1250             /* Set the pixel function options it provided. */
1251             const char* pszFuncName =
1252                 CSLFetchNameValue(papszOptions, "PixelFunctionType");
1253             if( pszFuncName != nullptr )
1254                 poDerivedBand->SetPixelFunctionName(pszFuncName);
1255 
1256             const char* pszLanguage =
1257                 CSLFetchNameValue(papszOptions, "PixelFunctionLanguage");
1258             if( pszLanguage != nullptr )
1259                 poDerivedBand->SetPixelFunctionLanguage(pszLanguage);
1260 
1261             const char* pszTransferTypeName =
1262                 CSLFetchNameValue(papszOptions, "SourceTransferType");
1263             if( pszTransferTypeName != nullptr )
1264             {
1265                 const GDALDataType eTransferType =
1266                     GDALGetDataTypeByName(pszTransferTypeName);
1267                 if( eTransferType == GDT_Unknown )
1268                 {
1269                     CPLError( CE_Failure, CPLE_AppDefined,
1270                               "invalid SourceTransferType: \"%s\".",
1271                               pszTransferTypeName);
1272                     delete poDerivedBand;
1273                     return CE_Failure;
1274                 }
1275                 poDerivedBand->SetSourceTransferType(eTransferType);
1276             }
1277 
1278             /* We're done with the derived band specific stuff, so */
1279             /* we can assigned the base class pointer now. */
1280             poBand = poDerivedBand;
1281         }
1282         else {
1283             int nBlockXSizeIn = atoi(
1284                 CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "0"));
1285             int nBlockYSizeIn = atoi(
1286                 CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "0"));
1287             /* ---- Standard sourced band ---- */
1288             poBand = new VRTSourcedRasterBand(
1289                 this, GetRasterCount() + 1, eType,
1290                 GetRasterXSize(), GetRasterYSize(),
1291                 nBlockXSizeIn, nBlockYSizeIn);
1292         }
1293 
1294         SetBand( GetRasterCount() + 1, poBand );
1295 
1296         for( int i=0; papszOptions != nullptr && papszOptions[i] != nullptr; i++ )
1297         {
1298             if( STARTS_WITH_CI(papszOptions[i], "AddFuncSource=") )
1299             {
1300                 char **papszTokens
1301                     = CSLTokenizeStringComplex( papszOptions[i]+14,
1302                                                 ",", TRUE, FALSE );
1303                 if( CSLCount(papszTokens) < 1 )
1304                 {
1305                     CPLError( CE_Failure, CPLE_AppDefined,
1306                               "AddFuncSource(): required argument missing." );
1307                     // TODO: How should this error be handled?  Return
1308                     // CE_Failure?
1309                 }
1310 
1311                 VRTImageReadFunc pfnReadFunc = nullptr;
1312                 sscanf( papszTokens[0], "%p", &pfnReadFunc );
1313 
1314                 void *pCBData = nullptr;
1315                 if( CSLCount(papszTokens) > 1 )
1316                     sscanf( papszTokens[1], "%p", &pCBData );
1317 
1318                 const double dfNoDataValue =
1319                     ( CSLCount(papszTokens) > 2 ) ?
1320                     CPLAtof( papszTokens[2] ) : VRT_NODATA_UNSET;
1321 
1322                 poBand->AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue );
1323 
1324                 CSLDestroy( papszTokens );
1325             }
1326         }
1327 
1328         return CE_None;
1329     }
1330 }
1331 /*! @endcond */
1332 /************************************************************************/
1333 /*                              VRTAddBand()                            */
1334 /************************************************************************/
1335 
1336 /**
1337  * @see VRTDataset::VRTAddBand().
1338  *
1339  * @note The return type of this function is int, but the actual values
1340  * returned are of type CPLErr.
1341  */
1342 
VRTAddBand(VRTDatasetH hDataset,GDALDataType eType,char ** papszOptions)1343 int CPL_STDCALL VRTAddBand( VRTDatasetH hDataset, GDALDataType eType,
1344                             char **papszOptions )
1345 
1346 {
1347     VALIDATE_POINTER1( hDataset, "VRTAddBand", 0 );
1348 
1349     return static_cast<VRTDataset *>(GDALDataset::FromHandle(
1350         hDataset))->AddBand( eType, papszOptions );
1351 }
1352 /*! @cond Doxygen_Suppress */
1353 /************************************************************************/
1354 /*                               Create()                               */
1355 /************************************************************************/
1356 
1357 GDALDataset *
Create(const char * pszName,int nXSize,int nYSize,int nBands,GDALDataType eType,char ** papszOptions)1358 VRTDataset::Create( const char * pszName,
1359                     int nXSize, int nYSize, int nBands,
1360                     GDALDataType eType, char ** papszOptions )
1361 
1362 {
1363     if( STARTS_WITH_CI(pszName, "<VRTDataset") )
1364     {
1365         GDALDataset *poDS = OpenXML( pszName, nullptr, GA_Update );
1366         if(  poDS != nullptr )
1367             poDS->SetDescription( "<FromXML>" );
1368         return poDS;
1369     }
1370 
1371     const char *pszSubclass = CSLFetchNameValue( papszOptions,
1372                                                  "SUBCLASS" );
1373 
1374     VRTDataset *poDS = nullptr;
1375 
1376     if( pszSubclass == nullptr || EQUAL(pszSubclass,"VRTDataset") )
1377         poDS = new VRTDataset( nXSize, nYSize );
1378     else if( EQUAL(pszSubclass,"VRTWarpedDataset") )
1379     {
1380         poDS = new VRTWarpedDataset( nXSize, nYSize );
1381     }
1382     else
1383     {
1384         CPLError( CE_Failure, CPLE_AppDefined,
1385                   "SUBCLASS=%s not recognised.",
1386                   pszSubclass );
1387         return nullptr;
1388     }
1389     poDS->eAccess = GA_Update;
1390 
1391     poDS->SetDescription( pszName );
1392 
1393     for( int iBand = 0; iBand < nBands; iBand++ )
1394         poDS->AddBand( eType, nullptr );
1395 
1396     poDS->SetNeedsFlush();
1397 
1398     poDS->oOvManager.Initialize( poDS, pszName );
1399 
1400     return poDS;
1401 }
1402 
1403 
1404 /************************************************************************/
1405 /*                     CreateMultiDimensional()                         */
1406 /************************************************************************/
1407 
CreateMultiDimensional(const char * pszFilename,CSLConstList,CSLConstList)1408 GDALDataset * VRTDataset::CreateMultiDimensional( const char * pszFilename,
1409                                                   CSLConstList /*papszRootGroupOptions*/,
1410                                                   CSLConstList /*papszOptions*/ )
1411 {
1412     VRTDataset *poDS = new VRTDataset( 0, 0 );
1413     poDS->eAccess = GA_Update;
1414     poDS->SetDescription(pszFilename);
1415     poDS->m_poRootGroup = std::make_shared<VRTGroup>(std::string(), "/");
1416     poDS->m_poRootGroup->SetIsRootGroup();
1417     poDS->m_poRootGroup->SetFilename(pszFilename);
1418     poDS->m_poRootGroup->SetDirty();
1419 
1420     return poDS;
1421 }
1422 
1423 
1424 /************************************************************************/
1425 /*                            GetFileList()                             */
1426 /************************************************************************/
1427 
GetFileList()1428 char** VRTDataset::GetFileList()
1429 {
1430     char** papszFileList = GDALDataset::GetFileList();
1431 
1432     int nSize = CSLCount(papszFileList);
1433     int nMaxSize = nSize;
1434 
1435     // Do not need an element deallocator as each string points to an
1436     // element of the papszFileList.
1437     CPLHashSet* hSetFiles = CPLHashSetNew(CPLHashSetHashStr,
1438                                           CPLHashSetEqualStr,
1439                                           nullptr);
1440 
1441     for( int iBand = 0; iBand < nBands; iBand++ )
1442     {
1443       static_cast<VRTRasterBand *>(
1444           papoBands[iBand])->GetFileList(
1445               &papszFileList, &nSize, &nMaxSize, hSetFiles );
1446     }
1447 
1448     CPLHashSetDestroy(hSetFiles);
1449 
1450     return papszFileList;
1451 }
1452 
1453 /************************************************************************/
1454 /*                              Delete()                                */
1455 /************************************************************************/
1456 
1457 /* We implement Delete() to avoid that the default implementation */
1458 /* in GDALDriver::Delete() destroys the source files listed by GetFileList(),*/
1459 /* which would be an undesired effect... */
Delete(const char * pszFilename)1460 CPLErr VRTDataset::Delete( const char * pszFilename )
1461 {
1462     GDALDriverH hDriver = GDALIdentifyDriver(pszFilename, nullptr);
1463 
1464     if( !hDriver || !EQUAL( GDALGetDriverShortName(hDriver), "VRT" ) )
1465         return CE_Failure;
1466 
1467     if( strstr(pszFilename, "<VRTDataset") == nullptr &&
1468         VSIUnlink( pszFilename ) != 0 )
1469     {
1470         CPLError( CE_Failure, CPLE_AppDefined,
1471                   "Deleting %s failed:\n%s",
1472                   pszFilename,
1473                   VSIStrerror(errno) );
1474         return CE_Failure;
1475     }
1476 
1477     return CE_None;
1478 }
1479 
1480 /************************************************************************/
1481 /*                          CreateMaskBand()                            */
1482 /************************************************************************/
1483 
CreateMaskBand(int)1484 CPLErr VRTDataset::CreateMaskBand( int )
1485 {
1486     if( m_poMaskBand != nullptr )
1487     {
1488         CPLError(CE_Failure, CPLE_AppDefined,
1489                  "This VRT dataset has already a mask band");
1490         return CE_Failure;
1491     }
1492 
1493     SetMaskBand(new VRTSourcedRasterBand( this, 0 ));
1494 
1495     return CE_None;
1496 }
1497 
1498 /************************************************************************/
1499 /*                           SetMaskBand()                              */
1500 /************************************************************************/
1501 
SetMaskBand(VRTRasterBand * poMaskBandIn)1502 void VRTDataset::SetMaskBand(VRTRasterBand* poMaskBandIn)
1503 {
1504     delete m_poMaskBand;
1505     m_poMaskBand = poMaskBandIn;
1506     m_poMaskBand->SetIsMaskBand();
1507 }
1508 
1509 /************************************************************************/
1510 /*                        CloseDependentDatasets()                      */
1511 /************************************************************************/
1512 
CloseDependentDatasets()1513 int VRTDataset::CloseDependentDatasets()
1514 {
1515     /* We need to call it before removing the sources, otherwise */
1516     /* we would remove them from the serizalized VRT */
1517     FlushCache();
1518 
1519     int bHasDroppedRef = GDALDataset::CloseDependentDatasets();
1520 
1521     for( int iBand = 0; iBand < nBands; iBand++ )
1522     {
1523         bHasDroppedRef |= static_cast<VRTRasterBand *>(
1524             papoBands[iBand] )->CloseDependentDatasets();
1525     }
1526 
1527     return bHasDroppedRef;
1528 }
1529 
1530 /************************************************************************/
1531 /*                      CheckCompatibleForDatasetIO()                   */
1532 /************************************************************************/
1533 
1534 /* We will return TRUE only if all the bands are VRTSourcedRasterBands */
1535 /* made of identical sources, that are strictly VRTSimpleSource, and that */
1536 /* the band number of each source is the band number of the */
1537 /* VRTSourcedRasterBand. */
1538 
CheckCompatibleForDatasetIO()1539 int VRTDataset::CheckCompatibleForDatasetIO()
1540 {
1541     int nSources = 0;
1542     VRTSource **papoSources = nullptr;
1543     CPLString osResampling;
1544 
1545     if( m_bCompatibleForDatasetIO >= 0 )
1546     {
1547         return m_bCompatibleForDatasetIO;
1548     }
1549 
1550     for(int iBand = 0; iBand < nBands; iBand++)
1551     {
1552         if( !static_cast<VRTRasterBand *>(
1553                 papoBands[iBand] )->IsSourcedRasterBand() )
1554             return FALSE;
1555 
1556         VRTSourcedRasterBand* poBand
1557             = static_cast<VRTSourcedRasterBand*>( papoBands[iBand] );
1558 
1559         // Do not allow VRTDerivedRasterBand for example
1560         if( typeid(*poBand) != typeid(VRTSourcedRasterBand) )
1561             return FALSE;
1562 
1563         if( iBand == 0 )
1564         {
1565             nSources = poBand->nSources;
1566             papoSources = poBand->papoSources;
1567             for(int iSource = 0; iSource < nSources; iSource++)
1568             {
1569                 if( !papoSources[iSource]->IsSimpleSource() )
1570                     return FALSE;
1571 
1572                 VRTSimpleSource* poSource = static_cast<VRTSimpleSource *>(
1573                     papoSources[iSource] );
1574                 if( !EQUAL(poSource->GetType(), "SimpleSource") )
1575                     return FALSE;
1576 
1577                 GDALRasterBand *srcband = poSource->GetBand();
1578                 if( srcband == nullptr )
1579                     return FALSE;
1580                 if( srcband->GetDataset() == nullptr )
1581                     return FALSE;
1582                 if( srcband->GetDataset()->GetRasterCount() <= iBand )
1583                     return FALSE;
1584                 if( srcband->GetDataset()->GetRasterBand(iBand + 1) != srcband )
1585                     return FALSE;
1586                 osResampling = poSource->GetResampling();
1587             }
1588         }
1589         else if( nSources != poBand->nSources )
1590         {
1591             return FALSE;
1592         }
1593         else
1594         {
1595             for(int iSource = 0; iSource < nSources; iSource++)
1596             {
1597                 if( !poBand->papoSources[iSource]->IsSimpleSource() )
1598                     return FALSE;
1599                 VRTSimpleSource* poRefSource
1600                     = static_cast<VRTSimpleSource *>(
1601                         papoSources[iSource] );
1602 
1603                 VRTSimpleSource* poSource = static_cast<VRTSimpleSource *>(
1604                     poBand->papoSources[iSource] );
1605                 if( !EQUAL(poSource->GetType(), "SimpleSource") )
1606                     return FALSE;
1607                 if( !poSource->IsSameExceptBandNumber(poRefSource) )
1608                     return FALSE;
1609 
1610                 GDALRasterBand *srcband = poSource->GetBand();
1611                 if( srcband == nullptr )
1612                     return FALSE;
1613                 if( srcband->GetDataset() == nullptr )
1614                     return FALSE;
1615                 if( srcband->GetDataset()->GetRasterCount() <= iBand )
1616                     return FALSE;
1617                 if( srcband->GetDataset()->GetRasterBand(iBand + 1) != srcband )
1618                     return FALSE;
1619                 if( osResampling.compare(poSource->GetResampling()) != 0 )
1620                     return FALSE;
1621             }
1622         }
1623     }
1624 
1625     return nSources != 0;
1626 }
1627 
1628 
1629 /************************************************************************/
1630 /*                      ExpandProxyBands()                              */
1631 /************************************************************************/
1632 /* In ProxyPoolDatasets, by default only one band is initialized. When using
1633  * VRTDataset::IRasterIO and CheckCompatibleForDatasetIO is True, we need to have
1634  * all bands initialized (but only for the last band in the VRTDataset). This function
1635  * assumes CheckCompatibleForDatasetIO() has already been run and returned successful.
1636  */
ExpandProxyBands()1637 void VRTDataset::ExpandProxyBands()
1638 {
1639     VRTSourcedRasterBand * poLastBand = static_cast<VRTSourcedRasterBand*>(papoBands[nBands - 1]);
1640 
1641     CPLAssert(poLastBand != nullptr); // CheckCompatibleForDatasetIO()
1642 
1643     int nSources = poLastBand->nSources;
1644 
1645     for (int iSource = 0; iSource < nSources; iSource++)
1646     {
1647         VRTSimpleSource* poSource = static_cast<VRTSimpleSource *>(poLastBand->papoSources[iSource]);
1648 
1649         CPLAssert(poSource != nullptr); // CheckCompatibleForDatasetIO()
1650 
1651         GDALProxyPoolDataset * dataset = dynamic_cast<GDALProxyPoolDataset *>(poSource->GetBand()->GetDataset());
1652 
1653         if (dataset == nullptr)
1654         {
1655             continue; // only GDALProxyPoolDataset needs to be expanded
1656         }
1657 
1658         if (dataset->GetBands()[0] != nullptr)
1659         {
1660             continue; // first band already set, so just assume all the others are set as well
1661         }
1662 
1663         for (int iBand = 1; iBand <= nBands - 1; iBand++ )
1664         {
1665             VRTSourcedRasterBand * srcband = static_cast<VRTSourcedRasterBand *>(papoBands[iBand - 1]);
1666             VRTSimpleSource* src = static_cast<VRTSimpleSource *>(srcband->papoSources[iSource]);
1667             GDALRasterBand * rasterband = src->GetBand();
1668 
1669             int nBlockXSize, nBlockYSize;
1670 
1671             rasterband->GetBlockSize(&nBlockXSize, &nBlockYSize);
1672 
1673             dataset->AddSrcBand(iBand, rasterband->GetRasterDataType(), nBlockXSize, nBlockYSize);
1674         }
1675     }
1676 }
1677 
1678 
1679 
1680 
1681 /************************************************************************/
1682 /*                         GetSingleSimpleSource()                      */
1683 /*                                                                      */
1684 /* Returns a non-NULL dataset if the VRT is made of a single source     */
1685 /* that is a simple source, in its full extent, and with all of its     */
1686 /* bands. Basically something produced by :                             */
1687 /*   gdal_translate src dst.vrt -of VRT (-a_srs / -a_ullr)              */
1688 /************************************************************************/
1689 
GetSingleSimpleSource()1690 GDALDataset* VRTDataset::GetSingleSimpleSource()
1691 {
1692     if( !CheckCompatibleForDatasetIO() )
1693         return nullptr;
1694 
1695     VRTSourcedRasterBand* poVRTBand
1696         = static_cast<VRTSourcedRasterBand *>( papoBands[0] );
1697     if( poVRTBand->nSources != 1 )
1698         return nullptr;
1699 
1700     VRTSimpleSource* poSource = static_cast<VRTSimpleSource *>(
1701         poVRTBand->papoSources[0] );
1702 
1703     GDALRasterBand* poBand = poSource->GetBand();
1704     if( poBand == nullptr )
1705         return nullptr;
1706 
1707     GDALDataset* poSrcDS = poBand->GetDataset();
1708     if( poSrcDS == nullptr )
1709         return nullptr;
1710 
1711     /* Check that it uses the full source dataset */
1712     double dfReqXOff = 0.0;
1713     double dfReqYOff = 0.0;
1714     double dfReqXSize = 0.0;
1715     double dfReqYSize = 0.0;
1716     int nReqXOff = 0;
1717     int nReqYOff = 0;
1718     int nReqXSize = 0;
1719     int nReqYSize = 0;
1720     int nOutXOff = 0;
1721     int nOutYOff = 0;
1722     int nOutXSize = 0;
1723     int nOutYSize = 0;
1724     if( !poSource->GetSrcDstWindow(
1725            0, 0,
1726            poSrcDS->GetRasterXSize(),
1727            poSrcDS->GetRasterYSize(),
1728            poSrcDS->GetRasterXSize(),
1729            poSrcDS->GetRasterYSize(),
1730            &dfReqXOff, &dfReqYOff,
1731            &dfReqXSize, &dfReqYSize,
1732            &nReqXOff, &nReqYOff,
1733            &nReqXSize, &nReqYSize,
1734            &nOutXOff, &nOutYOff,
1735            &nOutXSize, &nOutYSize ) )
1736         return nullptr;
1737 
1738     if( nReqXOff != 0 || nReqYOff != 0 ||
1739         nReqXSize != poSrcDS->GetRasterXSize() ||
1740         nReqYSize != poSrcDS->GetRasterYSize() )
1741         return nullptr;
1742 
1743     if( nOutXOff != 0 || nOutYOff != 0 ||
1744         nOutXSize != poSrcDS->GetRasterXSize() ||
1745         nOutYSize != poSrcDS->GetRasterYSize() )
1746         return nullptr;
1747 
1748     return poSrcDS;
1749 }
1750 
1751 /************************************************************************/
1752 /*                             AdviseRead()                             */
1753 /************************************************************************/
1754 
AdviseRead(int nXOff,int nYOff,int nXSize,int nYSize,int nBufXSize,int nBufYSize,GDALDataType eDT,int nBandCount,int * panBandList,char ** papszOptions)1755 CPLErr VRTDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
1756                                int nBufXSize, int nBufYSize,
1757                                GDALDataType eDT,
1758                                int nBandCount, int *panBandList,
1759                                char **papszOptions )
1760 {
1761     if( !CheckCompatibleForDatasetIO() )
1762         return CE_None;
1763 
1764     VRTSourcedRasterBand* poVRTBand
1765         = static_cast<VRTSourcedRasterBand *>( papoBands[0] );
1766     if( poVRTBand->nSources != 1 )
1767         return CE_None;
1768 
1769     VRTSimpleSource* poSource = static_cast<VRTSimpleSource *>(
1770         poVRTBand->papoSources[0] );
1771 
1772     GDALRasterBand* poBand = poSource->GetBand();
1773     if( poBand == nullptr )
1774         return CE_None;
1775 
1776     GDALDataset* poSrcDS = poBand->GetDataset();
1777     if( poSrcDS == nullptr )
1778         return CE_None;
1779 
1780     /* Find source window and buffer size */
1781     double dfReqXOff = 0.0;
1782     double dfReqYOff = 0.0;
1783     double dfReqXSize = 0.0;
1784     double dfReqYSize = 0.0;
1785     int nReqXOff = 0;
1786     int nReqYOff = 0;
1787     int nReqXSize = 0;
1788     int nReqYSize = 0;
1789     int nOutXOff = 0;
1790     int nOutYOff = 0;
1791     int nOutXSize = 0;
1792     int nOutYSize = 0;
1793     if( !poSource->GetSrcDstWindow(
1794            nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
1795            &dfReqXOff, &dfReqYOff,
1796            &dfReqXSize, &dfReqYSize,
1797            &nReqXOff, &nReqYOff,
1798            &nReqXSize, &nReqYSize,
1799            &nOutXOff, &nOutYOff,
1800            &nOutXSize, &nOutYSize ) )
1801         return CE_None;
1802 
1803     return poSrcDS->AdviseRead(nReqXOff, nReqYOff, nReqXSize, nReqYSize,
1804                                nOutXSize, nOutYSize,
1805                                eDT, nBandCount, panBandList, papszOptions);
1806 }
1807 
1808 /************************************************************************/
1809 /*                              IRasterIO()                             */
1810 /************************************************************************/
1811 
IRasterIO(GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,GSpacing nPixelSpace,GSpacing nLineSpace,GSpacing nBandSpace,GDALRasterIOExtraArg * psExtraArg)1812 CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
1813                               int nXOff, int nYOff, int nXSize, int nYSize,
1814                               void * pData, int nBufXSize, int nBufYSize,
1815                               GDALDataType eBufType,
1816                               int nBandCount, int *panBandMap,
1817                               GSpacing nPixelSpace, GSpacing nLineSpace,
1818                               GSpacing nBandSpace,
1819                               GDALRasterIOExtraArg* psExtraArg )
1820 {
1821     // It may be valid to recurse one when dealing with a subsampled request
1822     if( m_nRecursionCounter > 1 )
1823     {
1824         CPLError(
1825             CE_Failure, CPLE_AppDefined,
1826             "VRTDataset::IRasterIO() called recursively on the "
1827             "same dataset. It looks like the VRT is referencing itself." );
1828         return CE_Failure;
1829     }
1830 
1831     m_nRecursionCounter ++;
1832 
1833     bool bLocalCompatibleForDatasetIO = CPL_TO_BOOL(CheckCompatibleForDatasetIO());
1834     if( bLocalCompatibleForDatasetIO && eRWFlag == GF_Read &&
1835         (nBufXSize < nXSize || nBufYSize < nYSize) && m_apoOverviews.empty() )
1836     {
1837         int bTried = FALSE;
1838         const CPLErr eErr = TryOverviewRasterIO( eRWFlag,
1839                                                  nXOff, nYOff, nXSize, nYSize,
1840                                                  pData, nBufXSize, nBufYSize,
1841                                                  eBufType,
1842                                                  nBandCount, panBandMap,
1843                                                  nPixelSpace, nLineSpace,
1844                                                  nBandSpace,
1845                                                  psExtraArg,
1846                                                  &bTried );
1847 
1848         if( bTried )
1849         {
1850             m_nRecursionCounter --;
1851             return eErr;
1852         }
1853 
1854         for(int iBand = 0; iBand < nBands; iBand++)
1855         {
1856             VRTSourcedRasterBand* poBand
1857                 = static_cast<VRTSourcedRasterBand *>( papoBands[iBand] );
1858 
1859             // If there are overviews, let VRTSourcedRasterBand::IRasterIO()
1860             // do the job.
1861             if( poBand->GetOverviewCount() != 0 )
1862             {
1863                 bLocalCompatibleForDatasetIO = false;
1864                 break;
1865             }
1866         }
1867     }
1868 
1869     // If resampling with non-nearest neighbour, we need to be careful
1870     // if the VRT band exposes a nodata value, but the sources do not have it
1871     if( bLocalCompatibleForDatasetIO && eRWFlag == GF_Read &&
1872         (nXSize != nBufXSize || nYSize != nBufYSize) &&
1873         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour )
1874     {
1875         for( int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++ )
1876         {
1877             VRTSourcedRasterBand* poBand =
1878                 static_cast<VRTSourcedRasterBand*>(
1879                     GetRasterBand(panBandMap[iBandIndex]) );
1880             int bHasNoData = FALSE;
1881             const double dfNoDataValue = poBand->GetNoDataValue(&bHasNoData);
1882             if( bHasNoData )
1883             {
1884                 for( int i = 0; i < poBand->nSources; i++ )
1885                 {
1886                     VRTSimpleSource* poSource
1887                         = static_cast<VRTSimpleSource *>(
1888                             poBand->papoSources[i] );
1889                     int bSrcHasNoData = FALSE;
1890                     const double dfSrcNoData
1891                         = poSource->GetBand()->GetNoDataValue(&bSrcHasNoData);
1892                     if( !bSrcHasNoData || dfSrcNoData != dfNoDataValue )
1893                     {
1894                         bLocalCompatibleForDatasetIO = false;
1895                         break;
1896                     }
1897                 }
1898                 if( !bLocalCompatibleForDatasetIO )
1899                     break;
1900             }
1901         }
1902     }
1903 
1904     if( bLocalCompatibleForDatasetIO && eRWFlag == GF_Read )
1905     {
1906 
1907         // Make sure the expand the last band before using them below
1908         ExpandProxyBands();
1909 
1910         for(int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++)
1911         {
1912             VRTSourcedRasterBand* poBand
1913                 = static_cast<VRTSourcedRasterBand *>(
1914                     GetRasterBand( panBandMap[iBandIndex] ) );
1915 
1916             /* Dirty little trick to initialize the buffer without doing */
1917             /* any real I/O */
1918             const int nSavedSources = poBand->nSources;
1919             poBand->nSources = 0;
1920 
1921             GByte *pabyBandData
1922                 = static_cast<GByte *>( pData ) + iBandIndex * nBandSpace;
1923 
1924             poBand->IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize,
1925                                 pabyBandData, nBufXSize, nBufYSize,
1926                                 eBufType,
1927                                 nPixelSpace, nLineSpace, psExtraArg);
1928 
1929             poBand->nSources = nSavedSources;
1930         }
1931 
1932         CPLErr eErr = CE_None;
1933         GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
1934         void *pProgressDataGlobal = psExtraArg->pProgressData;
1935 
1936         // Use the last band, because when sources reference a GDALProxyDataset,
1937         // they don't necessary instantiate all underlying rasterbands.
1938         VRTSourcedRasterBand* poBand = static_cast<VRTSourcedRasterBand *>(
1939             papoBands[nBands - 1] );
1940         for( int iSource = 0;
1941              eErr == CE_None && iSource < poBand->nSources;
1942              iSource++ )
1943         {
1944             psExtraArg->pfnProgress = GDALScaledProgress;
1945             psExtraArg->pProgressData =
1946                 GDALCreateScaledProgress(
1947                     1.0 * iSource / poBand->nSources,
1948                     1.0 * (iSource + 1) / poBand->nSources,
1949                     pfnProgressGlobal,
1950                     pProgressDataGlobal );
1951 
1952             VRTSimpleSource* poSource = static_cast<VRTSimpleSource *>(
1953                 poBand->papoSources[iSource] );
1954 
1955             eErr = poSource->DatasetRasterIO( poBand->GetRasterDataType(),
1956                                               nXOff, nYOff, nXSize, nYSize,
1957                                               pData, nBufXSize, nBufYSize,
1958                                               eBufType,
1959                                               nBandCount, panBandMap,
1960                                               nPixelSpace, nLineSpace,
1961                                               nBandSpace,
1962                                               psExtraArg );
1963 
1964             GDALDestroyScaledProgress( psExtraArg->pProgressData );
1965         }
1966 
1967         psExtraArg->pfnProgress = pfnProgressGlobal;
1968         psExtraArg->pProgressData = pProgressDataGlobal;
1969 
1970         m_nRecursionCounter --;
1971         return eErr;
1972     }
1973 
1974     CPLErr eErr;
1975     if( eRWFlag == GF_Read &&
1976         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
1977         nBufXSize < nXSize && nBufYSize < nYSize && nBandCount > 1 )
1978     {
1979         // Force going through VRTSourcedRasterBand::IRasterIO(), otherwise
1980         // GDALDataset::IRasterIOResampled() would be used without source
1981         // overviews being potentially used.
1982         eErr = GDALDataset::BandBasedRasterIO(
1983                                    eRWFlag, nXOff, nYOff, nXSize, nYSize,
1984                                    pData, nBufXSize, nBufYSize,
1985                                    eBufType,
1986                                    nBandCount, panBandMap,
1987                                    nPixelSpace, nLineSpace, nBandSpace,
1988                                    psExtraArg );
1989     }
1990     else
1991     {
1992         eErr = GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
1993                                     pData, nBufXSize, nBufYSize,
1994                                     eBufType,
1995                                     nBandCount, panBandMap,
1996                                     nPixelSpace, nLineSpace, nBandSpace,
1997                                     psExtraArg );
1998     }
1999     m_nRecursionCounter --;
2000     return eErr;
2001 }
2002 
2003 /************************************************************************/
2004 /*                  UnsetPreservedRelativeFilenames()                   */
2005 /************************************************************************/
2006 
UnsetPreservedRelativeFilenames()2007 void VRTDataset::UnsetPreservedRelativeFilenames()
2008 {
2009     for(int iBand = 0; iBand < nBands; iBand++)
2010     {
2011         if( !static_cast<VRTRasterBand *>(
2012                papoBands[iBand] )->IsSourcedRasterBand() )
2013             continue;
2014 
2015         VRTSourcedRasterBand* poBand
2016             = static_cast<VRTSourcedRasterBand *>( papoBands[iBand] );
2017         const int nSources = poBand->nSources;
2018         VRTSource** papoSources = poBand->papoSources;
2019         for(int iSource = 0; iSource < nSources; iSource++)
2020         {
2021             if( !papoSources[iSource]->IsSimpleSource() )
2022                 continue;
2023 
2024             VRTSimpleSource* poSource = static_cast<VRTSimpleSource *>(
2025                 papoSources[iSource] );
2026             poSource->UnsetPreservedRelativeFilenames();
2027         }
2028     }
2029 }
2030 
2031 /************************************************************************/
2032 /*                        BuildVirtualOverviews()                       */
2033 /************************************************************************/
2034 
CheckBandForOverview(GDALRasterBand * poBand,GDALRasterBand * & poFirstBand,int & nOverviews,std::vector<GDALDataset * > & apoOverviewsBak)2035 static bool CheckBandForOverview(GDALRasterBand* poBand,
2036                                  GDALRasterBand*& poFirstBand,
2037                                  int& nOverviews,
2038                                  std::vector<GDALDataset*>& apoOverviewsBak)
2039 {
2040     if( !cpl::down_cast<VRTRasterBand *>(poBand)->IsSourcedRasterBand())
2041         return false;
2042 
2043     VRTSourcedRasterBand* poVRTBand
2044         = cpl::down_cast<VRTSourcedRasterBand *>(poBand);
2045     if( poVRTBand->nSources != 1 )
2046         return false;
2047     if( !poVRTBand->papoSources[0]->IsSimpleSource() )
2048         return false;
2049 
2050     VRTSimpleSource* poSource
2051         = cpl::down_cast<VRTSimpleSource *>( poVRTBand->papoSources[0] );
2052     if( !EQUAL(poSource->GetType(), "SimpleSource") &&
2053         !EQUAL(poSource->GetType(), "ComplexSource") )
2054         return false;
2055     GDALRasterBand* poSrcBand =
2056         poBand->GetBand() == 0 ? poSource->GetMaskBandMainBand() : poSource->GetBand();
2057     if( poSrcBand == nullptr )
2058         return false;
2059 
2060     // To prevent recursion
2061     apoOverviewsBak.push_back(nullptr);
2062     const int nOvrCount = poSrcBand->GetOverviewCount();
2063     apoOverviewsBak.resize(0);
2064 
2065     if( nOvrCount == 0 )
2066         return false;
2067     if( poFirstBand == nullptr )
2068     {
2069         if( poSrcBand->GetXSize() == 0 || poSrcBand->GetYSize() == 0 )
2070             return false;
2071         poFirstBand = poSrcBand;
2072         nOverviews = nOvrCount;
2073     }
2074     else if( nOvrCount < nOverviews )
2075         nOverviews = nOvrCount;
2076     return true;
2077 }
2078 
2079 
BuildVirtualOverviews()2080 void VRTDataset::BuildVirtualOverviews()
2081 {
2082     // Currently we expose virtual overviews only if the dataset is made of
2083     // a single SimpleSource/ComplexSource, in each band.
2084     // And if the underlying sources have overviews of course
2085     if( !m_apoOverviews.empty() || !m_apoOverviewsBak.empty() )
2086         return;
2087 
2088     int nOverviews = 0;
2089     GDALRasterBand* poFirstBand = nullptr;
2090 
2091     for( int iBand = 0; iBand < nBands; iBand++ )
2092     {
2093         if( !CheckBandForOverview(papoBands[iBand], poFirstBand, nOverviews, m_apoOverviewsBak) )
2094             return;
2095     }
2096 
2097     if( m_poMaskBand )
2098     {
2099         if( !CheckBandForOverview(m_poMaskBand, poFirstBand, nOverviews, m_apoOverviewsBak) )
2100             return;
2101     }
2102     if( poFirstBand == nullptr )
2103     {
2104         // to make cppcheck happy
2105         CPLAssert(false);
2106         return;
2107     }
2108 
2109     VRTSourcedRasterBand* l_poVRTBand
2110         = cpl::down_cast<VRTSourcedRasterBand *>(papoBands[0]);
2111     VRTSimpleSource* poSource
2112         = cpl::down_cast<VRTSimpleSource *>( l_poVRTBand->papoSources[0] );
2113     const double dfDstToSrcXRatio = poSource->m_dfDstXSize / poSource->m_dfSrcXSize;
2114     const double dfDstToSrcYRatio = poSource->m_dfDstYSize / poSource->m_dfSrcYSize;
2115 
2116     for( int j = 0; j < nOverviews; j++)
2117     {
2118         auto poOvrBand = poFirstBand->GetOverview(j);
2119         if( !poOvrBand )
2120             return;
2121         const double dfXRatio = static_cast<double>(
2122             poOvrBand->GetXSize() ) / poFirstBand->GetXSize();
2123         const double dfYRatio = static_cast<double>(
2124             poOvrBand->GetYSize() ) / poFirstBand->GetYSize();
2125         if( dfXRatio >= dfDstToSrcXRatio ||
2126             dfYRatio >= dfDstToSrcYRatio )
2127         {
2128             continue;
2129         }
2130         const int nOvrXSize = static_cast<int>(0.5 + nRasterXSize * dfXRatio);
2131         const int nOvrYSize = static_cast<int>(0.5 + nRasterYSize * dfYRatio);
2132         if( nOvrXSize < 128 || nOvrYSize < 128 )
2133             break;
2134         VRTDataset* poOvrVDS = new VRTDataset(nOvrXSize, nOvrYSize);
2135         m_apoOverviews.push_back(poOvrVDS);
2136 
2137         const auto CreateOverviewBand =
2138             [&poOvrVDS, nOvrXSize, nOvrYSize, dfXRatio, dfYRatio]
2139             (VRTSourcedRasterBand* poVRTBand)
2140         {
2141             VRTSourcedRasterBand* poOvrVRTBand = new VRTSourcedRasterBand(
2142                 poOvrVDS,
2143                 poVRTBand->GetBand(),
2144                 poVRTBand->GetRasterDataType(),
2145                 nOvrXSize, nOvrYSize);
2146             poOvrVRTBand->CopyCommonInfoFrom(poVRTBand);
2147             poOvrVRTBand->m_bNoDataValueSet = poVRTBand->m_bNoDataValueSet;
2148             poOvrVRTBand->m_dfNoDataValue = poVRTBand->m_dfNoDataValue;
2149             poOvrVRTBand->m_bHideNoDataValue = poVRTBand->m_bHideNoDataValue;
2150 
2151             VRTSimpleSource* poSrcSource = cpl::down_cast<VRTSimpleSource *>(
2152                 poVRTBand->papoSources[0] );
2153             VRTSimpleSource* poNewSource = nullptr;
2154             if( EQUAL(poSrcSource->GetType(), "SimpleSource") )
2155             {
2156                 poNewSource =
2157                     new VRTSimpleSource(poSrcSource, dfXRatio, dfYRatio);
2158             }
2159             else if( EQUAL(poSrcSource->GetType(), "ComplexSource") )
2160             {
2161               poNewSource = new VRTComplexSource(
2162                   cpl::down_cast<VRTComplexSource *>( poSrcSource ),
2163                   dfXRatio, dfYRatio );
2164             }
2165             else
2166             {
2167                 CPLAssert(false);
2168             }
2169             if( poNewSource )
2170             {
2171                 auto poNewSourceBand = poVRTBand->GetBand() == 0 ?
2172                     poNewSource->GetMaskBandMainBand() :
2173                     poNewSource->GetBand();
2174                 CPLAssert(poNewSourceBand);
2175                 auto poNewSourceBandDS = poNewSourceBand->GetDataset();
2176                 if( poNewSourceBandDS )
2177                     poNewSourceBandDS->Reference();
2178                 poOvrVRTBand->AddSource(poNewSource);
2179             }
2180 
2181             return poOvrVRTBand;
2182         };
2183 
2184         for( int i = 0; i < nBands; i++ )
2185         {
2186             VRTSourcedRasterBand* poSrcBand
2187                 = cpl::down_cast<VRTSourcedRasterBand *>(GetRasterBand(i+1));
2188             auto poOvrVRTBand = CreateOverviewBand(poSrcBand);
2189             poOvrVDS->SetBand( poOvrVDS->GetRasterCount() + 1, poOvrVRTBand );
2190 
2191         }
2192 
2193         if( m_poMaskBand )
2194         {
2195             VRTSourcedRasterBand* poSrcBand
2196                 = cpl::down_cast<VRTSourcedRasterBand *>(m_poMaskBand);
2197             auto poOvrVRTBand = CreateOverviewBand(poSrcBand);
2198             poOvrVDS->SetMaskBand(poOvrVRTBand);
2199         }
2200     }
2201 }
2202 
2203 /************************************************************************/
2204 /*                        AddVirtualOverview()                          */
2205 /************************************************************************/
2206 
AddVirtualOverview(int nOvFactor,const char * pszResampling)2207 bool VRTDataset::AddVirtualOverview(int nOvFactor, const char* pszResampling)
2208 {
2209     if( nRasterXSize / nOvFactor == 0 ||
2210         nRasterYSize / nOvFactor == 0 )
2211     {
2212         return false;
2213     }
2214 
2215     CPLStringList argv;
2216     argv.AddString("-of");
2217     argv.AddString("VRT");
2218     argv.AddString("-outsize");
2219     argv.AddString(CPLSPrintf("%d", nRasterXSize / nOvFactor));
2220     argv.AddString(CPLSPrintf("%d", nRasterYSize / nOvFactor));
2221     argv.AddString("-r");
2222     argv.AddString(pszResampling);
2223 
2224     GDALTranslateOptions* psOptions = GDALTranslateOptionsNew(argv.List(), nullptr);
2225 
2226     // Add a dummy overview so that BuildVirtualOverviews() doesn't trigger
2227     m_apoOverviews.push_back(nullptr);
2228     CPLAssert(m_bCanTakeRef);
2229     m_bCanTakeRef = false; // we don't want hOverviewDS to take a reference on ourselves.
2230     GDALDatasetH hOverviewDS = GDALTranslate("", GDALDataset::ToHandle(this),
2231                                     psOptions, nullptr);
2232     m_bCanTakeRef = true;
2233     m_apoOverviews.resize(m_apoOverviews.size() - 1);
2234 
2235     GDALTranslateOptionsFree( psOptions );
2236     if( hOverviewDS == nullptr )
2237         return false;
2238 
2239     m_anOverviewFactors.push_back(nOvFactor);
2240     m_apoOverviews.push_back(GDALDataset::FromHandle(hOverviewDS));
2241     return true;
2242 }
2243 
2244 /************************************************************************/
2245 /*                          IBuildOverviews()                           */
2246 /************************************************************************/
2247 
2248 CPLErr
IBuildOverviews(const char * pszResampling,int nOverviews,int * panOverviewList,int nListBands,int * panBandList,GDALProgressFunc pfnProgress,void * pProgressData)2249 VRTDataset::IBuildOverviews( const char *pszResampling,
2250                              int nOverviews,
2251                              int *panOverviewList,
2252                              int nListBands,
2253                              int *panBandList,
2254                              GDALProgressFunc pfnProgress,
2255                              void * pProgressData )
2256 {
2257     if( CPLTestBool(CPLGetConfigOption("VRT_VIRTUAL_OVERVIEWS", "NO")) )
2258     {
2259         SetNeedsFlush();
2260         if( nOverviews == 0 ||
2261             (!m_apoOverviews.empty() && m_anOverviewFactors.empty()) )
2262         {
2263             m_anOverviewFactors.clear();
2264             m_apoOverviewsBak.insert(m_apoOverviewsBak.end(),
2265                                      m_apoOverviews.begin(),
2266                                      m_apoOverviews.end());
2267             m_apoOverviews.clear();
2268         }
2269         m_osOverviewResampling = pszResampling;
2270         for(int i = 0; i < nOverviews; i++ )
2271         {
2272             if( std::find(m_anOverviewFactors.begin(),
2273                           m_anOverviewFactors.end(),
2274                           panOverviewList[i]) == m_anOverviewFactors.end() )
2275             {
2276                 AddVirtualOverview(panOverviewList[i], pszResampling);
2277             }
2278         }
2279         return CE_None;
2280     }
2281 
2282     if( !oOvManager.IsInitialized() )
2283     {
2284         const char* pszDesc = GetDescription();
2285         if( pszDesc[0] )
2286         {
2287             oOvManager.Initialize( this, pszDesc );
2288         }
2289     }
2290 
2291     // Make implicit overviews invisible, but do not destroy them in case they
2292     // are already used.  Should the client do that?  Behavior might undefined
2293     // in GDAL API?
2294     if( !m_apoOverviews.empty() )
2295     {
2296         m_apoOverviewsBak.insert(m_apoOverviewsBak.end(),
2297                                  m_apoOverviews.begin(),
2298                                  m_apoOverviews.end());
2299         m_apoOverviews.clear();
2300     }
2301     else
2302     {
2303         // Add a dummy overview so that GDALDataset::IBuildOverviews()
2304         // doesn't manage to get a virtual implicit overview.
2305         m_apoOverviews.push_back(nullptr);
2306     }
2307 
2308     CPLErr eErr = GDALDataset::IBuildOverviews( pszResampling,
2309                                          nOverviews,
2310                                          panOverviewList,
2311                                          nListBands,
2312                                          panBandList,
2313                                          pfnProgress,
2314                                          pProgressData );
2315 
2316     m_apoOverviews.clear();
2317     return eErr;
2318 }
2319 
2320 /*! @endcond */
2321