static CPLStringList ParseSimpleJson(const char *pszJson) { /* -------------------------------------------------------------------- */ /* We are expecting simple documents like the following with no */ /* heirarchy or complex structure. */ /* -------------------------------------------------------------------- */ /* { "access_token":"1/fFBGRNJru1FQd44AzqT3Zg", "expires_in":3920, "token_type":"Bearer" } */ CPLStringList oWords( CSLTokenizeString2(pszJson, " \n\t,:{}", CSLT_HONOURSTRINGS )); CPLStringList oNameValue; for( int i=0; i < oWords.size(); i += 2 ) { oNameValue.SetNameValue( oWords[i], oWords[i+1] ); } return oNameValue; }
bool GNMRule::ParseRuleString() { CPLStringList aTokens (CSLTokenizeString2(m_soRuleString.c_str(), " ", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES)); // the minimum rule consist 3 tokens int nTokenCount = aTokens.Count(); if(nTokenCount < 3) { CPLError( CE_Failure, CPLE_IllegalArg, "Need more than %d tokens. Failed to parse rule: %s", nTokenCount, m_soRuleString.c_str() ); return false; } if(EQUAL(aTokens[0], GNM_RULEKW_ALLOW)) m_bAllow = true; else if(EQUAL(aTokens[0], GNM_RULEKW_DENY)) m_bAllow = false; else { CPLError( CE_Failure, CPLE_IllegalArg, "First token is invalid. Failed to parse rule: %s", m_soRuleString.c_str() ); return false; } // now just test if the value == connects // in future should set rule type if(!EQUAL(aTokens[1], GNM_RULEKW_CONNECTS)) { CPLError( CE_Failure, CPLE_IllegalArg, "Not a CONNECTS rule. Failed to parse rule: %s", m_soRuleString.c_str() ); return false; } if(EQUAL(aTokens[2], GNM_RULEKW_ANY)) { m_bAny = true; return true; } else { if(nTokenCount < 5) { CPLError( CE_Failure, CPLE_IllegalArg, "Not an ANY rule, but have only %d tokens. Failed to parse rule: %s", nTokenCount, m_soRuleString.c_str() ); return false; } m_soSrcLayerName = aTokens[2]; m_soTgtLayerName = aTokens[4]; } if(nTokenCount < 7) // skip 5 and 6 parameters return true; else m_soConnLayerName = aTokens[6]; return true; }
/** * @details This method is the heart of the tiler. A `TileCoordinate` is used * to obtain the geospatial extent associated with that tile as related to the * underlying GDAL dataset. This mapping may require a reprojection if the * underlying dataset is not in the tile projection system. This information * is then encapsulated as a GDAL virtual raster (VRT) dataset and returned to * the caller. * * It is the caller's responsibility to call `GDALClose()` on the returned * dataset. */ GDALTile * GDALTiler::createRasterTile(double (&adfGeoTransform)[6]) const { if (poDataset == NULL) { throw CTBException("No GDAL dataset is set"); } // The source and sink datasets GDALDatasetH hSrcDS = (GDALDatasetH) dataset(); GDALDatasetH hDstDS; // The transformation option list CPLStringList transformOptions; // The source, sink and grid srs const char *pszSrcWKT = GDALGetProjectionRef(hSrcDS), *pszGridWKT = pszSrcWKT; if (!strlen(pszSrcWKT)) throw CTBException("The source dataset no longer has a spatial reference system assigned"); // Populate the SRS WKT strings if we need to reproject if (requiresReprojection()) { pszGridWKT = crsWKT.c_str(); transformOptions.SetNameValue("SRC_SRS", pszSrcWKT); transformOptions.SetNameValue("DST_SRS", pszGridWKT); } // Set the warp options GDALWarpOptions *psWarpOptions = GDALCreateWarpOptions(); psWarpOptions->eResampleAlg = options.resampleAlg; psWarpOptions->dfWarpMemoryLimit = options.warpMemoryLimit; psWarpOptions->hSrcDS = hSrcDS; psWarpOptions->nBandCount = poDataset->GetRasterCount(); psWarpOptions->panSrcBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount ); psWarpOptions->panDstBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount ); for (short unsigned int i = 0; i < psWarpOptions->nBandCount; ++i) { psWarpOptions->panDstBands[i] = psWarpOptions->panSrcBands[i] = i + 1; } // Create the image to image transformer void *transformerArg = GDALCreateGenImgProjTransformer2(hSrcDS, NULL, transformOptions.List()); if(transformerArg == NULL) { GDALDestroyWarpOptions(psWarpOptions); throw CTBException("Could not create image to image transformer"); } // Try and get an overview from the source dataset that corresponds more // closely to the resolution of this tile. GDALDatasetH hWrkSrcDS = getOverviewDataset(hSrcDS, GDALGenImgProjTransform, transformerArg); if (hWrkSrcDS == NULL) { hWrkSrcDS = psWarpOptions->hSrcDS = hSrcDS; } else { // We need to recreate the transform when operating on an overview. GDALDestroyGenImgProjTransformer( transformerArg ); transformerArg = GDALCreateGenImgProjTransformer2( hWrkSrcDS, NULL, transformOptions.List() ); if(transformerArg == NULL) { GDALDestroyWarpOptions(psWarpOptions); throw CTBException("Could not create overview image to image transformer"); } } // Specify the destination geotransform GDALSetGenImgProjTransformerDstGeoTransform(transformerArg, adfGeoTransform ); // Decide if we are doing an approximate or exact transformation if (options.errorThreshold) { // approximate: wrap the transformer with a linear approximator psWarpOptions->pTransformerArg = GDALCreateApproxTransformer(GDALGenImgProjTransform, transformerArg, options.errorThreshold); if (psWarpOptions->pTransformerArg == NULL) { GDALDestroyWarpOptions(psWarpOptions); GDALDestroyGenImgProjTransformer(transformerArg); throw CTBException("Could not create linear approximator"); } psWarpOptions->pfnTransformer = GDALApproxTransform; } else { // exact: no wrapping required psWarpOptions->pTransformerArg = transformerArg; psWarpOptions->pfnTransformer = GDALGenImgProjTransform; } // Specify a multi threaded warp operation using all CPU cores CPLStringList warpOptions(psWarpOptions->papszWarpOptions, false); warpOptions.SetNameValue("NUM_THREADS", "ALL_CPUS"); psWarpOptions->papszWarpOptions = warpOptions.StealList(); // The raster tile is represented as a VRT dataset hDstDS = GDALCreateWarpedVRT(hWrkSrcDS, mGrid.tileSize(), mGrid.tileSize(), adfGeoTransform, psWarpOptions); bool isApproxTransform = (psWarpOptions->pfnTransformer == GDALApproxTransform); GDALDestroyWarpOptions( psWarpOptions ); if (hDstDS == NULL) { GDALDestroyGenImgProjTransformer(transformerArg); throw CTBException("Could not create warped VRT"); } // Set the projection information on the dataset. This will always be the grid // SRS. if (GDALSetProjection( hDstDS, pszGridWKT ) != CE_None) { GDALClose(hDstDS); if (transformerArg != NULL) { GDALDestroyGenImgProjTransformer(transformerArg); } throw CTBException("Could not set projection on VRT"); } // If uncommenting the following line for debug purposes, you must also `#include "vrtdataset.h"` //std::cout << "VRT: " << CPLSerializeXMLTree(((VRTWarpedDataset *) hDstDS)->SerializeToXML(NULL)) << std::endl; // Create the tile, passing it the base image transformer to manage if this is // an approximate transform return new GDALTile((GDALDataset *) hDstDS, isApproxTransform ? transformerArg : NULL); }
char CPL_DLL *GOA2GetRefreshToken( const char *pszAuthToken, const char *pszScope ) { /* -------------------------------------------------------------------- */ /* Prepare request. */ /* -------------------------------------------------------------------- */ CPLString osItem; CPLStringList oOptions; oOptions.AddString( "HEADERS=Content-Type: application/x-www-form-urlencoded" ); osItem.Printf( "POSTFIELDS=" "code=%s" "&client_id=%s" "&client_secret=%s" "&redirect_uri=urn:ietf:wg:oauth:2.0:oob" "&grant_type=authorization_code", pszAuthToken, CPLGetConfigOption("GOA2_CLIENT_ID", GDAL_CLIENT_ID), CPLGetConfigOption("GOA2_CLIENT_SECRET", GDAL_CLIENT_SECRET)); oOptions.AddString(osItem); /* -------------------------------------------------------------------- */ /* Submit request by HTTP. */ /* -------------------------------------------------------------------- */ CPLHTTPResult * psResult = CPLHTTPFetch( GOOGLE_AUTH_URL "/token", oOptions); if (psResult == NULL) return NULL; /* -------------------------------------------------------------------- */ /* One common mistake is to try and reuse the auth token. */ /* After the first use it will return invalid_grant. */ /* -------------------------------------------------------------------- */ if( psResult->pabyData != NULL && strstr((const char *) psResult->pabyData,"invalid_grant") != NULL) { CPLString osURL; osURL.Seize( GOA2GetAuthorizationURL(pszScope) ); CPLError( CE_Failure, CPLE_AppDefined, "Attempt to use a OAuth2 authorization code multiple times.\n" "Request a fresh authorization token at\n%s.", osURL.c_str() ); CPLHTTPDestroyResult(psResult); return NULL; } if (psResult->pabyData == NULL || psResult->pszErrBuf != NULL) { if( psResult->pszErrBuf != NULL ) CPLDebug( "GOA2", "%s", psResult->pszErrBuf ); if( psResult->pabyData != NULL ) CPLDebug( "GOA2", "%s", psResult->pabyData ); CPLError( CE_Failure, CPLE_AppDefined, "Fetching OAuth2 access code from auth code failed."); CPLHTTPDestroyResult(psResult); return NULL; } CPLDebug( "GOA2", "Access Token Response:\n%s", (const char *) psResult->pabyData ); /* -------------------------------------------------------------------- */ /* This response is in JSON and will look something like: */ /* -------------------------------------------------------------------- */ /* { "access_token" : "ya29.AHES6ZToqkIJkat5rIqMixR1b8PlWBACNO8OYbqqV-YF1Q13E2Kzjw", "token_type" : "Bearer", "expires_in" : 3600, "refresh_token" : "1/eF88pciwq9Tp_rHEhuiIv9AS44Ufe4GOymGawTVPGYo" } */ CPLStringList oResponse = ParseSimpleJson( (const char *) psResult->pabyData ); CPLHTTPDestroyResult(psResult); CPLString osAccessToken = oResponse.FetchNameValueDef( "access_token", "" ); CPLString osRefreshToken = oResponse.FetchNameValueDef( "refresh_token", "" ); CPLDebug("GOA2", "Access Token : '%s'", osAccessToken.c_str()); CPLDebug("GOA2", "Refresh Token : '%s'", osRefreshToken.c_str()); if( osRefreshToken.size() == 0) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to identify a refresh token in the OAuth2 response."); return NULL; } else { // Currently we discard the access token and just return the refresh token return CPLStrdup(osRefreshToken); } }
char *GOA2GetAccessToken( const char *pszRefreshToken, CPL_UNUSED const char *pszScope ) { /* -------------------------------------------------------------------- */ /* Prepare request. */ /* -------------------------------------------------------------------- */ CPLString osItem; CPLStringList oOptions; oOptions.AddString( "HEADERS=Content-Type: application/x-www-form-urlencoded" ); osItem.Printf( "POSTFIELDS=" "refresh_token=%s" "&client_id=%s" "&client_secret=%s" "&grant_type=refresh_token", pszRefreshToken, CPLGetConfigOption("GOA2_CLIENT_ID", GDAL_CLIENT_ID), CPLGetConfigOption("GOA2_CLIENT_SECRET", GDAL_CLIENT_SECRET)); oOptions.AddString(osItem); /* -------------------------------------------------------------------- */ /* Submit request by HTTP. */ /* -------------------------------------------------------------------- */ CPLHTTPResult *psResult = CPLHTTPFetch(GOOGLE_AUTH_URL "/token", oOptions); if (psResult == NULL) return NULL; if (psResult->pabyData == NULL || psResult->pszErrBuf != NULL) { if( psResult->pszErrBuf != NULL ) CPLDebug( "GFT", "%s", psResult->pszErrBuf ); if( psResult->pabyData != NULL ) CPLDebug( "GFT", "%s", psResult->pabyData ); CPLError( CE_Failure, CPLE_AppDefined, "Fetching OAuth2 access code from auth code failed."); CPLHTTPDestroyResult(psResult); return NULL; } CPLDebug( "GOA2", "Refresh Token Response:\n%s", (const char *) psResult->pabyData ); /* -------------------------------------------------------------------- */ /* This response is in JSON and will look something like: */ /* -------------------------------------------------------------------- */ /* { "access_token":"1/fFBGRNJru1FQd44AzqT3Zg", "expires_in":3920, "token_type":"Bearer" } */ CPLStringList oResponse = ParseSimpleJson( (const char *) psResult->pabyData ); CPLHTTPDestroyResult(psResult); CPLString osAccessToken = oResponse.FetchNameValueDef( "access_token", "" ); CPLDebug("GOA2", "Access Token : '%s'", osAccessToken.c_str()); if (osAccessToken.size() == 0) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to identify an access token in the OAuth2 response."); return NULL; } else return CPLStrdup(osAccessToken); }
CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, const char *pszUnused ) { PamInitialize(); /* -------------------------------------------------------------------- */ /* Apply any dataset level metadata. */ /* -------------------------------------------------------------------- */ oMDMD.XMLInit( psTree, TRUE ); /* -------------------------------------------------------------------- */ /* Collect various other items of metadata. */ /* -------------------------------------------------------------------- */ GDALMajorObject::SetDescription( CPLGetXMLValue( psTree, "Description", "" ) ); if( CPLGetXMLValue( psTree, "NoDataValue", NULL ) != NULL ) { const char *pszLEHex = CPLGetXMLValue( psTree, "NoDataValue.le_hex_equiv", NULL ); if( pszLEHex != NULL ) { int nBytes; GByte *pabyBin = CPLHexToBinary( pszLEHex, &nBytes ); if( nBytes == 8 ) { CPL_LSBPTR64( pabyBin ); GDALPamRasterBand::SetNoDataValue( *((double *) pabyBin) ); } else { GDALPamRasterBand::SetNoDataValue( atof(CPLGetXMLValue( psTree, "NoDataValue", "0" )) ); } CPLFree( pabyBin ); } else { GDALPamRasterBand::SetNoDataValue( atof(CPLGetXMLValue( psTree, "NoDataValue", "0" )) ); } } GDALPamRasterBand::SetOffset( atof(CPLGetXMLValue( psTree, "Offset", "0.0" )) ); GDALPamRasterBand::SetScale( atof(CPLGetXMLValue( psTree, "Scale", "1.0" )) ); GDALPamRasterBand::SetUnitType( CPLGetXMLValue( psTree, "UnitType", NULL)); if( CPLGetXMLValue( psTree, "ColorInterp", NULL ) != NULL ) { const char *pszInterp = CPLGetXMLValue( psTree, "ColorInterp", NULL ); GDALPamRasterBand::SetColorInterpretation( GDALGetColorInterpretationByName(pszInterp)); } /* -------------------------------------------------------------------- */ /* Category names. */ /* -------------------------------------------------------------------- */ if( CPLGetXMLNode( psTree, "CategoryNames" ) != NULL ) { CPLXMLNode *psEntry; CPLStringList oCategoryNames; for( psEntry = CPLGetXMLNode( psTree, "CategoryNames" )->psChild; psEntry != NULL; psEntry = psEntry->psNext ) { /* Don't skeep <Category> tag with empty content */ if( psEntry->eType != CXT_Element || !EQUAL(psEntry->pszValue,"Category") || (psEntry->psChild != NULL && psEntry->psChild->eType != CXT_Text) ) continue; oCategoryNames.AddString( (psEntry->psChild) ? psEntry->psChild->pszValue : "" ); } GDALPamRasterBand::SetCategoryNames( oCategoryNames.List() ); } /* -------------------------------------------------------------------- */ /* Collect a color table. */ /* -------------------------------------------------------------------- */ if( CPLGetXMLNode( psTree, "ColorTable" ) != NULL ) { CPLXMLNode *psEntry; GDALColorTable oTable; int iEntry = 0; for( psEntry = CPLGetXMLNode( psTree, "ColorTable" )->psChild; psEntry != NULL; psEntry = psEntry->psNext ) { GDALColorEntry sCEntry; sCEntry.c1 = (short) atoi(CPLGetXMLValue( psEntry, "c1", "0" )); sCEntry.c2 = (short) atoi(CPLGetXMLValue( psEntry, "c2", "0" )); sCEntry.c3 = (short) atoi(CPLGetXMLValue( psEntry, "c3", "0" )); sCEntry.c4 = (short) atoi(CPLGetXMLValue( psEntry, "c4", "255" )); oTable.SetColorEntry( iEntry++, &sCEntry ); } GDALPamRasterBand::SetColorTable( &oTable ); } /* -------------------------------------------------------------------- */ /* Do we have a complete set of stats? */ /* -------------------------------------------------------------------- */ if( CPLGetXMLNode( psTree, "Minimum" ) != NULL && CPLGetXMLNode( psTree, "Maximum" ) != NULL ) { psPam->bHaveMinMax = TRUE; psPam->dfMin = atof(CPLGetXMLValue(psTree, "Minimum","0")); psPam->dfMax = atof(CPLGetXMLValue(psTree, "Maximum","0")); } if( CPLGetXMLNode( psTree, "Mean" ) != NULL && CPLGetXMLNode( psTree, "StandardDeviation" ) != NULL ) { psPam->bHaveStats = TRUE; psPam->dfMean = atof(CPLGetXMLValue(psTree, "Mean","0")); psPam->dfStdDev = atof(CPLGetXMLValue(psTree,"StandardDeviation","0")); } /* -------------------------------------------------------------------- */ /* Histograms */ /* -------------------------------------------------------------------- */ CPLXMLNode *psHist = CPLGetXMLNode( psTree, "Histograms" ); if( psHist != NULL ) { CPLXMLNode *psNext = psHist->psNext; psHist->psNext = NULL; if (psPam->psSavedHistograms != NULL) { CPLDestroyXMLNode (psPam->psSavedHistograms ); psPam->psSavedHistograms = NULL; } psPam->psSavedHistograms = CPLCloneXMLTree( psHist ); psHist->psNext = psNext; } /* -------------------------------------------------------------------- */ /* Raster Attribute Table */ /* -------------------------------------------------------------------- */ CPLXMLNode *psRAT = CPLGetXMLNode( psTree, "GDALRasterAttributeTable" ); if( psRAT != NULL ) { if( psPam->poDefaultRAT != NULL ) { delete psPam->poDefaultRAT; psPam->poDefaultRAT = NULL; } psPam->poDefaultRAT = new GDALDefaultRasterAttributeTable(); psPam->poDefaultRAT->XMLInit( psRAT, "" ); } return CE_None; }
CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree, const char *pszVRTPath ) { /* -------------------------------------------------------------------- */ /* Validate a bit. */ /* -------------------------------------------------------------------- */ if( psTree == NULL || psTree->eType != CXT_Element || !EQUAL(psTree->pszValue,"VRTRasterBand") ) { CPLError( CE_Failure, CPLE_AppDefined, "Invalid node passed to VRTRasterBand::XMLInit()." ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Set the band if provided as an attribute. */ /* -------------------------------------------------------------------- */ const char* pszBand = CPLGetXMLValue( psTree, "band", NULL); if( pszBand != NULL ) { nBand = atoi(pszBand); } /* -------------------------------------------------------------------- */ /* Set the band if provided as an attribute. */ /* -------------------------------------------------------------------- */ const char *pszDataType = CPLGetXMLValue( psTree, "dataType", NULL); if( pszDataType != NULL ) { eDataType = GDALGetDataTypeByName(pszDataType); } /* -------------------------------------------------------------------- */ /* Apply any band level metadata. */ /* -------------------------------------------------------------------- */ oMDMD.XMLInit( psTree, TRUE ); /* -------------------------------------------------------------------- */ /* Collect various other items of metadata. */ /* -------------------------------------------------------------------- */ SetDescription( CPLGetXMLValue( psTree, "Description", "" ) ); if( CPLGetXMLValue( psTree, "NoDataValue", NULL ) != NULL ) SetNoDataValue( CPLAtofM(CPLGetXMLValue( psTree, "NoDataValue", "0" )) ); if( CPLGetXMLValue( psTree, "HideNoDataValue", NULL ) != NULL ) bHideNoDataValue = CSLTestBoolean( CPLGetXMLValue( psTree, "HideNoDataValue", "0" ) ); SetUnitType( CPLGetXMLValue( psTree, "UnitType", NULL ) ); SetOffset( atof(CPLGetXMLValue( psTree, "Offset", "0.0" )) ); SetScale( atof(CPLGetXMLValue( psTree, "Scale", "1.0" )) ); if( CPLGetXMLValue( psTree, "ColorInterp", NULL ) != NULL ) { const char *pszInterp = CPLGetXMLValue( psTree, "ColorInterp", NULL ); SetColorInterpretation(GDALGetColorInterpretationByName(pszInterp)); } /* -------------------------------------------------------------------- */ /* Category names. */ /* -------------------------------------------------------------------- */ if( CPLGetXMLNode( psTree, "CategoryNames" ) != NULL ) { CPLXMLNode *psEntry; CSLDestroy( papszCategoryNames ); papszCategoryNames = NULL; CPLStringList oCategoryNames; for( psEntry = CPLGetXMLNode( psTree, "CategoryNames" )->psChild; psEntry != NULL; psEntry = psEntry->psNext ) { if( psEntry->eType != CXT_Element || !EQUAL(psEntry->pszValue,"Category") || (psEntry->psChild != NULL && psEntry->psChild->eType != CXT_Text) ) continue; oCategoryNames.AddString( (psEntry->psChild) ? psEntry->psChild->pszValue : ""); } papszCategoryNames = oCategoryNames.StealList(); } /* -------------------------------------------------------------------- */ /* Collect a color table. */ /* -------------------------------------------------------------------- */ if( CPLGetXMLNode( psTree, "ColorTable" ) != NULL ) { CPLXMLNode *psEntry; GDALColorTable oTable; int iEntry = 0; for( psEntry = CPLGetXMLNode( psTree, "ColorTable" )->psChild; psEntry != NULL; psEntry = psEntry->psNext ) { GDALColorEntry sCEntry; sCEntry.c1 = (short) atoi(CPLGetXMLValue( psEntry, "c1", "0" )); sCEntry.c2 = (short) atoi(CPLGetXMLValue( psEntry, "c2", "0" )); sCEntry.c3 = (short) atoi(CPLGetXMLValue( psEntry, "c3", "0" )); sCEntry.c4 = (short) atoi(CPLGetXMLValue( psEntry, "c4", "255" )); oTable.SetColorEntry( iEntry++, &sCEntry ); } SetColorTable( &oTable ); } /* -------------------------------------------------------------------- */ /* Histograms */ /* -------------------------------------------------------------------- */ CPLXMLNode *psHist = CPLGetXMLNode( psTree, "Histograms" ); if( psHist != NULL ) { CPLXMLNode *psNext = psHist->psNext; psHist->psNext = NULL; psSavedHistograms = CPLCloneXMLTree( psHist ); psHist->psNext = psNext; } /* ==================================================================== */ /* Overviews */ /* ==================================================================== */ CPLXMLNode *psNode; for( psNode = psTree->psChild; psNode != NULL; psNode = psNode->psNext ) { if( psNode->eType != CXT_Element || !EQUAL(psNode->pszValue,"Overview") ) continue; /* -------------------------------------------------------------------- */ /* Prepare filename. */ /* -------------------------------------------------------------------- */ char *pszSrcDSName = NULL; CPLXMLNode* psFileNameNode=CPLGetXMLNode(psNode,"SourceFilename"); const char *pszFilename = psFileNameNode ? CPLGetXMLValue(psFileNameNode,NULL, NULL) : NULL; if( pszFilename == NULL ) { CPLError( CE_Warning, CPLE_AppDefined, "Missing <SourceFilename> element in Overview." ); return CE_Failure; } if (EQUALN(pszFilename, "MEM:::", 6) && pszVRTPath != NULL && !CSLTestBoolean(CPLGetConfigOption("VRT_ALLOW_MEM_DRIVER", "NO"))) { CPLError( CE_Failure, CPLE_AppDefined, "<SourceFilename> points to a MEM dataset, which is rather suspect! " "If you know what you are doing, define the VRT_ALLOW_MEM_DRIVER configuration option to YES" ); return CE_Failure; } if( pszVRTPath != NULL && atoi(CPLGetXMLValue( psFileNameNode, "relativetoVRT", "0")) ) { pszSrcDSName = CPLStrdup( CPLProjectRelativeFilename( pszVRTPath, pszFilename ) ); } else pszSrcDSName = CPLStrdup( pszFilename ); /* -------------------------------------------------------------------- */ /* Get the raster band. */ /* -------------------------------------------------------------------- */ int nSrcBand = atoi(CPLGetXMLValue(psNode,"SourceBand","1")); apoOverviews.resize( apoOverviews.size() + 1 ); apoOverviews[apoOverviews.size()-1].osFilename = pszSrcDSName; apoOverviews[apoOverviews.size()-1].nBand = nSrcBand; CPLFree( pszSrcDSName ); } /* ==================================================================== */ /* Mask band (specific to that raster band) */ /* ==================================================================== */ CPLXMLNode* psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand"); if (psMaskBandNode) psNode = psMaskBandNode->psChild; else psNode = NULL; for( ; psNode != NULL; psNode = psNode->psNext ) { if( psNode->eType != CXT_Element || !EQUAL(psNode->pszValue,"VRTRasterBand") ) continue; if( ((VRTDataset*)poDS)->poMaskBand != NULL) { CPLError( CE_Warning, CPLE_AppDefined, "Illegal mask band at raster band level when a dataset mask band already exists." ); break; } const char *pszSubclass = CPLGetXMLValue( psNode, "subclass", "VRTSourcedRasterBand" ); VRTRasterBand *poBand = NULL; if( EQUAL(pszSubclass,"VRTSourcedRasterBand") ) poBand = new VRTSourcedRasterBand( GetDataset(), 0 ); else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") ) poBand = new VRTDerivedRasterBand( GetDataset(), 0 ); else if( EQUAL(pszSubclass, "VRTRawRasterBand") ) poBand = new VRTRawRasterBand( GetDataset(), 0 ); else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") ) poBand = new VRTWarpedRasterBand( GetDataset(), 0 ); else { CPLError( CE_Failure, CPLE_AppDefined, "VRTRasterBand of unrecognised subclass '%s'.", pszSubclass ); break; } if( poBand->XMLInit( psNode, pszVRTPath ) == CE_None ) { SetMaskBand(poBand); } break; } return CE_None; }
int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, CPL_UNUSED int bMerge ) { CPLXMLNode *psMetadata; /* ==================================================================== */ /* Process all <Metadata> elements, each for one domain. */ /* ==================================================================== */ for( psMetadata = psTree->psChild; psMetadata != NULL; psMetadata = psMetadata->psNext ) { CPLXMLNode *psMDI; const char *pszDomain, *pszFormat; if( psMetadata->eType != CXT_Element || !EQUAL(psMetadata->pszValue,"Metadata") ) continue; pszDomain = CPLGetXMLValue( psMetadata, "domain", "" ); pszFormat = CPLGetXMLValue( psMetadata, "format", "" ); // Make sure we have a CPLStringList for this domain, // without wiping out an existing one. if( GetMetadata( pszDomain ) == NULL ) SetMetadata( NULL, pszDomain ); int iDomain = CSLFindString( papszDomainList, pszDomain ); CPLAssert( iDomain != -1 ); CPLStringList *poMDList = papoMetadataLists[iDomain]; /* -------------------------------------------------------------------- */ /* XML format subdocuments. */ /* -------------------------------------------------------------------- */ if( EQUAL(pszFormat,"xml") ) { CPLXMLNode *psSubDoc; /* find first non-attribute child of current element */ psSubDoc = psMetadata->psChild; while( psSubDoc != NULL && psSubDoc->eType == CXT_Attribute ) psSubDoc = psSubDoc->psNext; char *pszDoc = CPLSerializeXMLTree( psSubDoc ); poMDList->Clear(); poMDList->AddStringDirectly( pszDoc ); } /* -------------------------------------------------------------------- */ /* Name value format. */ /* <MDI key="...">value_Text</MDI> */ /* -------------------------------------------------------------------- */ else { for( psMDI = psMetadata->psChild; psMDI != NULL; psMDI = psMDI->psNext ) { if( !EQUAL(psMDI->pszValue,"MDI") || psMDI->eType != CXT_Element || psMDI->psChild == NULL || psMDI->psChild->psNext == NULL || psMDI->psChild->eType != CXT_Attribute || psMDI->psChild->psChild == NULL ) continue; char* pszName = psMDI->psChild->psChild->pszValue; char* pszValue = psMDI->psChild->psNext->pszValue; if( pszName != NULL && pszValue != NULL ) poMDList->SetNameValue( pszName, pszValue ); } } } return CSLCount(papszDomainList) != 0; }
MAIN_START(argc, argv) { // Check that we are running against at least GDAL 1.5. // Note to developers: if we use newer API, please change the requirement. if (atoi(GDALVersionInfo("VERSION_NUM")) < 1500) { fprintf(stderr, "At least, GDAL >= 1.5.0 is required for this version of %s, " "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME); exit(1); } GDALAllRegister(); argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 ); if( argc < 1 ) exit( -argc ); const char *pszSrcFilename = nullptr; const char *pszDstFilename = nullptr; int nOrder = 0; void *hTransformArg; GDALTransformerFunc pfnTransformer = nullptr; int nGCPCount = 0; GDAL_GCP *pasGCPs = nullptr; int bInverse = FALSE; CPLStringList aosTO; int bOutputXY = FALSE; double dfX = 0.0; double dfY = 0.0; double dfZ = 0.0; double dfT = 0.0; bool bCoordOnCommandLine = false; /* -------------------------------------------------------------------- */ /* Parse arguments. */ /* -------------------------------------------------------------------- */ for( int i = 1; i < argc && argv[i] != nullptr; i++ ) { if( EQUAL(argv[i], "--utility_version") ) { printf("%s was compiled against GDAL %s and " "is running against GDAL %s\n", argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME")); CSLDestroy(argv); return 0; } else if( EQUAL(argv[i],"--help") ) { Usage(); } else if( EQUAL(argv[i],"-t_srs") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); const char *pszSRS = argv[++i]; if( !IsValidSRS(pszSRS) ) exit(1); aosTO.SetNameValue("DST_SRS", pszSRS ); } else if( EQUAL(argv[i],"-s_srs") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); const char *pszSRS = argv[++i]; if( !IsValidSRS(pszSRS) ) exit(1); aosTO.SetNameValue("SRC_SRS", pszSRS ); } else if( EQUAL(argv[i],"-ct") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); const char *pszCT = argv[++i]; aosTO.SetNameValue("COORDINATE_OPERATION", pszCT ); } else if( EQUAL(argv[i],"-order") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); nOrder = atoi(argv[++i]); aosTO.SetNameValue("MAX_GCP_ORDER", argv[i] ); } else if( EQUAL(argv[i],"-tps") ) { aosTO.SetNameValue("METHOD", "GCP_TPS" ); nOrder = -1; } else if( EQUAL(argv[i],"-rpc") ) { aosTO.SetNameValue("METHOD", "RPC" ); } else if( EQUAL(argv[i],"-geoloc") ) { aosTO.SetNameValue("METHOD", "GEOLOC_ARRAY" ); } else if( EQUAL(argv[i],"-i") ) { bInverse = TRUE; } else if( EQUAL(argv[i],"-to") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); aosTO.AddString( argv[++i] ); } else if( EQUAL(argv[i],"-gcp") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4); char* endptr = nullptr; /* -gcp pixel line easting northing [elev] */ nGCPCount++; pasGCPs = static_cast<GDAL_GCP *>( CPLRealloc(pasGCPs, sizeof(GDAL_GCP) * nGCPCount)); GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 ); pasGCPs[nGCPCount-1].dfGCPPixel = CPLAtof(argv[++i]); pasGCPs[nGCPCount-1].dfGCPLine = CPLAtof(argv[++i]); pasGCPs[nGCPCount-1].dfGCPX = CPLAtof(argv[++i]); pasGCPs[nGCPCount-1].dfGCPY = CPLAtof(argv[++i]); if( argv[i+1] != nullptr && (CPLStrtod(argv[i+1], &endptr) != 0.0 || argv[i+1][0] == '0') ) { // Check that last argument is really a number and not a // filename looking like a number (see ticket #863). if (endptr && *endptr == 0) pasGCPs[nGCPCount-1].dfGCPZ = CPLAtof(argv[++i]); } /* should set id and info? */ } else if( EQUAL(argv[i],"-output_xy") ) { bOutputXY = TRUE; } else if( EQUAL(argv[i],"-coord") && i + 2 < argc) { bCoordOnCommandLine = true; dfX = CPLAtof(argv[++i]); dfY = CPLAtof(argv[++i]); if( i + 1 < argc && CPLGetValueType(argv[i+1]) != CPL_VALUE_STRING ) dfZ = CPLAtof(argv[++i]); if( i + 1 < argc && CPLGetValueType(argv[i+1]) != CPL_VALUE_STRING ) dfT = CPLAtof(argv[++i]); } else if( argv[i][0] == '-' ) { Usage(CPLSPrintf("Unknown option name '%s'", argv[i])); } else if( pszSrcFilename == nullptr ) { pszSrcFilename = argv[i]; } else if( pszDstFilename == nullptr ) { pszDstFilename = argv[i]; } else { Usage("Too many command options."); } } /* -------------------------------------------------------------------- */ /* Open src and destination file, if appropriate. */ /* -------------------------------------------------------------------- */ GDALDatasetH hSrcDS = nullptr; if( pszSrcFilename != nullptr ) { hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly ); if( hSrcDS == nullptr ) exit( 1 ); } GDALDatasetH hDstDS = nullptr; if( pszDstFilename != nullptr ) { hDstDS = GDALOpen( pszDstFilename, GA_ReadOnly ); if( hDstDS == nullptr ) exit( 1 ); } if( hSrcDS != nullptr && nGCPCount > 0 ) { fprintf(stderr, "Command line GCPs and input file specified, " "specify one or the other.\n"); exit( 1 ); } /* -------------------------------------------------------------------- */ /* Create a transformation object from the source to */ /* destination coordinate system. */ /* -------------------------------------------------------------------- */ if( nGCPCount != 0 && nOrder == -1 ) { pfnTransformer = GDALTPSTransform; hTransformArg = GDALCreateTPSTransformer( nGCPCount, pasGCPs, FALSE ); } else if( nGCPCount != 0 ) { pfnTransformer = GDALGCPTransform; hTransformArg = GDALCreateGCPTransformer( nGCPCount, pasGCPs, nOrder, FALSE ); } else { pfnTransformer = GDALGenImgProjTransform; hTransformArg = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, aosTO.List() ); } if( hTransformArg == nullptr ) { exit( 1 ); } /* -------------------------------------------------------------------- */ /* Read points from stdin, transform and write to stdout. */ /* -------------------------------------------------------------------- */ double dfLastT = 0.0; while( bCoordOnCommandLine || !feof(stdin) ) { if( !bCoordOnCommandLine ) { char szLine[1024]; if( fgets( szLine, sizeof(szLine)-1, stdin ) == nullptr ) break; char **papszTokens = CSLTokenizeString(szLine); const int nCount = CSLCount(papszTokens); if( nCount < 2 ) { CSLDestroy(papszTokens); continue; } dfX = CPLAtof(papszTokens[0]); dfY = CPLAtof(papszTokens[1]); if( nCount >= 3 ) dfZ = CPLAtof(papszTokens[2]); else dfZ = 0.0; if( nCount == 4 ) dfT = CPLAtof(papszTokens[3]); else dfT = 0.0; CSLDestroy(papszTokens); } if( dfT != dfLastT && nGCPCount == 0 ) { if( dfT != 0.0 ) { aosTO.SetNameValue("COORDINATE_EPOCH", CPLSPrintf("%g", dfT)); } else { aosTO.SetNameValue("COORDINATE_EPOCH", nullptr); } GDALDestroyGenImgProjTransformer(hTransformArg); hTransformArg = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, aosTO.List() ); } int bSuccess = TRUE; if( pfnTransformer( hTransformArg, bInverse, 1, &dfX, &dfY, &dfZ, &bSuccess ) && bSuccess ) { if( bOutputXY ) CPLprintf( "%.15g %.15g\n", dfX, dfY ); else CPLprintf( "%.15g %.15g %.15g\n", dfX, dfY, dfZ ); } else { printf( "transformation failed.\n" ); } if( bCoordOnCommandLine ) break; dfLastT = dfT; } if( nGCPCount != 0 && nOrder == -1 ) { GDALDestroyTPSTransformer(hTransformArg); } else if( nGCPCount != 0 ) { GDALDestroyGCPTransformer(hTransformArg); } else { GDALDestroyGenImgProjTransformer(hTransformArg); } if (nGCPCount) { GDALDeinitGCPs( nGCPCount, pasGCPs ); CPLFree( pasGCPs ); } if (hSrcDS) GDALClose(hSrcDS); if (hDstDS) GDALClose(hDstDS); GDALDumpOpenDatasets( stderr ); GDALDestroyDriverManager(); CSLDestroy( argv ); return 0; }
void object::test<9>() { // Test some name=value handling stuff *with* sorting active. CPLStringList oNVL; oNVL.Sort(); oNVL.AddNameValue( "KEY1", "VALUE1" ); oNVL.AddNameValue( "2KEY", "VALUE2" ); ensure_equals( "91", oNVL.Count(), 2 ); ensure( "92", EQUAL(oNVL.FetchNameValue("KEY1"),"VALUE1") ); ensure( "93", EQUAL(oNVL.FetchNameValue("2KEY"),"VALUE2") ); ensure( "94", oNVL.FetchNameValue("MISSING") == NULL ); oNVL.AddNameValue( "KEY1", "VALUE3" ); ensure_equals( "95", oNVL.Count(), 3 ); ensure( "96", EQUAL(oNVL.FetchNameValue("KEY1"),"VALUE1") ); ensure( "97", EQUAL(oNVL.FetchNameValueDef("MISSING","X"),"X") ); oNVL.SetNameValue( "2KEY", "VALUE4" ); ensure( "98", EQUAL(oNVL.FetchNameValue("2KEY"),"VALUE4") ); ensure_equals( "99", oNVL.Count(), 3 ); // make sure deletion works. oNVL.SetNameValue( "2KEY", NULL ); ensure( "9a", oNVL.FetchNameValue("2KEY") == NULL ); ensure_equals( "9b", oNVL.Count(), 2 ); // Test insertion logic pretty carefully. oNVL.Clear(); ensure( "9c", oNVL.IsSorted() == TRUE ); oNVL.SetNameValue( "B", "BB" ); oNVL.SetNameValue( "A", "AA" ); oNVL.SetNameValue( "D", "DD" ); oNVL.SetNameValue( "C", "CC" ); // items should be in sorted order. ensure( "9c1", EQUAL(oNVL[0],"A=AA") ); ensure( "9c2", EQUAL(oNVL[1],"B=BB") ); ensure( "9c3", EQUAL(oNVL[2],"C=CC") ); ensure( "9c4", EQUAL(oNVL[3],"D=DD") ); ensure( "9d", EQUAL(oNVL.FetchNameValue("A"),"AA") ); ensure( "9e", EQUAL(oNVL.FetchNameValue("B"),"BB") ); ensure( "9f", EQUAL(oNVL.FetchNameValue("C"),"CC") ); ensure( "9g", EQUAL(oNVL.FetchNameValue("D"),"DD") ); }
void object::test<8>() { // Test some name=value handling stuff. CPLStringList oNVL; oNVL.AddNameValue( "KEY1", "VALUE1" ); oNVL.AddNameValue( "2KEY", "VALUE2" ); ensure_equals( oNVL.Count(), 2 ); ensure( EQUAL(oNVL.FetchNameValue("2KEY"),"VALUE2") ); ensure( oNVL.FetchNameValue("MISSING") == NULL ); oNVL.AddNameValue( "KEY1", "VALUE3" ); ensure( EQUAL(oNVL.FetchNameValue("KEY1"),"VALUE1") ); ensure( EQUAL(oNVL[2],"KEY1=VALUE3") ); ensure( EQUAL(oNVL.FetchNameValueDef("MISSING","X"),"X") ); oNVL.SetNameValue( "2KEY", "VALUE4" ); ensure( EQUAL(oNVL.FetchNameValue("2KEY"),"VALUE4") ); ensure_equals( oNVL.Count(), 3 ); // make sure deletion works. oNVL.SetNameValue( "2KEY", NULL ); ensure( oNVL.FetchNameValue("2KEY") == NULL ); ensure_equals( oNVL.Count(), 2 ); // Test boolean support. ensure_equals( "b1", oNVL.FetchBoolean( "BOOL", TRUE ), TRUE ); ensure_equals( "b2", oNVL.FetchBoolean( "BOOL", FALSE ), FALSE ); oNVL.SetNameValue( "BOOL", "YES" ); ensure_equals( "b3", oNVL.FetchBoolean( "BOOL", TRUE ), TRUE ); ensure_equals( "b4", oNVL.FetchBoolean( "BOOL", FALSE ), TRUE ); oNVL.SetNameValue( "BOOL", "1" ); ensure_equals( "b5", oNVL.FetchBoolean( "BOOL", FALSE ), TRUE ); oNVL.SetNameValue( "BOOL", "0" ); ensure_equals( "b6", oNVL.FetchBoolean( "BOOL", TRUE ), FALSE ); oNVL.SetNameValue( "BOOL", "FALSE" ); ensure_equals( "b7", oNVL.FetchBoolean( "BOOL", TRUE ), FALSE ); oNVL.SetNameValue( "BOOL", "ON" ); ensure_equals( "b8", oNVL.FetchBoolean( "BOOL", FALSE ), TRUE ); // Test assignmenet operator. CPLStringList oCopy; { CPLStringList oTemp; oTemp.AddString("test"); oCopy = oTemp; } ensure( "c1", EQUAL(oCopy[0],"test") ); oCopy = oCopy; ensure( "c2", EQUAL(oCopy[0],"test") ); // Test copy constructor. CPLStringList oCopy2(oCopy); oCopy.Clear(); ensure( "c3", EQUAL(oCopy2[0],"test") ); // Test sorting CPLStringList oTestSort; oTestSort.AddNameValue("Z", "1"); oTestSort.AddNameValue("L", "2"); oTestSort.AddNameValue("T", "3"); oTestSort.AddNameValue("A", "4"); oTestSort.Sort(); ensure( "c4", EQUAL(oTestSort[0],"A=4") ); ensure( "c5", EQUAL(oTestSort[1],"L=2") ); ensure( "c6", EQUAL(oTestSort[2],"T=3") ); ensure( "c7", EQUAL(oTestSort[3],"Z=1") ); ensure_equals( "c8", oTestSort[4], (const char*)NULL ); // Test FetchNameValue() in a sorted list ensure( "c9", EQUAL(oTestSort.FetchNameValue("A"),"4") ); ensure( "c10", EQUAL(oTestSort.FetchNameValue("L"),"2") ); ensure( "c11", EQUAL(oTestSort.FetchNameValue("T"),"3") ); ensure( "c12", EQUAL(oTestSort.FetchNameValue("Z"),"1") ); // Test AddNameValue() in a sorted list oTestSort.AddNameValue("B", "5"); ensure( "c13", EQUAL(oTestSort[0],"A=4") ); ensure( "c14", EQUAL(oTestSort[1],"B=5") ); ensure( "c15", EQUAL(oTestSort[2],"L=2") ); ensure( "c16", EQUAL(oTestSort[3],"T=3") ); ensure( "c17", EQUAL(oTestSort[4],"Z=1") ); ensure_equals( "c18", oTestSort[5], (const char*)NULL ); // Test SetNameValue() of an existing item in a sorted list oTestSort.SetNameValue("Z", "6"); ensure( "c19", EQUAL(oTestSort[4],"Z=6") ); // Test SetNameValue() of a non-existing item in a sorted list oTestSort.SetNameValue("W", "7"); ensure( "c20", EQUAL(oTestSort[0],"A=4") ); ensure( "c21", EQUAL(oTestSort[1],"B=5") ); ensure( "c22", EQUAL(oTestSort[2],"L=2") ); ensure( "c23", EQUAL(oTestSort[3],"T=3") ); ensure( "c24", EQUAL(oTestSort[4],"W=7") ); ensure( "c25", EQUAL(oTestSort[5],"Z=6") ); ensure_equals( "c26", oTestSort[6], (const char*)NULL ); }
void object::test<7>() { CPLStringList oCSL; ensure( "7nil", oCSL.List() == NULL ); oCSL.AddString( "def" ); oCSL.AddString( "abc" ); ensure_equals( "7", oCSL.Count(), 2 ); ensure( "70", EQUAL(oCSL[0], "def") ); ensure( "71", EQUAL(oCSL[1], "abc") ); ensure( "72", oCSL[17] == NULL ); ensure( "73", oCSL[-1] == NULL ); ensure_equals( "74", oCSL.FindString("abc"), 1 ); CSLDestroy( oCSL.StealList() ); ensure_equals( "75", oCSL.Count(), 0 ); ensure( "76", oCSL.List() == NULL ); // Test that the list will make an internal copy when needed to // modify a read-only list. oCSL.AddString( "def" ); oCSL.AddString( "abc" ); CPLStringList oCopy( oCSL.List(), FALSE ); ensure_equals( "77", oCSL.List(), oCopy.List() ); ensure_equals( "78", oCSL.Count(), oCopy.Count() ); oCopy.AddString( "xyz" ); ensure( "79", oCSL.List() != oCopy.List() ); ensure_equals( "7a", oCopy.Count(), 3 ); ensure_equals( "7b", oCSL.Count(), 2 ); ensure( "7c", EQUAL(oCopy[2], "xyz") ); }
bool ConnectionFactory::checkRemoteConnection(const enum ngsCatalogObjectType type, const Options &options) { resetError(); switch(type) { case CAT_CONTAINER_NGW: { std::string url = options.asString(KEY_URL); if(url.empty()) { return errorMessage(_("Missing required option 'url'")); } std::string login = options.asString(KEY_LOGIN); if(login.empty()) { login = "******"; } else { std::string oldLogin(login); login = CPLString(login).Trim(); if(!compare(oldLogin, login, true)) { warningMessage("Login was trimmed!"); } } std::string password = options.asString(KEY_PASSWORD); CPLStringList requestOptions; std::string headers = "Accept: */*"; Options authOptions; authOptions.add(KEY_TYPE, "basic"); authOptions.add(KEY_LOGIN, login); authOptions.add(KEY_PASSWORD, password); AuthStore::authAdd(url, authOptions); std::string auth = AuthStore::authHeader(url); AuthStore::authRemove(url); if(!auth.empty()) { headers += "\r\n"; headers += auth; } requestOptions.AddNameValue("HEADERS", headers.c_str()); CPLJSONDocument checkReq; if(!checkReq.LoadUrl(ngw::getCurrentUserUrl(url), requestOptions)) { return errorMessage(CPLGetLastErrorMsg()); } CPLJSONObject root = checkReq.GetRoot(); if(!root.IsValid()) { return errorMessage(_("Response is invalid")); } if(root.GetString("keyname") == login) { return true; } return errorMessage(_("User '%s' failed to connect to %s."), login.c_str(), url.c_str()); } default: return errorMessage(_("Unsupported connection type %d"), type); } }
/** Load proj.4 geoidgrids as GDAL dataset * * @param pszProj4Geoidgrids Value of proj.4 geoidgrids parameter. * @param pbError If not NULL, the pointed value will be set to TRUE if an * error occurred. * * @return a dataset. If not NULL, it must be closed with GDALClose(). * * @since GDAL 2.2 */ GDALDatasetH GDALOpenVerticalShiftGrid( const char* pszProj4Geoidgrids, int* pbError ) { char** papszGrids = CSLTokenizeString2( pszProj4Geoidgrids, ",", 0); const int nGridCount = CSLCount(papszGrids); if( nGridCount == 1 ) { CSLDestroy(papszGrids); bool bMissingOk = false; if( *pszProj4Geoidgrids == '@' ) { pszProj4Geoidgrids ++; bMissingOk = true; } const CPLString osFilename(GetProj4Filename(pszProj4Geoidgrids)); const char* const papszOpenOptions[] = { "@SHIFT_ORIGIN_IN_MINUS_180_PLUS_180=YES", nullptr }; GDALDatasetH hDS = GDALOpenEx(osFilename, 0, nullptr, papszOpenOptions, nullptr); if( hDS == nullptr ) { CPLDebug("GDAL", "Cannot find file corresponding to %s", pszProj4Geoidgrids); } if( pbError ) *pbError = (!bMissingOk && hDS == nullptr); return hDS; } CPLStringList aosFilenames; for( int i = nGridCount - 1; i >= 0; i-- ) { const char* pszName = papszGrids[i]; bool bMissingOk = false; if( *pszName == '@' ) { pszName ++; bMissingOk = true; } const CPLString osFilename(GetProj4Filename(pszName)); VSIStatBufL sStat; if( osFilename.empty() || VSIStatL(osFilename, &sStat) != 0 ) { CPLDebug("GDAL", "Cannot find file corresponding to %s", pszName); if( !bMissingOk ) { if( pbError ) *pbError = true; CSLDestroy(papszGrids); return nullptr; } } else { aosFilenames.AddString(osFilename); } } CSLDestroy(papszGrids); if( aosFilenames.empty() ) { if( pbError ) *pbError = false; return nullptr; } char** papszArgv = nullptr; papszArgv = CSLAddString(papszArgv, "-resolution"); papszArgv = CSLAddString(papszArgv, "highest"); papszArgv = CSLAddString(papszArgv, "-vrtnodata"); papszArgv = CSLAddString(papszArgv, "-inf"); papszArgv = CSLAddString(papszArgv, "-oo"); papszArgv = CSLAddString(papszArgv, "@SHIFT_ORIGIN_IN_MINUS_180_PLUS_180=YES"); GDALBuildVRTOptions* psOptions = GDALBuildVRTOptionsNew(papszArgv, nullptr); CSLDestroy(papszArgv); GDALDatasetH hDS = GDALBuildVRT( "", aosFilenames.size(), nullptr, aosFilenames.List(), psOptions, nullptr ); GDALBuildVRTOptionsFree( psOptions ); if( pbError ) *pbError = hDS != nullptr; return hDS; }