LCOV - code coverage report
Current view: directory - frmts/vrt - vrtdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 523 443 84.7 %
Date: 2013-03-30 Functions: 35 32 91.4 %

       1                 : /******************************************************************************
       2                 :  * $Id: vrtdataset.cpp 25769 2013-03-19 07:50:17Z antonio $
       3                 :  *
       4                 :  * Project:  Virtual GDAL Datasets
       5                 :  * Purpose:  Implementation of VRTDataset
       6                 :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.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                 : #include "cpl_string.h"
      32                 : #include "cpl_minixml.h"
      33                 : #include "ogr_spatialref.h"
      34                 : 
      35                 : CPL_CVSID("$Id: vrtdataset.cpp 25769 2013-03-19 07:50:17Z antonio $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                            VRTDataset()                             */
      39                 : /************************************************************************/
      40                 : 
      41            1016 : VRTDataset::VRTDataset( int nXSize, int nYSize )
      42                 : 
      43                 : {
      44            1016 :     nRasterXSize = nXSize;
      45            1016 :     nRasterYSize = nYSize;
      46            1016 :     pszProjection = NULL;
      47                 : 
      48            1016 :     bNeedsFlush = FALSE;
      49            1016 :     bWritable = TRUE;
      50                 : 
      51            1016 :     bGeoTransformSet = FALSE;
      52            1016 :     adfGeoTransform[0] = 0.0;
      53            1016 :     adfGeoTransform[1] = 1.0;
      54            1016 :     adfGeoTransform[2] = 0.0;
      55            1016 :     adfGeoTransform[3] = 0.0;
      56            1016 :     adfGeoTransform[4] = 0.0;
      57            1016 :     adfGeoTransform[5] = 1.0;
      58                 : 
      59            1016 :     nGCPCount = 0;
      60            1016 :     pasGCPList = NULL;
      61            1016 :     pszGCPProjection = CPLStrdup("");
      62                 : 
      63            1016 :     pszVRTPath = NULL;
      64                 : 
      65            1016 :     poMaskBand = NULL;
      66                 :     
      67            1016 :     GDALRegister_VRT();
      68            1016 :     poDriver = (GDALDriver *) GDALGetDriverByName( "VRT" );
      69                 : 
      70            1016 :     bCompatibleForDatasetIO = -1;
      71            1016 : }
      72                 : 
      73                 : /************************************************************************/
      74                 : /*                              VRTCreate()                             */
      75                 : /************************************************************************/
      76                 : 
      77                 : /**
      78                 :  * @see VRTDataset::VRTDataset()
      79                 :  */
      80                 : 
      81              68 : VRTDatasetH CPL_STDCALL VRTCreate(int nXSize, int nYSize)
      82                 : 
      83                 : {
      84              68 :     return ( new VRTDataset(nXSize, nYSize) );
      85                 : }
      86                 : 
      87                 : /************************************************************************/
      88                 : /*                            ~VRTDataset()                            */
      89                 : /************************************************************************/
      90                 : 
      91            1016 : VRTDataset::~VRTDataset()
      92                 : 
      93                 : {
      94            1016 :     FlushCache();
      95            1016 :     CPLFree( pszProjection );
      96                 : 
      97            1016 :     CPLFree( pszGCPProjection );
      98            1016 :     if( nGCPCount > 0 )
      99                 :     {
     100              25 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     101              25 :         CPLFree( pasGCPList );
     102                 :     }
     103            1016 :     CPLFree( pszVRTPath );
     104                 : 
     105            1016 :     delete poMaskBand;
     106            1016 : }
     107                 : 
     108                 : /************************************************************************/
     109                 : /*                             FlushCache()                             */
     110                 : /************************************************************************/
     111                 : 
     112            1251 : void VRTDataset::FlushCache()
     113                 : 
     114                 : {
     115            1251 :     GDALDataset::FlushCache();
     116                 : 
     117            1251 :     if( !bNeedsFlush || bWritable == FALSE)
     118             523 :         return;
     119                 : 
     120             728 :     bNeedsFlush = FALSE;
     121                 : 
     122                 :     // We don't write to disk if there is no filename.  This is a 
     123                 :     // memory only dataset.
     124             883 :     if( strlen(GetDescription()) == 0 
     125             155 :         || EQUALN(GetDescription(),"<VRTDataset",11) )
     126             573 :         return;
     127                 : 
     128                 :     /* -------------------------------------------------------------------- */
     129                 :     /*      Create the output file.                                         */
     130                 :     /* -------------------------------------------------------------------- */
     131                 :     VSILFILE *fpVRT;
     132                 : 
     133             155 :     fpVRT = VSIFOpenL( GetDescription(), "w" );
     134             155 :     if( fpVRT == NULL )
     135                 :     {
     136                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     137               1 :                   "Failed to write .vrt file in FlushCache()." );
     138               1 :         return;
     139                 :     }
     140                 : 
     141                 :     /* -------------------------------------------------------------------- */
     142                 :     /*      Convert tree to a single block of XML text.                     */
     143                 :     /* -------------------------------------------------------------------- */
     144             154 :     char *pszVRTPath = CPLStrdup(CPLGetPath(GetDescription()));
     145             154 :     CPLXMLNode *psDSTree = SerializeToXML( pszVRTPath );
     146                 :     char *pszXML;
     147                 : 
     148             154 :     pszXML = CPLSerializeXMLTree( psDSTree );
     149                 : 
     150             154 :     CPLDestroyXMLNode( psDSTree );
     151                 : 
     152             154 :     CPLFree( pszVRTPath );
     153                 : 
     154                 :     /* -------------------------------------------------------------------- */
     155                 :     /*      Write to disk.                                                  */
     156                 :     /* -------------------------------------------------------------------- */
     157             154 :     VSIFWriteL( pszXML, 1, strlen(pszXML), fpVRT );
     158             154 :     VSIFCloseL( fpVRT );
     159                 : 
     160             154 :     CPLFree( pszXML );
     161                 : }
     162                 : 
     163                 : /************************************************************************/
     164                 : /*                            VRTFlushCache()                           */
     165                 : /************************************************************************/
     166                 : 
     167                 : /**
     168                 :  * @see VRTDataset::FlushCache()
     169                 :  */
     170                 : 
     171               0 : void CPL_STDCALL VRTFlushCache( VRTDatasetH hDataset )
     172                 : {
     173               0 :     VALIDATE_POINTER0( hDataset, "VRTFlushCache" );
     174                 : 
     175               0 :     ((VRTDataset *)hDataset)->FlushCache();
     176                 : }
     177                 : 
     178                 : /************************************************************************/
     179                 : /*                           SerializeToXML()                           */
     180                 : /************************************************************************/
     181                 : 
     182             162 : CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPath )
     183                 : 
     184                 : {
     185                 :     /* -------------------------------------------------------------------- */
     186                 :     /*      Setup root node and attributes.                                 */
     187                 :     /* -------------------------------------------------------------------- */
     188             162 :     CPLXMLNode *psDSTree = NULL;
     189             162 :     CPLXMLNode *psMD = NULL;
     190                 :     char       szNumber[128];
     191                 : 
     192             162 :     psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTDataset" );
     193                 : 
     194             162 :     sprintf( szNumber, "%d", GetRasterXSize() );
     195             162 :     CPLSetXMLValue( psDSTree, "#rasterXSize", szNumber );
     196                 : 
     197             162 :     sprintf( szNumber, "%d", GetRasterYSize() );
     198             162 :     CPLSetXMLValue( psDSTree, "#rasterYSize", szNumber );
     199                 : 
     200                 :  /* -------------------------------------------------------------------- */
     201                 :  /*      SRS                                                             */
     202                 :  /* -------------------------------------------------------------------- */
     203             162 :     if( pszProjection != NULL && strlen(pszProjection) > 0 )
     204             143 :         CPLSetXMLValue( psDSTree, "SRS", pszProjection );
     205                 : 
     206                 :  /* -------------------------------------------------------------------- */
     207                 :  /*      Geotransform.                                                   */
     208                 :  /* -------------------------------------------------------------------- */
     209             162 :     if( bGeoTransformSet )
     210                 :     {
     211                 :         CPLSetXMLValue( psDSTree, "GeoTransform", 
     212                 :                         CPLSPrintf( "%24.16e,%24.16e,%24.16e,%24.16e,%24.16e,%24.16e",
     213                 :                                     adfGeoTransform[0],
     214                 :                                     adfGeoTransform[1],
     215                 :                                     adfGeoTransform[2],
     216                 :                                     adfGeoTransform[3],
     217                 :                                     adfGeoTransform[4],
     218             149 :                                     adfGeoTransform[5] ) );
     219                 :     }
     220                 : 
     221                 : /* -------------------------------------------------------------------- */
     222                 : /*      Metadata                                                        */
     223                 : /* -------------------------------------------------------------------- */
     224             162 :     psMD = oMDMD.Serialize();
     225             162 :     if( psMD != NULL )
     226             109 :         CPLAddXMLChild( psDSTree, psMD );
     227                 : 
     228                 :  /* -------------------------------------------------------------------- */
     229                 :  /*      GCPs                                                            */
     230                 :  /* -------------------------------------------------------------------- */
     231             162 :     if( nGCPCount > 0 )
     232                 :     {
     233                 :         CPLXMLNode *psGCPList = CPLCreateXMLNode( psDSTree, CXT_Element, 
     234               2 :                                                   "GCPList" );
     235                 : 
     236               2 :         CPLXMLNode* psLastChild = NULL;
     237                 : 
     238               2 :         if( pszGCPProjection != NULL && strlen(pszGCPProjection) > 0 )
     239                 :         {
     240               1 :             CPLSetXMLValue( psGCPList, "#Projection", pszGCPProjection );
     241               1 :             psLastChild = psGCPList->psChild;
     242                 :         }
     243                 : 
     244               8 :         for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
     245                 :         {
     246                 :             CPLXMLNode *psXMLGCP;
     247               6 :             GDAL_GCP *psGCP = pasGCPList + iGCP;
     248                 : 
     249               6 :             psXMLGCP = CPLCreateXMLNode( NULL, CXT_Element, "GCP" );
     250                 : 
     251               6 :             if( psLastChild == NULL )
     252               1 :                 psGCPList->psChild = psXMLGCP;
     253                 :             else
     254               5 :                 psLastChild->psNext = psXMLGCP;
     255               6 :             psLastChild = psXMLGCP;
     256                 : 
     257               6 :             CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId );
     258                 : 
     259               6 :             if( psGCP->pszInfo != NULL && strlen(psGCP->pszInfo) > 0 )
     260               0 :                 CPLSetXMLValue( psXMLGCP, "Info", psGCP->pszInfo );
     261                 : 
     262                 :             CPLSetXMLValue( psXMLGCP, "#Pixel", 
     263               6 :                             CPLSPrintf( "%.4f", psGCP->dfGCPPixel ) );
     264                 : 
     265                 :             CPLSetXMLValue( psXMLGCP, "#Line", 
     266               6 :                             CPLSPrintf( "%.4f", psGCP->dfGCPLine ) );
     267                 : 
     268                 :             CPLSetXMLValue( psXMLGCP, "#X", 
     269               6 :                             CPLSPrintf( "%.12E", psGCP->dfGCPX ) );
     270                 : 
     271                 :             CPLSetXMLValue( psXMLGCP, "#Y", 
     272               6 :                             CPLSPrintf( "%.12E", psGCP->dfGCPY ) );
     273                 : 
     274               6 :             if( psGCP->dfGCPZ != 0.0 )
     275                 :                 CPLSetXMLValue( psXMLGCP, "#GCPZ", 
     276               0 :                                 CPLSPrintf( "%.12E", psGCP->dfGCPZ ) );
     277                 :         }
     278                 :     }
     279                 : 
     280                 :     /* -------------------------------------------------------------------- */
     281                 :     /*      Serialize bands.                                                */
     282                 :     /* -------------------------------------------------------------------- */
     283             400 :     for( int iBand = 0; iBand < nBands; iBand++ )
     284                 :     {
     285                 :         CPLXMLNode *psBandTree = 
     286             238 :             ((VRTRasterBand *) papoBands[iBand])->SerializeToXML(pszVRTPath);
     287                 : 
     288             238 :         if( psBandTree != NULL )
     289             238 :             CPLAddXMLChild( psDSTree, psBandTree );
     290                 :     }
     291                 : 
     292                 :     /* -------------------------------------------------------------------- */
     293                 :     /*      Serialize dataset mask band.                                    */
     294                 :     /* -------------------------------------------------------------------- */
     295             162 :     if (poMaskBand)
     296                 :     {
     297                 :         CPLXMLNode *psBandTree =
     298               6 :             poMaskBand->SerializeToXML(pszVRTPath);
     299                 : 
     300               6 :         if( psBandTree != NULL )
     301                 :         {
     302                 :             CPLXMLNode *psMaskBandElement = CPLCreateXMLNode( psDSTree, CXT_Element, 
     303               6 :                                                               "MaskBand" );
     304               6 :             CPLAddXMLChild( psMaskBandElement, psBandTree );
     305                 :         }
     306                 :     }
     307                 : 
     308             162 :     return psDSTree;
     309                 : }
     310                 : 
     311                 : /************************************************************************/
     312                 : /*                          VRTSerializeToXML()                         */
     313                 : /************************************************************************/
     314                 : 
     315                 : /**
     316                 :  * @see VRTDataset::SerializeToXML()
     317                 :  */
     318                 : 
     319               0 : CPLXMLNode * CPL_STDCALL VRTSerializeToXML( VRTDatasetH hDataset,
     320                 :                                             const char *pszVRTPath )
     321                 : {
     322               0 :     VALIDATE_POINTER1( hDataset, "VRTSerializeToXML", NULL );
     323                 : 
     324               0 :     return ((VRTDataset *)hDataset)->SerializeToXML(pszVRTPath);
     325                 : }
     326                 : 
     327                 : /************************************************************************/
     328                 : /*                              XMLInit()                               */
     329                 : /************************************************************************/
     330                 : 
     331             384 : CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
     332                 : 
     333                 : {
     334             384 :     if( pszVRTPath != NULL )
     335             370 :         this->pszVRTPath = CPLStrdup(pszVRTPath);
     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Check for an SRS node.                                          */
     339                 : /* -------------------------------------------------------------------- */
     340             384 :     if( strlen(CPLGetXMLValue(psTree, "SRS", "")) > 0 )
     341                 :     {
     342             221 :         OGRSpatialReference oSRS;
     343                 : 
     344             221 :         CPLFree( pszProjection );
     345             221 :         pszProjection = NULL;
     346                 : 
     347             221 :         if( oSRS.SetFromUserInput( CPLGetXMLValue(psTree, "SRS", "") )
     348                 :             == OGRERR_NONE )
     349             220 :             oSRS.exportToWkt( &pszProjection );
     350                 :     }
     351                 : 
     352                 : /* -------------------------------------------------------------------- */
     353                 : /*      Check for a GeoTransform node.                                  */
     354                 : /* -------------------------------------------------------------------- */
     355             384 :     if( strlen(CPLGetXMLValue(psTree, "GeoTransform", "")) > 0 )
     356                 :     {
     357             232 :         const char *pszGT = CPLGetXMLValue(psTree, "GeoTransform", "");
     358                 :         char  **papszTokens;
     359                 : 
     360             232 :         papszTokens = CSLTokenizeStringComplex( pszGT, ",", FALSE, FALSE );
     361             232 :         if( CSLCount(papszTokens) != 6 )
     362                 :         {
     363                 :             CPLError( CE_Warning, CPLE_AppDefined,
     364               0 :                       "GeoTransform node does not have expected six values.");
     365                 :         }
     366                 :         else
     367                 :         {
     368            1624 :             for( int iTA = 0; iTA < 6; iTA++ )
     369            1392 :                 adfGeoTransform[iTA] = atof(papszTokens[iTA]);
     370             232 :             bGeoTransformSet = TRUE;
     371                 :         }
     372                 : 
     373             232 :         CSLDestroy( papszTokens );
     374                 :     }
     375                 : 
     376                 : /* -------------------------------------------------------------------- */
     377                 : /*      Check for GCPs.                                                 */
     378                 : /* -------------------------------------------------------------------- */
     379             384 :     CPLXMLNode *psGCPList = CPLGetXMLNode( psTree, "GCPList" );
     380                 : 
     381             384 :     if( psGCPList != NULL )
     382                 :     {
     383                 :         CPLXMLNode *psXMLGCP;
     384              21 :         OGRSpatialReference oSRS;
     385              21 :         const char *pszRawProj = CPLGetXMLValue(psGCPList, "Projection", "");
     386                 : 
     387              21 :         CPLFree( pszGCPProjection );
     388                 : 
     389              21 :         if( strlen(pszRawProj) > 0 
     390                 :             && oSRS.SetFromUserInput( pszRawProj ) == OGRERR_NONE )
     391              16 :             oSRS.exportToWkt( &pszGCPProjection );
     392                 :         else
     393               5 :             pszGCPProjection = CPLStrdup("");
     394                 : 
     395                 :         // Count GCPs.
     396              21 :         int  nGCPMax = 0;
     397                 :          
     398             122 :         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
     399                 :              psXMLGCP = psXMLGCP->psNext )
     400             101 :             nGCPMax++;
     401                 :          
     402              21 :         pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
     403                 :          
     404             122 :         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
     405                 :              psXMLGCP = psXMLGCP->psNext )
     406                 :         {
     407             101 :             GDAL_GCP *psGCP = pasGCPList + nGCPCount;
     408                 : 
     409             101 :             if( !EQUAL(psXMLGCP->pszValue,"GCP") || 
     410                 :                 psXMLGCP->eType != CXT_Element )
     411              18 :                 continue;
     412                 :              
     413              83 :             GDALInitGCPs( 1, psGCP );
     414                 :              
     415              83 :             CPLFree( psGCP->pszId );
     416              83 :             psGCP->pszId = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Id",""));
     417                 :              
     418              83 :             CPLFree( psGCP->pszInfo );
     419              83 :             psGCP->pszInfo = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Info",""));
     420                 :              
     421              83 :             psGCP->dfGCPPixel = atof(CPLGetXMLValue(psXMLGCP,"Pixel","0.0"));
     422              83 :             psGCP->dfGCPLine = atof(CPLGetXMLValue(psXMLGCP,"Line","0.0"));
     423                 :              
     424              83 :             psGCP->dfGCPX = atof(CPLGetXMLValue(psXMLGCP,"X","0.0"));
     425              83 :             psGCP->dfGCPY = atof(CPLGetXMLValue(psXMLGCP,"Y","0.0"));
     426              83 :             psGCP->dfGCPZ = atof(CPLGetXMLValue(psXMLGCP,"Z","0.0"));
     427                 : 
     428              83 :             nGCPCount++;
     429              21 :         }
     430                 :     }
     431                 :      
     432                 : /* -------------------------------------------------------------------- */
     433                 : /*      Apply any dataset level metadata.                               */
     434                 : /* -------------------------------------------------------------------- */
     435             384 :     oMDMD.XMLInit( psTree, TRUE );
     436                 : 
     437                 : /* -------------------------------------------------------------------- */
     438                 : /*      Create dataset mask band.                                       */
     439                 : /* -------------------------------------------------------------------- */
     440                 :     CPLXMLNode *psChild;
     441                 : 
     442                 :     /* Parse dataset mask band first */
     443             384 :     CPLXMLNode* psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
     444             384 :     if (psMaskBandNode)
     445              10 :         psChild = psMaskBandNode->psChild;
     446                 :     else
     447             374 :         psChild = NULL;
     448             384 :     for( ; psChild != NULL; psChild=psChild->psNext )
     449                 :     {
     450              10 :         if( psChild->eType == CXT_Element
     451                 :             && EQUAL(psChild->pszValue,"VRTRasterBand") )
     452                 :         {
     453              10 :             VRTRasterBand  *poBand = NULL;
     454                 :             const char *pszSubclass = CPLGetXMLValue( psChild, "subclass",
     455              10 :                                                       "VRTSourcedRasterBand" );
     456                 : 
     457              10 :             if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
     458              10 :                 poBand = new VRTSourcedRasterBand( this, 0 );
     459               0 :             else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
     460               0 :                 poBand = new VRTDerivedRasterBand( this, 0 );
     461               0 :             else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
     462               0 :                 poBand = new VRTRawRasterBand( this, 0 );
     463               0 :             else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") )
     464               0 :                 poBand = new VRTWarpedRasterBand( this, 0 );
     465                 :             else
     466                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     467                 :                           "VRTRasterBand of unrecognised subclass '%s'.",
     468               0 :                           pszSubclass );
     469                 : 
     470              20 :             if( poBand != NULL
     471              10 :                 && poBand->XMLInit( psChild, pszVRTPath ) == CE_None )
     472                 :             {
     473              10 :                 SetMaskBand(poBand);
     474              10 :                 break;
     475                 :             }
     476                 :             else
     477                 :             {
     478               0 :                 if( poBand )
     479               0 :                     delete poBand;
     480               0 :                 return CE_Failure;
     481                 :             }
     482                 :         }
     483                 :     }
     484                 : 
     485                 : /* -------------------------------------------------------------------- */
     486                 : /*      Create band information objects.                                */
     487                 : /* -------------------------------------------------------------------- */
     488             384 :     int   nBands = 0;
     489            2417 :     for( psChild=psTree->psChild; psChild != NULL; psChild=psChild->psNext )
     490                 :     {
     491            2134 :         if( psChild->eType == CXT_Element
     492                 :             && EQUAL(psChild->pszValue,"VRTRasterBand") )
     493                 :         {
     494             553 :             VRTRasterBand  *poBand = NULL;
     495                 :             const char *pszSubclass = CPLGetXMLValue( psChild, "subclass", 
     496             553 :                                                       "VRTSourcedRasterBand" );
     497                 : 
     498             553 :             if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
     499             460 :                 poBand = new VRTSourcedRasterBand( this, nBands+1 );
     500              93 :             else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
     501               1 :                 poBand = new VRTDerivedRasterBand( this, nBands+1 );
     502              92 :             else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
     503              11 :                 poBand = new VRTRawRasterBand( this, nBands+1 );
     504              81 :             else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") )
     505              81 :                 poBand = new VRTWarpedRasterBand( this, nBands+1 );
     506                 :             else
     507                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     508                 :                           "VRTRasterBand of unrecognised subclass '%s'.",
     509               0 :                           pszSubclass );
     510                 : 
     511            1106 :             if( poBand != NULL 
     512             553 :                 && poBand->XMLInit( psChild, pszVRTPath ) == CE_None )
     513                 :             {
     514             452 :                 SetBand( ++nBands, poBand );
     515                 :             }
     516                 :             else
     517                 :             {
     518             101 :                 if( poBand )
     519             101 :                     delete poBand; 
     520             101 :                 return CE_Failure;
     521                 :             }
     522                 :         }
     523                 :     }
     524                 :     
     525             283 :     return CE_None;
     526                 : }
     527                 : 
     528                 : /************************************************************************/
     529                 : /*                            GetGCPCount()                             */
     530                 : /************************************************************************/
     531                 : 
     532             182 : int VRTDataset::GetGCPCount()
     533                 : 
     534                 : {
     535             182 :     return nGCPCount;
     536                 : }
     537                 : 
     538                 : /************************************************************************/
     539                 : /*                          GetGCPProjection()                          */
     540                 : /************************************************************************/
     541                 : 
     542              24 : const char *VRTDataset::GetGCPProjection()
     543                 : 
     544                 : {
     545              24 :     return pszGCPProjection;
     546                 : }
     547                 : 
     548                 : /************************************************************************/
     549                 : /*                               GetGCPs()                              */
     550                 : /************************************************************************/
     551                 : 
     552              28 : const GDAL_GCP *VRTDataset::GetGCPs()
     553                 : 
     554                 : {
     555              28 :     return pasGCPList;
     556                 : }
     557                 : 
     558                 : /************************************************************************/
     559                 : /*                              SetGCPs()                               */
     560                 : /************************************************************************/
     561                 : 
     562               4 : CPLErr VRTDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
     563                 :                             const char *pszGCPProjection )
     564                 : 
     565                 : {
     566               4 :     CPLFree( this->pszGCPProjection );
     567               4 :     if( this->nGCPCount > 0 )
     568                 :     {
     569               0 :         GDALDeinitGCPs( this->nGCPCount, this->pasGCPList );
     570               0 :         CPLFree( this->pasGCPList );
     571                 :     }
     572                 : 
     573               4 :     this->pszGCPProjection = CPLStrdup(pszGCPProjection);
     574                 : 
     575               4 :     this->nGCPCount = nGCPCount;
     576                 : 
     577               4 :     this->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList );
     578                 : 
     579               4 :     this->bNeedsFlush = TRUE;
     580                 : 
     581               4 :     return CE_None;
     582                 : }
     583                 : 
     584                 : /************************************************************************/
     585                 : /*                           SetProjection()                            */
     586                 : /************************************************************************/
     587                 : 
     588             211 : CPLErr VRTDataset::SetProjection( const char *pszWKT )
     589                 : 
     590                 : {
     591             211 :     CPLFree( pszProjection );
     592             211 :     pszProjection = NULL;
     593                 : 
     594             211 :     if( pszWKT != NULL )
     595             211 :         pszProjection = CPLStrdup(pszWKT);
     596                 : 
     597             211 :     bNeedsFlush = TRUE;
     598                 : 
     599             211 :     return CE_None;
     600                 : }
     601                 : 
     602                 : /************************************************************************/
     603                 : /*                          GetProjectionRef()                          */
     604                 : /************************************************************************/
     605                 : 
     606             248 : const char *VRTDataset::GetProjectionRef()
     607                 : 
     608                 : {
     609             248 :     if( pszProjection == NULL )
     610              53 :         return "";
     611                 :     else
     612             195 :         return pszProjection;
     613                 : }
     614                 : 
     615                 : /************************************************************************/
     616                 : /*                          SetGeoTransform()                           */
     617                 : /************************************************************************/
     618                 : 
     619             211 : CPLErr VRTDataset::SetGeoTransform( double *padfGeoTransformIn )
     620                 : 
     621                 : {
     622             211 :     memcpy( adfGeoTransform, padfGeoTransformIn, sizeof(double) * 6 );
     623             211 :     bGeoTransformSet = TRUE;
     624                 : 
     625             211 :     bNeedsFlush = TRUE;
     626                 : 
     627             211 :     return CE_None;
     628                 : }
     629                 : 
     630                 : /************************************************************************/
     631                 : /*                          GetGeoTransform()                           */
     632                 : /************************************************************************/
     633                 : 
     634             286 : CPLErr VRTDataset::GetGeoTransform( double * padfGeoTransform )
     635                 : 
     636                 : {
     637             286 :     memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
     638                 : 
     639             286 :     if( bGeoTransformSet )
     640             227 :         return CE_None;
     641                 :     else
     642              59 :         return CE_Failure;
     643                 : }
     644                 : 
     645                 : /************************************************************************/
     646                 : /*                            SetMetadata()                             */
     647                 : /************************************************************************/
     648                 : 
     649             152 : CPLErr VRTDataset::SetMetadata( char **papszMetadata, 
     650                 :                                    const char *pszDomain )
     651                 : 
     652                 : {
     653             152 :     SetNeedsFlush();
     654                 : 
     655             152 :     return GDALDataset::SetMetadata( papszMetadata, pszDomain );
     656                 : }
     657                 : 
     658                 : /************************************************************************/
     659                 : /*                          SetMetadataItem()                           */
     660                 : /************************************************************************/
     661                 : 
     662             107 : CPLErr VRTDataset::SetMetadataItem( const char *pszName, 
     663                 :                                     const char *pszValue, 
     664                 :                                     const char *pszDomain )
     665                 : 
     666                 : {
     667             107 :     SetNeedsFlush();
     668                 : 
     669             107 :     return GDALDataset::SetMetadataItem( pszName, pszValue, pszDomain );
     670                 : }
     671                 : 
     672                 : /************************************************************************/
     673                 : /*                              Identify()                              */
     674                 : /************************************************************************/
     675                 : 
     676           19366 : int VRTDataset::Identify( GDALOpenInfo * poOpenInfo )
     677                 : 
     678                 : {
     679           19366 :     if( poOpenInfo->nHeaderBytes > 20
     680                 :          && strstr((const char *)poOpenInfo->pabyHeader,"<VRTDataset") != NULL )
     681             391 :         return TRUE;
     682                 : 
     683           18975 :     if( strstr(poOpenInfo->pszFilename,"<VRTDataset") != NULL )
     684              15 :         return TRUE;
     685                 : 
     686           18960 :     return FALSE;
     687                 : }
     688                 : 
     689                 : /************************************************************************/
     690                 : /*                                Open()                                */
     691                 : /************************************************************************/
     692                 : 
     693            8981 : GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
     694                 : 
     695                 : {
     696            8981 :     char *pszVRTPath = NULL;
     697                 : 
     698                 : /* -------------------------------------------------------------------- */
     699                 : /*      Does this appear to be a virtual dataset definition XML         */
     700                 : /*      file?                                                           */
     701                 : /* -------------------------------------------------------------------- */
     702            8981 :     if( !Identify( poOpenInfo ) )
     703            8596 :         return NULL;
     704                 : 
     705                 : /* -------------------------------------------------------------------- */
     706                 : /*  Try to read the whole file into memory.       */
     707                 : /* -------------------------------------------------------------------- */
     708                 :     char        *pszXML;
     709                 : 
     710             385 :     VSILFILE        *fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     711             385 :     if( fp != NULL )
     712                 :     {
     713                 :         unsigned int nLength;
     714                 :      
     715             371 :         VSIFSeekL( fp, 0, SEEK_END );
     716             371 :         nLength = (int) VSIFTellL( fp );
     717             371 :         VSIFSeekL( fp, 0, SEEK_SET );
     718                 :         
     719             371 :         nLength = MAX(0,nLength);
     720             371 :         pszXML = (char *) VSIMalloc(nLength+1);
     721                 :         
     722             371 :         if( pszXML == NULL )
     723                 :         {
     724               0 :             VSIFCloseL(fp);
     725                 :             CPLError( CE_Failure, CPLE_OutOfMemory, 
     726                 :                       "Failed to allocate %d byte buffer to hold VRT xml file.",
     727               0 :                       nLength );
     728               0 :             return NULL;
     729                 :         }
     730                 :         
     731             371 :         if( VSIFReadL( pszXML, 1, nLength, fp ) != nLength )
     732                 :         {
     733               0 :             VSIFCloseL(fp);
     734               0 :             CPLFree( pszXML );
     735                 :             CPLError( CE_Failure, CPLE_FileIO,
     736                 :                       "Failed to read %d bytes from VRT xml file.",
     737               0 :                       nLength );
     738               0 :             return NULL;
     739                 :         }
     740                 :         
     741             371 :         pszXML[nLength] = '\0';
     742                 : 
     743             371 :         char* pszCurDir = CPLGetCurrentDir();
     744             371 :         const char *currentVrtFilename = CPLProjectRelativeFilename(pszCurDir, poOpenInfo->pszFilename);
     745             371 :         CPLFree(pszCurDir);
     746                 : #if defined(HAVE_READLINK) && defined(HAVE_LSTAT)
     747                 :         VSIStatBuf statBuffer;
     748                 :         char filenameBuffer[2048];
     749                 : 
     750               4 :         while( true ) {
     751             375 :             int lstatCode = lstat( currentVrtFilename, &statBuffer );
     752             375 :             if ( lstatCode == -1 ) {
     753             104 :                 if (errno == ENOENT) {
     754                 :                     // The file could be a virtual file, let later checks handle it.
     755             104 :                     break;
     756                 :                 } else {
     757               0 :                     VSIFCloseL(fp);
     758               0 :                     CPLFree( pszXML );
     759                 :                     CPLError( CE_Failure, CPLE_FileIO,
     760                 :                               "Failed to lstat %s: %s",
     761                 :                               currentVrtFilename,
     762               0 :                               VSIStrerror(errno) );
     763               0 :                     return NULL;
     764                 :                 }
     765                 :             }
     766                 : 
     767             271 :             if ( !VSI_ISLNK(statBuffer.st_mode) ) {
     768             267 :                 break;
     769                 :             }
     770                 : 
     771               4 :             int bufferSize = readlink(currentVrtFilename, filenameBuffer, sizeof(filenameBuffer));
     772               4 :             if (bufferSize != -1) {
     773               4 :                 filenameBuffer[MIN(bufferSize, (int) sizeof(filenameBuffer) - 1)] = 0;
     774                 :                 // The filename in filenameBuffer might be a relative path from the linkfile resolve it before looping
     775               4 :                 currentVrtFilename = CPLProjectRelativeFilename(CPLGetDirname(currentVrtFilename), filenameBuffer);
     776                 :             } else {
     777               0 :                 VSIFCloseL(fp);
     778               0 :                 CPLFree( pszXML );
     779                 :                 CPLError( CE_Failure, CPLE_FileIO,
     780                 :                           "Failed to read filename from symlink %s: %s",
     781                 :                           currentVrtFilename,
     782               0 :                           VSIStrerror(errno) );
     783               0 :                 return NULL;
     784                 :             }
     785                 :         }
     786                 : #endif
     787                 : 
     788             371 :         pszVRTPath = CPLStrdup(CPLGetPath(currentVrtFilename));
     789                 : 
     790             371 :         VSIFCloseL(fp);
     791                 :     }
     792                 : /* -------------------------------------------------------------------- */
     793                 : /*      Or use the filename as the XML input.                           */
     794                 : /* -------------------------------------------------------------------- */
     795                 :     else
     796                 :     {
     797              14 :         pszXML = CPLStrdup( poOpenInfo->pszFilename );
     798                 :     }
     799                 : 
     800                 : /* -------------------------------------------------------------------- */
     801                 : /*      Turn the XML representation into a VRTDataset.                  */
     802                 : /* -------------------------------------------------------------------- */
     803             385 :     VRTDataset *poDS = (VRTDataset *) OpenXML( pszXML, pszVRTPath, poOpenInfo->eAccess );
     804                 : 
     805             385 :     if( poDS != NULL )
     806             283 :         poDS->bNeedsFlush = FALSE;
     807                 : 
     808             385 :     CPLFree( pszXML );
     809             385 :     CPLFree( pszVRTPath );
     810                 : 
     811                 : /* -------------------------------------------------------------------- */
     812                 : /*      Open overviews.                                                 */
     813                 : /* -------------------------------------------------------------------- */
     814             385 :     if( fp != NULL && poDS != NULL )
     815             269 :         poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     816                 : 
     817             385 :     return poDS;
     818                 : }
     819                 : 
     820                 : /************************************************************************/
     821                 : /*                              OpenXML()                               */
     822                 : /*                                                                      */
     823                 : /*      Create an open VRTDataset from a supplied XML representation    */
     824                 : /*      of the dataset.                                                 */
     825                 : /************************************************************************/
     826                 : 
     827             385 : GDALDataset *VRTDataset::OpenXML( const char *pszXML, const char *pszVRTPath,
     828                 :                                   GDALAccess eAccess)
     829                 : 
     830                 : {
     831                 :  /* -------------------------------------------------------------------- */
     832                 :  /*      Parse the XML.                                                  */
     833                 :  /* -------------------------------------------------------------------- */
     834                 :     CPLXMLNode  *psTree;
     835                 : 
     836             385 :     psTree = CPLParseXMLString( pszXML );
     837                 : 
     838             385 :     if( psTree == NULL )
     839               0 :         return NULL;
     840                 : 
     841             385 :     CPLXMLNode *psRoot = CPLGetXMLNode( psTree, "=VRTDataset" );
     842             385 :     if (psRoot == NULL)
     843                 :     {
     844                 :         CPLError( CE_Failure, CPLE_AppDefined,
     845               0 :                   "Missing VRTDataset element." );
     846               0 :         CPLDestroyXMLNode( psTree );
     847               0 :         return NULL;
     848                 :     }
     849                 : 
     850             385 :     if( CPLGetXMLNode( psRoot, "rasterXSize" ) == NULL
     851                 :         || CPLGetXMLNode( psRoot, "rasterYSize" ) == NULL
     852                 :         || CPLGetXMLNode( psRoot, "VRTRasterBand" ) == NULL )
     853                 :     {
     854                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     855                 :                   "Missing one of rasterXSize, rasterYSize or bands on"
     856               1 :                   " VRTDataset." );
     857               1 :         CPLDestroyXMLNode( psTree );
     858               1 :         return NULL;
     859                 :     }
     860                 : 
     861                 : /* -------------------------------------------------------------------- */
     862                 : /*      Create the new virtual dataset object.                          */
     863                 : /* -------------------------------------------------------------------- */
     864                 :     VRTDataset *poDS;
     865             384 :     int nXSize = atoi(CPLGetXMLValue(psRoot,"rasterXSize","0"));
     866             384 :     int nYSize = atoi(CPLGetXMLValue(psRoot,"rasterYSize","0"));
     867                 :     
     868             384 :     if ( !GDALCheckDatasetDimensions(nXSize, nYSize) )
     869                 :     {
     870               0 :         CPLDestroyXMLNode( psTree );
     871               0 :         return NULL;
     872                 :     }
     873                 : 
     874             384 :     if( strstr(pszXML,"VRTWarpedDataset") != NULL )
     875              45 :         poDS = new VRTWarpedDataset( nXSize, nYSize );
     876                 :     else
     877                 :     {
     878             339 :         poDS = new VRTDataset( nXSize, nYSize );
     879             339 :         poDS->eAccess = eAccess;
     880                 :     }
     881                 : 
     882             384 :     if( poDS->XMLInit( psRoot, pszVRTPath ) != CE_None )
     883                 :     {
     884             101 :         delete poDS;
     885             101 :         poDS = NULL;
     886                 :     }
     887                 : 
     888                 : /* -------------------------------------------------------------------- */
     889                 : /*      Try to return a regular handle on the file.                     */
     890                 : /* -------------------------------------------------------------------- */
     891             384 :     CPLDestroyXMLNode( psTree );
     892                 : 
     893             384 :     return poDS;
     894                 : }
     895                 : 
     896                 : /************************************************************************/
     897                 : /*                              AddBand()                               */
     898                 : /************************************************************************/
     899                 : 
     900            1913 : CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
     901                 : 
     902                 : {
     903                 :     int i;
     904                 : 
     905            1913 :     const char *pszSubClass = CSLFetchNameValue(papszOptions, "subclass");
     906                 : 
     907            1913 :     bNeedsFlush = 1;
     908                 : 
     909                 : /* ==================================================================== */
     910                 : /*      Handle a new raw band.                                          */
     911                 : /* ==================================================================== */
     912            1913 :     if( pszSubClass != NULL && EQUAL(pszSubClass,"VRTRawRasterBand") )
     913                 :     {
     914               3 :         int nWordDataSize = GDALGetDataTypeSize( eType ) / 8;
     915               3 :         vsi_l_offset nImageOffset = 0;
     916               3 :         int nPixelOffset = nWordDataSize;
     917               3 :         int nLineOffset = nWordDataSize * GetRasterXSize();
     918                 :         const char *pszFilename;
     919               3 :         const char *pszByteOrder = NULL;
     920               3 :         int bRelativeToVRT = FALSE;
     921                 : 
     922                 : /* -------------------------------------------------------------------- */
     923                 : /*      Collect required information.                                   */
     924                 : /* -------------------------------------------------------------------- */
     925               3 :         if( CSLFetchNameValue(papszOptions, "ImageOffset") != NULL )
     926               2 :             nImageOffset = atoi(CSLFetchNameValue(papszOptions, "ImageOffset"));
     927                 : 
     928               3 :         if( CSLFetchNameValue(papszOptions, "PixelOffset") != NULL )
     929               2 :             nPixelOffset = atoi(CSLFetchNameValue(papszOptions,"PixelOffset"));
     930                 : 
     931               3 :         if( CSLFetchNameValue(papszOptions, "LineOffset") != NULL )
     932               2 :             nLineOffset = atoi(CSLFetchNameValue(papszOptions, "LineOffset"));
     933                 : 
     934               3 :         if( CSLFetchNameValue(papszOptions, "ByteOrder") != NULL )
     935               2 :             pszByteOrder = CSLFetchNameValue(papszOptions, "ByteOrder");
     936                 : 
     937               3 :         if( CSLFetchNameValue(papszOptions, "SourceFilename") != NULL )
     938               3 :             pszFilename = CSLFetchNameValue(papszOptions, "SourceFilename");
     939                 :         else
     940                 :         {
     941                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     942               0 :                       "AddBand() requires a SourceFilename option for VRTRawRasterBands." );
     943               0 :             return CE_Failure;
     944                 :         }
     945                 :         
     946                 :         bRelativeToVRT = 
     947               3 :             CSLFetchBoolean( papszOptions, "RelativeToVRT", FALSE );
     948                 : 
     949                 : /* -------------------------------------------------------------------- */
     950                 : /*      Create and initialize the band.                                 */
     951                 : /* -------------------------------------------------------------------- */
     952                 :         CPLErr eErr;
     953                 : 
     954                 :         VRTRawRasterBand *poBand = 
     955               6 :             new VRTRawRasterBand( this, GetRasterCount() + 1, eType );
     956                 : 
     957                 :         eErr = 
     958                 :             poBand->SetRawLink( pszFilename, NULL, bRelativeToVRT,
     959                 :                                 nImageOffset, nPixelOffset, nLineOffset, 
     960               3 :                                 pszByteOrder );
     961               3 :         if( eErr != CE_None )
     962                 :         {
     963               0 :             delete poBand;
     964               0 :             return eErr;
     965                 :         }
     966                 : 
     967               3 :         SetBand( GetRasterCount() + 1, poBand );
     968                 : 
     969               3 :         return CE_None;
     970                 :     }
     971                 : 
     972                 : /* ==================================================================== */
     973                 : /*      Handle a new "sourced" band.                                    */
     974                 : /* ==================================================================== */
     975                 :     else
     976                 :     {
     977                 :         VRTSourcedRasterBand *poBand;
     978                 : 
     979                 :   /* ---- Check for our sourced band 'derived' subclass ---- */
     980            1913 :         if(pszSubClass != NULL && EQUAL(pszSubClass,"VRTDerivedRasterBand")) {
     981                 : 
     982                 :             /* We'll need a pointer to the subclass in case we need */
     983                 :             /* to set the new band's pixel function below. */
     984                 :             VRTDerivedRasterBand* poDerivedBand;
     985                 : 
     986                 :             poDerivedBand = new VRTDerivedRasterBand
     987                 :                 (this, GetRasterCount() + 1, eType,
     988               4 :                  GetRasterXSize(), GetRasterYSize());
     989                 : 
     990                 :             /* Set the pixel function options it provided. */
     991                 :             const char* pszFuncName =
     992               4 :                 CSLFetchNameValue(papszOptions, "PixelFunctionType");
     993               4 :             if (pszFuncName != NULL)
     994               3 :                 poDerivedBand->SetPixelFunctionName(pszFuncName);
     995                 : 
     996                 :             const char* pszTransferTypeName =
     997               4 :                 CSLFetchNameValue(papszOptions, "SourceTransferType");
     998               4 :             if (pszTransferTypeName != NULL) {
     999                 :                 GDALDataType eTransferType =
    1000               2 :                     GDALGetDataTypeByName(pszTransferTypeName);
    1001               2 :                 if (eTransferType == GDT_Unknown) {
    1002                 :                     CPLError( CE_Failure, CPLE_AppDefined,
    1003                 :                               "invalid SourceTransferType: \"%s\".",
    1004               1 :                               pszTransferTypeName);
    1005               1 :                     delete poDerivedBand;
    1006               1 :                     return CE_Failure;
    1007                 :                 }
    1008               1 :                 poDerivedBand->SetSourceTransferType(eTransferType);
    1009                 :             }
    1010                 : 
    1011                 :             /* We're done with the derived band specific stuff, so */
    1012                 :             /* we can assigned the base class pointer now. */
    1013               3 :             poBand = poDerivedBand;
    1014                 :         }
    1015                 :   else {
    1016                 : 
    1017                 :       /* ---- Standard sourced band ---- */
    1018                 :       poBand = new VRTSourcedRasterBand
    1019                 :     (this, GetRasterCount() + 1, eType, 
    1020            1906 :      GetRasterXSize(), GetRasterYSize());
    1021                 :   }
    1022                 : 
    1023            1909 :         SetBand( GetRasterCount() + 1, poBand );
    1024                 : 
    1025            1915 :         for( i=0; papszOptions != NULL && papszOptions[i] != NULL; i++ )
    1026                 :         {
    1027               6 :             if( EQUALN(papszOptions[i],"AddFuncSource=", 14) )
    1028                 :             {
    1029               0 :                 VRTImageReadFunc pfnReadFunc = NULL;
    1030               0 :                 void             *pCBData = NULL;
    1031               0 :                 double           dfNoDataValue = VRT_NODATA_UNSET;
    1032                 : 
    1033               0 :                 char **papszTokens = CSLTokenizeStringComplex( papszOptions[i]+14,
    1034               0 :                                                                ",", TRUE, FALSE );
    1035                 : 
    1036               0 :                 if( CSLCount(papszTokens) < 1 )
    1037                 :                 {
    1038                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
    1039               0 :                               "AddFuncSource() ... required argument missing." );
    1040                 :                 }
    1041                 : 
    1042               0 :                 sscanf( papszTokens[0], "%p", &pfnReadFunc );
    1043               0 :                 if( CSLCount(papszTokens) > 1 )
    1044               0 :                     sscanf( papszTokens[1], "%p", &pCBData );
    1045               0 :                 if( CSLCount(papszTokens) > 2 )
    1046               0 :                     dfNoDataValue = atof( papszTokens[2] );
    1047                 : 
    1048               0 :                 poBand->AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue );
    1049                 :             }
    1050                 :         }
    1051                 : 
    1052            1909 :         return CE_None;
    1053                 :     }
    1054                 : }
    1055                 : 
    1056                 : /************************************************************************/
    1057                 : /*                              VRTAddBand()                            */
    1058                 : /************************************************************************/
    1059                 : 
    1060                 : /**
    1061                 :  * @see VRTDataset::VRTAddBand().
    1062                 :  */
    1063                 : 
    1064            1600 : int CPL_STDCALL VRTAddBand( VRTDatasetH hDataset, GDALDataType eType, 
    1065                 :                             char **papszOptions )
    1066                 : 
    1067                 : {
    1068            1600 :     VALIDATE_POINTER1( hDataset, "VRTAddBand", 0 );
    1069                 : 
    1070            1600 :     return ((VRTDataset *) hDataset)->AddBand(eType, papszOptions);
    1071                 : }
    1072                 : 
    1073                 : /************************************************************************/
    1074                 : /*                               Create()                               */
    1075                 : /************************************************************************/
    1076                 : 
    1077                 : GDALDataset *
    1078             133 : VRTDataset::Create( const char * pszName,
    1079                 :                     int nXSize, int nYSize, int nBands,
    1080                 :                     GDALDataType eType, char ** papszOptions )
    1081                 : 
    1082                 : {
    1083             133 :     VRTDataset *poDS = NULL;
    1084             133 :     int        iBand = 0;
    1085                 : 
    1086                 :     (void) papszOptions;
    1087                 : 
    1088             133 :     if( EQUALN(pszName,"<VRTDataset",11) )
    1089                 :     {
    1090               0 :         GDALDataset *poDS = OpenXML( pszName, NULL, GA_Update );
    1091               0 :         if (poDS)
    1092               0 :             poDS->SetDescription( "<FromXML>" );
    1093               0 :         return poDS;
    1094                 :     }
    1095                 :     else
    1096                 :     {
    1097                 :         const char *pszSubclass = CSLFetchNameValue( papszOptions,
    1098             133 :                                                      "SUBCLASS" );
    1099                 : 
    1100             262 :         if( pszSubclass == NULL || EQUAL(pszSubclass,"VRTDataset") )
    1101             129 :             poDS = new VRTDataset( nXSize, nYSize );
    1102               4 :         else if( EQUAL(pszSubclass,"VRTWarpedDataset") )
    1103                 :         {
    1104               4 :             poDS = new VRTWarpedDataset( nXSize, nYSize );
    1105                 :         }
    1106                 :         else
    1107                 :         {
    1108                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    1109                 :                       "SUBCLASS=%s not recognised.", 
    1110               0 :                       pszSubclass );
    1111               0 :             return NULL;
    1112                 :         }
    1113             133 :         poDS->eAccess = GA_Update;
    1114                 : 
    1115             133 :         poDS->SetDescription( pszName );
    1116                 :         
    1117             201 :         for( iBand = 0; iBand < nBands; iBand++ )
    1118              68 :             poDS->AddBand( eType, NULL );
    1119                 :         
    1120             133 :         poDS->bNeedsFlush = 1;
    1121                 : 
    1122             133 :         poDS->oOvManager.Initialize( poDS, pszName );
    1123                 :         
    1124             133 :         return poDS;
    1125                 :     }
    1126                 : }
    1127                 : 
    1128                 : /************************************************************************/
    1129                 : /*                            GetFileList()                             */
    1130                 : /************************************************************************/
    1131                 : 
    1132               5 : char** VRTDataset::GetFileList()
    1133                 : {
    1134               5 :     char** papszFileList = GDALDataset::GetFileList();
    1135                 :     
    1136               5 :     int nSize = CSLCount(papszFileList);
    1137               5 :     int nMaxSize = nSize;
    1138                 :     
    1139                 :     /* Don't need an element desallocator as each string points to an */
    1140                 :     /* element of the papszFileList */
    1141                 :     CPLHashSet* hSetFiles = CPLHashSetNew(CPLHashSetHashStr,
    1142                 :                                           CPLHashSetEqualStr,
    1143               5 :                                           NULL);
    1144                 :                                           
    1145              10 :     for( int iBand = 0; iBand < nBands; iBand++ )
    1146                 :     {
    1147              15 :        ((VRTRasterBand *) papoBands[iBand])->GetFileList(
    1148              15 :                                 &papszFileList, &nSize, &nMaxSize, hSetFiles);
    1149                 :     }
    1150                 :                                           
    1151               5 :     CPLHashSetDestroy(hSetFiles);
    1152                 :     
    1153               5 :     return papszFileList;
    1154                 : }
    1155                 : 
    1156                 : /************************************************************************/
    1157                 : /*                              Delete()                                */
    1158                 : /************************************************************************/
    1159                 : 
    1160                 : /* We implement Delete() to avoid that the default implementation */
    1161                 : /* in GDALDriver::Delete() destroys the source files listed by GetFileList(),*/
    1162                 : /* which would be an undesired effect... */
    1163              15 : CPLErr VRTDataset::Delete( const char * pszFilename )
    1164                 : {
    1165              15 :     GDALDriverH hDriver = GDALIdentifyDriver(pszFilename, NULL);
    1166              15 :     if (hDriver && EQUAL(GDALGetDriverShortName(hDriver), "VRT"))
    1167                 :     {
    1168              15 :         if( strstr(pszFilename, "<VRTDataset") == NULL &&
    1169                 :             VSIUnlink( pszFilename ) != 0 )
    1170                 :         {
    1171                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1172                 :                       "Deleting %s failed:\n%s",
    1173                 :                       pszFilename,
    1174               0 :                       VSIStrerror(errno) );
    1175               0 :             return CE_Failure;
    1176                 :         }
    1177                 :         
    1178              15 :         return CE_None;
    1179                 :     }
    1180                 :     else
    1181               0 :         return CE_Failure;
    1182                 : }
    1183                 : 
    1184                 : /************************************************************************/
    1185                 : /*                          CreateMaskBand()                            */
    1186                 : /************************************************************************/
    1187                 : 
    1188               4 : CPLErr VRTDataset::CreateMaskBand( int nFlags )
    1189                 : {
    1190               4 :     if (poMaskBand != NULL)
    1191                 :     {
    1192                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1193               0 :                  "This VRT dataset has already a mask band");
    1194               0 :         return CE_Failure;
    1195                 :     }
    1196                 : 
    1197               4 :     SetMaskBand(new VRTSourcedRasterBand( this, 0 ));
    1198                 : 
    1199               4 :     return CE_None;
    1200                 : }
    1201                 : 
    1202                 : /************************************************************************/
    1203                 : /*                           SetMaskBand()                              */
    1204                 : /************************************************************************/
    1205                 : 
    1206              15 : void VRTDataset::SetMaskBand(VRTRasterBand* poMaskBand)
    1207                 : {
    1208              15 :     delete this->poMaskBand;
    1209              15 :     this->poMaskBand = poMaskBand;
    1210              15 :     poMaskBand->SetIsMaskBand();
    1211              15 : }
    1212                 : 
    1213                 : /************************************************************************/
    1214                 : /*                        CloseDependentDatasets()                      */
    1215                 : /************************************************************************/
    1216                 : 
    1217              65 : int VRTDataset::CloseDependentDatasets()
    1218                 : {
    1219                 :     /* We need to call it before removing the sources, otherwise */
    1220                 :     /* we would remove them from the serizalized VRT */
    1221              65 :     FlushCache();
    1222                 : 
    1223              65 :     int bHasDroppedRef = GDALDataset::CloseDependentDatasets();
    1224                 : 
    1225             175 :     for( int iBand = 0; iBand < nBands; iBand++ )
    1226                 :     {
    1227             330 :        bHasDroppedRef |= ((VRTRasterBand *) papoBands[iBand])->
    1228             330 :                                                 CloseDependentDatasets();
    1229                 :     }
    1230              65 :     return bHasDroppedRef;
    1231                 : }
    1232                 : 
    1233                 : /************************************************************************/
    1234                 : /*                      CheckCompatibleForDatasetIO()                   */
    1235                 : /************************************************************************/
    1236                 : 
    1237                 : /* We will return TRUE only if all the bands are VRTSourcedRasterBands */
    1238                 : /* made of identical sources, that are strictly VRTSimpleSource, and that */
    1239                 : /* the band number of each source is the band number of the VRTSouredRasterBand */
    1240                 : 
    1241             587 : int VRTDataset::CheckCompatibleForDatasetIO()
    1242                 : {
    1243                 :     int iBand;
    1244             587 :     int nSources = 0;
    1245             587 :     VRTSource    **papoSources = NULL;
    1246            2358 :     for(iBand = 0; iBand < nBands; iBand++)
    1247                 :     {
    1248            1839 :         if (!((VRTRasterBand *) papoBands[iBand])->IsSourcedRasterBand())
    1249              25 :             return FALSE;
    1250                 : 
    1251            1814 :         VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[iBand];
    1252                 : 
    1253                 :         /* If there are overviews, let's VRTSourcedRasterBand::IRasterIO() */
    1254                 :         /* do the job */
    1255            1814 :         if (poBand->GetOverviewCount() != 0)
    1256               0 :             return FALSE;
    1257                 : 
    1258            1814 :         if (iBand == 0)
    1259                 :         {
    1260             562 :             nSources = poBand->nSources;
    1261             562 :             papoSources = poBand->papoSources;
    1262            1911 :             for(int iSource = 0; iSource < nSources; iSource++)
    1263                 :             {
    1264            1362 :                 if (!papoSources[iSource]->IsSimpleSource())
    1265               0 :                     return FALSE;
    1266                 : 
    1267            1362 :                 VRTSimpleSource* poSource = (VRTSimpleSource* )papoSources[iSource];
    1268            1362 :                 if (!EQUAL(poSource->GetType(), "SimpleSource"))
    1269               9 :                     return FALSE;
    1270            1353 :                 if (poSource->GetBand() == NULL)
    1271               0 :                     return FALSE;
    1272            1353 :                 if (poSource->GetBand()->GetBand() != iBand + 1)
    1273               4 :                     return FALSE;
    1274                 :             }
    1275                 :         }
    1276            1252 :         else if (nSources != poBand->nSources)
    1277                 :         {
    1278               0 :             return FALSE;
    1279                 :         }
    1280                 :         else
    1281                 :         {
    1282            4874 :             for(int iSource = 0; iSource < nSources; iSource++)
    1283                 :             {
    1284            3652 :                 VRTSimpleSource* poRefSource = (VRTSimpleSource* )papoSources[iSource];
    1285            3652 :                 VRTSimpleSource* poSource = (VRTSimpleSource* )poBand->papoSources[iSource];
    1286            3652 :                 if (!EQUAL(poSource->GetType(), "SimpleSource"))
    1287               0 :                     return FALSE;
    1288            3652 :                 if (!poSource->IsSameExceptBandNumber(poRefSource))
    1289               2 :                     return FALSE;
    1290            3650 :                 if (poSource->GetBand() == NULL)
    1291               0 :                     return FALSE;
    1292            3650 :                 if (poSource->GetBand()->GetBand() != iBand + 1)
    1293              28 :                     return FALSE;
    1294                 :             }
    1295                 :         }
    1296                 :     }
    1297                 : 
    1298             519 :     return nSources != 0;
    1299                 : }
    1300                 : 
    1301                 : /************************************************************************/
    1302                 : /*                         GetSingleSimpleSource()                      */
    1303                 : /*                                                                      */
    1304                 : /* Returns a non-NULL dataset if the VRT is made of a single source     */
    1305                 : /* that is a simple source, in its full extent, and with all of its     */
    1306                 : /* bands. Basically something produced by :                             */
    1307                 : /*   gdal_translate src dst.vrt -of VRT (-a_srs / -a_ullr)              */
    1308                 : /************************************************************************/
    1309                 : 
    1310              83 : GDALDataset* VRTDataset::GetSingleSimpleSource()
    1311                 : {
    1312              83 :     if (!CheckCompatibleForDatasetIO())
    1313              30 :         return NULL;
    1314                 : 
    1315              53 :     VRTSourcedRasterBand* poVRTBand = (VRTSourcedRasterBand* )papoBands[0];
    1316              53 :     VRTSimpleSource* poSource = (VRTSimpleSource* )poVRTBand->papoSources[0];
    1317              53 :     GDALRasterBand* poBand = poSource->GetBand();
    1318              53 :     if (poBand == NULL)
    1319               0 :         return NULL;
    1320              53 :     GDALDataset* poSrcDS = poBand->GetDataset();
    1321              53 :     if (poSrcDS == NULL)
    1322               0 :         return NULL;
    1323                 : 
    1324                 :     /* Check that it uses the full source dataset */
    1325                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
    1326                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
    1327                 :     poSource->GetSrcDstWindow( 0, 0,
    1328                 :                                poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(),
    1329                 :                                poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(),
    1330                 :                                &nReqXOff, &nReqYOff,
    1331                 :                                &nReqXSize, &nReqYSize,
    1332                 :                                &nOutXOff, &nOutYOff,
    1333              53 :                                &nOutXSize, &nOutYSize );
    1334                 : 
    1335              53 :     if (nReqXOff != 0 || nReqYOff != 0 ||
    1336                 :         nReqXSize != poSrcDS->GetRasterXSize() ||
    1337                 :         nReqYSize != poSrcDS->GetRasterYSize())
    1338               8 :         return NULL;
    1339                 : 
    1340              45 :     if (nOutXOff != 0 || nOutYOff != 0 ||
    1341                 :         nOutXSize != poSrcDS->GetRasterXSize() ||
    1342                 :         nOutYSize != poSrcDS->GetRasterYSize())
    1343               0 :         return NULL;
    1344                 : 
    1345              45 :     return poSrcDS;
    1346                 : }
    1347                 : 
    1348                 : /************************************************************************/
    1349                 : /*                              IRasterIO()                             */
    1350                 : /************************************************************************/
    1351                 : 
    1352             696 : CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
    1353                 :                                int nXOff, int nYOff, int nXSize, int nYSize,
    1354                 :                                void * pData, int nBufXSize, int nBufYSize,
    1355                 :                                GDALDataType eBufType,
    1356                 :                                int nBandCount, int *panBandMap,
    1357                 :                                int nPixelSpace, int nLineSpace, int nBandSpace)
    1358                 : {
    1359             696 :     if (bCompatibleForDatasetIO < 0)
    1360                 :     {
    1361             504 :         bCompatibleForDatasetIO = CheckCompatibleForDatasetIO();
    1362                 :     }
    1363             696 :     if (bCompatibleForDatasetIO && eRWFlag == GF_Read && nBandCount > 1)
    1364                 :     {
    1365             224 :         for(int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++)
    1366                 :         {
    1367                 :             VRTSourcedRasterBand* poBand =
    1368             168 :                     (VRTSourcedRasterBand*)GetRasterBand(panBandMap[iBandIndex]);
    1369                 : 
    1370                 :             /* Dirty little trick to initialize the buffer without doing */
    1371                 :             /* any real I/O */
    1372             168 :             int nSavedSources = poBand->nSources;
    1373             168 :             poBand->nSources = 0;
    1374                 : 
    1375             168 :             GByte *pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
    1376                 :             poBand->IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize,
    1377                 :                                 pabyBandData, nBufXSize, nBufYSize,
    1378                 :                                 eBufType,
    1379             168 :                                 nPixelSpace, nLineSpace);
    1380                 : 
    1381             168 :             poBand->nSources = nSavedSources;
    1382                 :         }
    1383                 : 
    1384              56 :         CPLErr eErr = CE_None;
    1385                 :         /* Use the last band, because when sources reference a GDALProxyDataset, they */
    1386                 :         /* don't necessary instanciate all underlying rasterbands */
    1387              56 :         VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[nBands - 1];
    1388             112 :         for(int iSource = 0; eErr == CE_None && iSource < poBand->nSources; iSource++)
    1389                 :         {
    1390              56 :             VRTSimpleSource* poSource = (VRTSimpleSource* )poBand->papoSources[iSource];
    1391                 :             eErr = poSource->DatasetRasterIO( nXOff, nYOff, nXSize, nYSize,
    1392                 :                                               pData, nBufXSize, nBufYSize,
    1393                 :                                               eBufType,
    1394                 :                                               nBandCount, panBandMap,
    1395              56 :                                               nPixelSpace, nLineSpace, nBandSpace);
    1396                 :         }
    1397              56 :         return eErr;
    1398                 :     }
    1399                 : 
    1400                 :     return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
    1401                 :                                   pData, nBufXSize, nBufYSize,
    1402                 :                                   eBufType,
    1403                 :                                   nBandCount, panBandMap,
    1404             640 :                                   nPixelSpace, nLineSpace, nBandSpace);
    1405                 : }

Generated by: LCOV version 1.7