1 /******************************************************************************
2 *
3 * Project: GDAL Utilities
4 * Purpose: Common utility routines
5 * Author: Even Rouault, <even dot rouault at spatialys.com>
6 *
7 ******************************************************************************
8 * Copyright (c) 2011-2012, Even Rouault <even dot rouault at spatialys.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ****************************************************************************/
28
29 #include "commonutils.h"
30
31 #include <cstdio>
32 #include <cstring>
33
34 #include <string>
35
36 #include "cpl_conv.h"
37 #include "cpl_string.h"
38 #include "gdal.h"
39
40 CPL_CVSID("$Id: commonutils.cpp a7cdc486d524bef67fe59ab48bff81c8880be984 2019-06-22 19:30:01 +0200 Even Rouault $")
41
42 /* -------------------------------------------------------------------- */
43 /* DoesDriverHandleExtension() */
44 /* -------------------------------------------------------------------- */
45
DoesDriverHandleExtension(GDALDriverH hDriver,const char * pszExt)46 static bool DoesDriverHandleExtension( GDALDriverH hDriver, const char* pszExt )
47 {
48 bool bRet = false;
49 const char* pszDriverExtensions =
50 GDALGetMetadataItem( hDriver, GDAL_DMD_EXTENSIONS, nullptr );
51 if( pszDriverExtensions )
52 {
53 char** papszTokens = CSLTokenizeString( pszDriverExtensions );
54 for( int j = 0; papszTokens[j]; j++ )
55 {
56 if( EQUAL(pszExt, papszTokens[j]) )
57 {
58 bRet = true;
59 break;
60 }
61 }
62 CSLDestroy(papszTokens);
63 }
64 return bRet;
65 }
66
67 /* -------------------------------------------------------------------- */
68 /* GetOutputDriversFor() */
69 /* -------------------------------------------------------------------- */
70
GetOutputDriversFor(const char * pszDestFilename,int nFlagRasterVector)71 std::vector<CPLString> GetOutputDriversFor(const char* pszDestFilename,
72 int nFlagRasterVector)
73 {
74 std::vector<CPLString> aoDriverList;
75
76 CPLString osExt = CPLGetExtension(pszDestFilename);
77 if( EQUAL(osExt, "zip") &&
78 (CPLString(pszDestFilename).endsWith(".shp.zip") ||
79 CPLString(pszDestFilename).endsWith(".SHP.ZIP")) )
80 {
81 osExt = "shp.zip";
82 }
83 const int nDriverCount = GDALGetDriverCount();
84 for( int i = 0; i < nDriverCount; i++ )
85 {
86 GDALDriverH hDriver = GDALGetDriver(i);
87 if( (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, nullptr ) != nullptr ||
88 GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, nullptr ) != nullptr ) &&
89 (((nFlagRasterVector & GDAL_OF_RASTER) &&
90 GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, nullptr ) != nullptr) ||
91 ((nFlagRasterVector & GDAL_OF_VECTOR) &&
92 GDALGetMetadataItem( hDriver, GDAL_DCAP_VECTOR, nullptr ) != nullptr)) )
93 {
94 if( !osExt.empty() && DoesDriverHandleExtension(hDriver, osExt) )
95 {
96 aoDriverList.push_back( GDALGetDriverShortName(hDriver) );
97 }
98 else
99 {
100 const char* pszPrefix = GDALGetMetadataItem(hDriver,
101 GDAL_DMD_CONNECTION_PREFIX, nullptr);
102 if( pszPrefix && STARTS_WITH_CI(pszDestFilename, pszPrefix) )
103 {
104 aoDriverList.push_back( GDALGetDriverShortName(hDriver) );
105 }
106 }
107 }
108 }
109
110 // GMT is registered before netCDF for opening reasons, but we want
111 // netCDF to be used by default for output.
112 if( EQUAL(osExt, "nc") && aoDriverList.size() == 2 &&
113 EQUAL(aoDriverList[0], "GMT") && EQUAL(aoDriverList[1], "NETCDF") )
114 {
115 aoDriverList.clear();
116 aoDriverList.push_back("NETCDF");
117 aoDriverList.push_back("GMT");
118 }
119
120 return aoDriverList;
121 }
122
123 /* -------------------------------------------------------------------- */
124 /* GetOutputDriverForRaster() */
125 /* -------------------------------------------------------------------- */
126
GetOutputDriverForRaster(const char * pszDestFilename)127 CPLString GetOutputDriverForRaster(const char* pszDestFilename)
128 {
129 CPLString osFormat;
130 std::vector<CPLString> aoDrivers =
131 GetOutputDriversFor(pszDestFilename, GDAL_OF_RASTER);
132 CPLString osExt(CPLGetExtension(pszDestFilename));
133 if( aoDrivers.empty() )
134 {
135 if( osExt.empty() )
136 {
137 osFormat = "GTiff";
138 }
139 else
140 {
141 CPLError( CE_Failure, CPLE_AppDefined,
142 "Cannot guess driver for %s", pszDestFilename);
143 return "";
144 }
145 }
146 else
147 {
148 if( aoDrivers.size() > 1 )
149 {
150 CPLError( CE_Warning, CPLE_AppDefined,
151 "Several drivers matching %s extension. Using %s",
152 osExt.c_str(),
153 aoDrivers[0].c_str() );
154 }
155 osFormat = aoDrivers[0];
156 }
157 CPLDebug("GDAL", "Using %s driver", osFormat.c_str());
158 return osFormat;
159 }
160
161 /* -------------------------------------------------------------------- */
162 /* EarlySetConfigOptions() */
163 /* -------------------------------------------------------------------- */
164
EarlySetConfigOptions(int argc,char ** argv)165 void EarlySetConfigOptions( int argc, char ** argv )
166 {
167 // Must process some config options before GDALAllRegister() or
168 // OGRRegisterAll(), but we can't call GDALGeneralCmdLineProcessor() or
169 // OGRGeneralCmdLineProcessor(), because it needs the drivers to be
170 // registered for the --format or --formats options.
171 for( int i = 1; i < argc; i++ )
172 {
173 if( EQUAL(argv[i],"--config") && i + 2 < argc )
174 {
175 CPLSetConfigOption( argv[i+1], argv[i+2] );
176
177 i += 2;
178 }
179 else if( EQUAL(argv[i],"--debug") && i + 1 < argc )
180 {
181 CPLSetConfigOption( "CPL_DEBUG", argv[i+1] );
182 i += 1;
183 }
184 }
185 }
186