/src/gdal/apps/commonutils.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | * SPDX-License-Identifier: MIT |
11 | | ****************************************************************************/ |
12 | | |
13 | | #include "commonutils.h" |
14 | | |
15 | | #include <cstdio> |
16 | | #include <cstring> |
17 | | |
18 | | #include <string> |
19 | | |
20 | | #include "cpl_conv.h" |
21 | | #include "cpl_string.h" |
22 | | #include "gdal.h" |
23 | | |
24 | | /* -------------------------------------------------------------------- */ |
25 | | /* GetOutputDriversFor() */ |
26 | | /* -------------------------------------------------------------------- */ |
27 | | |
28 | | std::vector<std::string> GetOutputDriversFor(const char *pszDestFilename, |
29 | | int nFlagRasterVector) |
30 | 0 | { |
31 | 0 | return CPLStringList(GDALGetOutputDriversForDatasetName( |
32 | 0 | pszDestFilename, nFlagRasterVector, /* bSingleMatch = */ false, |
33 | 0 | /* bEmitWarning = */ false)); |
34 | 0 | } |
35 | | |
36 | | /* -------------------------------------------------------------------- */ |
37 | | /* GetOutputDriverForRaster() */ |
38 | | /* -------------------------------------------------------------------- */ |
39 | | |
40 | | CPLString GetOutputDriverForRaster(const char *pszDestFilename) |
41 | 0 | { |
42 | 0 | const CPLStringList aosList(GDALGetOutputDriversForDatasetName( |
43 | 0 | pszDestFilename, GDAL_OF_RASTER, /* bSingleMatch = */ true, |
44 | 0 | /* bEmitWarning = */ true)); |
45 | 0 | if (!aosList.empty()) |
46 | 0 | { |
47 | 0 | CPLDebug("GDAL", "Using %s driver", aosList[0]); |
48 | 0 | return aosList[0]; |
49 | 0 | } |
50 | 0 | return CPLString(); |
51 | 0 | } |
52 | | |
53 | | /* -------------------------------------------------------------------- */ |
54 | | /* EarlySetConfigOptions() */ |
55 | | /* -------------------------------------------------------------------- */ |
56 | | |
57 | | void EarlySetConfigOptions(int argc, char **argv) |
58 | 0 | { |
59 | | // Must process some config options before GDALAllRegister() or |
60 | | // OGRRegisterAll(), but we can't call GDALGeneralCmdLineProcessor() or |
61 | | // OGRGeneralCmdLineProcessor(), because it needs the drivers to be |
62 | | // registered for the --format or --formats options. |
63 | | |
64 | | // Start with --debug, so that "my_command --config UNKNOWN_CONFIG_OPTION --debug on" |
65 | | // detects and warns about a unknown config option. |
66 | 0 | for (int i = 1; i < argc; i++) |
67 | 0 | { |
68 | 0 | if (EQUAL(argv[i], "--config") && i + 1 < argc) |
69 | 0 | { |
70 | 0 | const char *pszArg = argv[i + 1]; |
71 | 0 | if (strchr(pszArg, '=') != nullptr) |
72 | 0 | { |
73 | 0 | char *pszKey = nullptr; |
74 | 0 | const char *pszValue = CPLParseNameValue(pszArg, &pszKey); |
75 | 0 | if (pszKey && EQUAL(pszKey, "CPL_DEBUG") && pszValue) |
76 | 0 | { |
77 | 0 | CPLSetConfigOption(pszKey, pszValue); |
78 | 0 | } |
79 | 0 | CPLFree(pszKey); |
80 | 0 | ++i; |
81 | 0 | } |
82 | 0 | else |
83 | 0 | { |
84 | 0 | if (i + 2 >= argc) |
85 | 0 | { |
86 | 0 | CPLError(CE_Failure, CPLE_AppDefined, |
87 | 0 | "--config option given without a key and value " |
88 | 0 | "argument."); |
89 | 0 | return; |
90 | 0 | } |
91 | | |
92 | 0 | if (EQUAL(argv[i + 1], "CPL_DEBUG")) |
93 | 0 | { |
94 | 0 | CPLSetConfigOption(argv[i + 1], argv[i + 2]); |
95 | 0 | } |
96 | |
|
97 | 0 | i += 2; |
98 | 0 | } |
99 | 0 | } |
100 | 0 | else if (EQUAL(argv[i], "--debug") && i + 1 < argc) |
101 | 0 | { |
102 | 0 | CPLSetConfigOption("CPL_DEBUG", argv[i + 1]); |
103 | 0 | i += 1; |
104 | 0 | } |
105 | 0 | } |
106 | 0 | for (int i = 1; i < argc; i++) |
107 | 0 | { |
108 | 0 | if (EQUAL(argv[i], "--config") && i + 1 < argc) |
109 | 0 | { |
110 | 0 | const char *pszArg = argv[i + 1]; |
111 | 0 | if (strchr(pszArg, '=') != nullptr) |
112 | 0 | { |
113 | 0 | char *pszKey = nullptr; |
114 | 0 | const char *pszValue = CPLParseNameValue(pszArg, &pszKey); |
115 | 0 | if (pszKey && !EQUAL(pszKey, "CPL_DEBUG") && pszValue) |
116 | 0 | { |
117 | 0 | CPLSetConfigOption(pszKey, pszValue); |
118 | 0 | } |
119 | 0 | CPLFree(pszKey); |
120 | 0 | ++i; |
121 | 0 | } |
122 | 0 | else |
123 | 0 | { |
124 | 0 | if (i + 2 >= argc) |
125 | 0 | { |
126 | 0 | CPLError(CE_Failure, CPLE_AppDefined, |
127 | 0 | "--config option given without a key and value " |
128 | 0 | "argument."); |
129 | 0 | return; |
130 | 0 | } |
131 | | |
132 | 0 | if (!EQUAL(argv[i + 1], "CPL_DEBUG")) |
133 | 0 | { |
134 | 0 | CPLSetConfigOption(argv[i + 1], argv[i + 2]); |
135 | 0 | } |
136 | |
|
137 | 0 | i += 2; |
138 | 0 | } |
139 | 0 | } |
140 | 0 | } |
141 | 0 | } |
142 | | |
143 | | /************************************************************************/ |
144 | | /* GDALRemoveBOM() */ |
145 | | /************************************************************************/ |
146 | | |
147 | | /* Remove potential UTF-8 BOM from data (must be NUL terminated) */ |
148 | | void GDALRemoveBOM(GByte *pabyData) |
149 | 0 | { |
150 | 0 | if (pabyData[0] == 0xEF && pabyData[1] == 0xBB && pabyData[2] == 0xBF) |
151 | 0 | { |
152 | 0 | memmove(pabyData, pabyData + 3, |
153 | 0 | strlen(reinterpret_cast<char *>(pabyData) + 3) + 1); |
154 | 0 | } |
155 | 0 | } |
156 | | |
157 | | /************************************************************************/ |
158 | | /* ArgIsNumeric() */ |
159 | | /************************************************************************/ |
160 | | |
161 | | int ArgIsNumeric(const char *pszArg) |
162 | | |
163 | 0 | { |
164 | 0 | return CPLGetValueType(pszArg) != CPL_VALUE_STRING; |
165 | 0 | } |
166 | | |
167 | | /************************************************************************/ |
168 | | /* GDALPatternMatch() */ |
169 | | /************************************************************************/ |
170 | | |
171 | | bool GDALPatternMatch(const char *input, const char *pattern) |
172 | | |
173 | 0 | { |
174 | 0 | while (*input != '\0') |
175 | 0 | { |
176 | 0 | if (*pattern == '\0') |
177 | 0 | return false; |
178 | | |
179 | 0 | else if (*pattern == '?') |
180 | 0 | { |
181 | 0 | pattern++; |
182 | 0 | if (static_cast<unsigned int>(*input) > 127) |
183 | 0 | { |
184 | | // Continuation bytes of such characters are of the form |
185 | | // 10xxxxxx (0x80), whereas single-byte are 0xxxxxxx |
186 | | // and the start of a multi-byte is 11xxxxxx |
187 | 0 | do |
188 | 0 | { |
189 | 0 | input++; |
190 | 0 | } while (static_cast<unsigned int>(*input) > 127); |
191 | 0 | } |
192 | 0 | else |
193 | 0 | { |
194 | 0 | input++; |
195 | 0 | } |
196 | 0 | } |
197 | 0 | else if (*pattern == '*') |
198 | 0 | { |
199 | 0 | if (pattern[1] == '\0') |
200 | 0 | return true; |
201 | | |
202 | | // Try eating varying amounts of the input till we get a positive. |
203 | 0 | for (int eat = 0; input[eat] != '\0'; eat++) |
204 | 0 | { |
205 | 0 | if (GDALPatternMatch(input + eat, pattern + 1)) |
206 | 0 | return true; |
207 | 0 | } |
208 | | |
209 | 0 | return false; |
210 | 0 | } |
211 | 0 | else |
212 | 0 | { |
213 | 0 | if (CPLTolower(*pattern) != CPLTolower(*input)) |
214 | 0 | { |
215 | 0 | return false; |
216 | 0 | } |
217 | 0 | else |
218 | 0 | { |
219 | 0 | input++; |
220 | 0 | pattern++; |
221 | 0 | } |
222 | 0 | } |
223 | 0 | } |
224 | | |
225 | 0 | if (*pattern != '\0' && strcmp(pattern, "*") != 0) |
226 | 0 | return false; |
227 | 0 | else |
228 | 0 | return true; |
229 | 0 | } |