Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: GDALAlgorithm class
5 : * Author: Even Rouault <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef GDAL_ALGORITHM_INCLUDED
14 : #define GDAL_ALGORITHM_INCLUDED
15 :
16 : #include "cpl_port.h"
17 : #include "cpl_progress.h"
18 :
19 : #include "gdal.h"
20 :
21 : /************************************************************************/
22 : /************************************************************************/
23 : /* GDAL Algorithm C API */
24 : /************************************************************************/
25 : /************************************************************************/
26 :
27 : CPL_C_START
28 :
29 : /** Type of an argument */
30 : typedef enum GDALAlgorithmArgType
31 : {
32 : /** Boolean type. Value is a bool. */
33 : GAAT_BOOLEAN,
34 : /** Single-value string type. Value is a std::string */
35 : GAAT_STRING,
36 : /** Single-value integer type. Value is a int */
37 : GAAT_INTEGER,
38 : /** Single-value real type. Value is a double */
39 : GAAT_REAL,
40 : /** Dataset type. Value is a GDALArgDatasetValue */
41 : GAAT_DATASET,
42 : /** Multi-value string type. Value is a std::vector<std::string> */
43 : GAAT_STRING_LIST,
44 : /** Multi-value integer type. Value is a std::vector<int> */
45 : GAAT_INTEGER_LIST,
46 : /** Multi-value real type. Value is a std::vector<double> */
47 : GAAT_REAL_LIST,
48 : /** Multi-value dataset type. Value is a std::vector<GDALArgDatasetValue> */
49 : GAAT_DATASET_LIST,
50 : } GDALAlgorithmArgType;
51 :
52 : /** Return whether the argument type is a list / multi-valued one. */
53 : bool CPL_DLL GDALAlgorithmArgTypeIsList(GDALAlgorithmArgType type);
54 :
55 : /** Return the string representation of the argument type */
56 : const char CPL_DLL *GDALAlgorithmArgTypeName(GDALAlgorithmArgType type);
57 :
58 : /** Opaque C type for GDALArgDatasetValue */
59 : typedef struct GDALArgDatasetValueHS *GDALArgDatasetValueH;
60 :
61 : /** Opaque C type for GDALAlgorithmArg */
62 : typedef struct GDALAlgorithmArgHS *GDALAlgorithmArgH;
63 :
64 : /** Opaque C type for GDALAlgorithm */
65 : typedef struct GDALAlgorithmHS *GDALAlgorithmH;
66 :
67 : /** Opaque C type for GDALAlgorithmRegistry */
68 : typedef struct GDALAlgorithmRegistryHS *GDALAlgorithmRegistryH;
69 :
70 : /************************************************************************/
71 : /* GDALAlgorithmRegistryH API */
72 : /************************************************************************/
73 :
74 : GDALAlgorithmRegistryH CPL_DLL GDALGetGlobalAlgorithmRegistry(void);
75 :
76 : void CPL_DLL GDALAlgorithmRegistryRelease(GDALAlgorithmRegistryH);
77 :
78 : char CPL_DLL **GDALAlgorithmRegistryGetAlgNames(GDALAlgorithmRegistryH);
79 :
80 : GDALAlgorithmH CPL_DLL GDALAlgorithmRegistryInstantiateAlg(
81 : GDALAlgorithmRegistryH, const char *pszAlgName);
82 :
83 : /************************************************************************/
84 : /* GDALAlgorithmH API */
85 : /************************************************************************/
86 :
87 : void CPL_DLL GDALAlgorithmRelease(GDALAlgorithmH);
88 :
89 : const char CPL_DLL *GDALAlgorithmGetName(GDALAlgorithmH);
90 :
91 : const char CPL_DLL *GDALAlgorithmGetDescription(GDALAlgorithmH);
92 :
93 : const char CPL_DLL *GDALAlgorithmGetLongDescription(GDALAlgorithmH);
94 :
95 : const char CPL_DLL *GDALAlgorithmGetHelpFullURL(GDALAlgorithmH);
96 :
97 : bool CPL_DLL GDALAlgorithmHasSubAlgorithms(GDALAlgorithmH);
98 :
99 : char CPL_DLL **GDALAlgorithmGetSubAlgorithmNames(GDALAlgorithmH);
100 :
101 : GDALAlgorithmH CPL_DLL
102 : GDALAlgorithmInstantiateSubAlgorithm(GDALAlgorithmH, const char *pszSubAlgName);
103 :
104 : bool CPL_DLL GDALAlgorithmParseCommandLineArguments(GDALAlgorithmH,
105 : CSLConstList papszArgs);
106 :
107 : GDALAlgorithmH CPL_DLL GDALAlgorithmGetActualAlgorithm(GDALAlgorithmH);
108 :
109 : bool CPL_DLL GDALAlgorithmRun(GDALAlgorithmH, GDALProgressFunc pfnProgress,
110 : void *pProgressData);
111 :
112 : bool CPL_DLL GDALAlgorithmFinalize(GDALAlgorithmH);
113 :
114 : char CPL_DLL *GDALAlgorithmGetUsageAsJSON(GDALAlgorithmH);
115 :
116 : char CPL_DLL **GDALAlgorithmGetArgNames(GDALAlgorithmH);
117 :
118 : GDALAlgorithmArgH CPL_DLL GDALAlgorithmGetArg(GDALAlgorithmH,
119 : const char *pszArgName);
120 :
121 : GDALAlgorithmArgH CPL_DLL GDALAlgorithmGetArgNonConst(GDALAlgorithmH,
122 : const char *pszArgName);
123 :
124 : /************************************************************************/
125 : /* GDALAlgorithmArgH API */
126 : /************************************************************************/
127 :
128 : void CPL_DLL GDALAlgorithmArgRelease(GDALAlgorithmArgH);
129 :
130 : const char CPL_DLL *GDALAlgorithmArgGetName(GDALAlgorithmArgH);
131 :
132 : GDALAlgorithmArgType CPL_DLL GDALAlgorithmArgGetType(GDALAlgorithmArgH);
133 :
134 : const char CPL_DLL *GDALAlgorithmArgGetDescription(GDALAlgorithmArgH);
135 :
136 : const char CPL_DLL *GDALAlgorithmArgGetShortName(GDALAlgorithmArgH);
137 :
138 : char CPL_DLL **GDALAlgorithmArgGetAliases(GDALAlgorithmArgH);
139 :
140 : const char CPL_DLL *GDALAlgorithmArgGetMetaVar(GDALAlgorithmArgH);
141 :
142 : const char CPL_DLL *GDALAlgorithmArgGetCategory(GDALAlgorithmArgH);
143 :
144 : bool CPL_DLL GDALAlgorithmArgIsPositional(GDALAlgorithmArgH);
145 :
146 : bool CPL_DLL GDALAlgorithmArgIsRequired(GDALAlgorithmArgH);
147 :
148 : int CPL_DLL GDALAlgorithmArgGetMinCount(GDALAlgorithmArgH);
149 :
150 : int CPL_DLL GDALAlgorithmArgGetMaxCount(GDALAlgorithmArgH);
151 :
152 : bool CPL_DLL GDALAlgorithmArgGetPackedValuesAllowed(GDALAlgorithmArgH);
153 :
154 : bool CPL_DLL GDALAlgorithmArgGetRepeatedArgAllowed(GDALAlgorithmArgH);
155 :
156 : char CPL_DLL **GDALAlgorithmArgGetChoices(GDALAlgorithmArgH);
157 :
158 : char CPL_DLL **GDALAlgorithmArgGetMetadataItem(GDALAlgorithmArgH, const char *);
159 :
160 : bool CPL_DLL GDALAlgorithmArgIsExplicitlySet(GDALAlgorithmArgH);
161 :
162 : bool CPL_DLL GDALAlgorithmArgHasDefaultValue(GDALAlgorithmArgH);
163 :
164 : bool CPL_DLL GDALAlgorithmArgGetDefaultAsBoolean(GDALAlgorithmArgH);
165 :
166 : const char CPL_DLL *GDALAlgorithmArgGetDefaultAsString(GDALAlgorithmArgH);
167 :
168 : int CPL_DLL GDALAlgorithmArgGetDefaultAsInteger(GDALAlgorithmArgH);
169 :
170 : double CPL_DLL GDALAlgorithmArgGetDefaultAsDouble(GDALAlgorithmArgH);
171 :
172 : char CPL_DLL **GDALAlgorithmArgGetDefaultAsStringList(GDALAlgorithmArgH);
173 :
174 : const int CPL_DLL *GDALAlgorithmArgGetDefaultAsIntegerList(GDALAlgorithmArgH,
175 : size_t *pnCount);
176 :
177 : const double CPL_DLL *GDALAlgorithmArgGetDefaultAsDoubleList(GDALAlgorithmArgH,
178 : size_t *pnCount);
179 :
180 : bool CPL_DLL GDALAlgorithmArgIsHidden(GDALAlgorithmArgH);
181 :
182 : bool CPL_DLL GDALAlgorithmArgIsHiddenForCLI(GDALAlgorithmArgH);
183 :
184 : bool CPL_DLL GDALAlgorithmArgIsHiddenForAPI(GDALAlgorithmArgH);
185 :
186 : bool CPL_DLL GDALAlgorithmArgIsOnlyForCLI(GDALAlgorithmArgH)
187 : CPL_WARN_DEPRECATED("Use GDALAlgorithmArgIsHiddenForAPI() instead");
188 :
189 : bool CPL_DLL GDALAlgorithmArgIsInput(GDALAlgorithmArgH);
190 :
191 : bool CPL_DLL GDALAlgorithmArgIsOutput(GDALAlgorithmArgH);
192 :
193 : const char CPL_DLL *GDALAlgorithmArgGetMutualExclusionGroup(GDALAlgorithmArgH);
194 :
195 : bool CPL_DLL GDALAlgorithmArgGetAsBoolean(GDALAlgorithmArgH);
196 :
197 : const char CPL_DLL *GDALAlgorithmArgGetAsString(GDALAlgorithmArgH);
198 :
199 : GDALArgDatasetValueH
200 : CPL_DLL GDALAlgorithmArgGetAsDatasetValue(GDALAlgorithmArgH);
201 :
202 : int CPL_DLL GDALAlgorithmArgGetAsInteger(GDALAlgorithmArgH);
203 :
204 : double CPL_DLL GDALAlgorithmArgGetAsDouble(GDALAlgorithmArgH);
205 :
206 : char CPL_DLL **GDALAlgorithmArgGetAsStringList(GDALAlgorithmArgH);
207 :
208 : const int CPL_DLL *GDALAlgorithmArgGetAsIntegerList(GDALAlgorithmArgH,
209 : size_t *pnCount);
210 :
211 : const double CPL_DLL *GDALAlgorithmArgGetAsDoubleList(GDALAlgorithmArgH,
212 : size_t *pnCount);
213 :
214 : bool CPL_DLL GDALAlgorithmArgSetAsBoolean(GDALAlgorithmArgH, bool);
215 :
216 : bool CPL_DLL GDALAlgorithmArgSetAsString(GDALAlgorithmArgH, const char *);
217 :
218 : bool CPL_DLL GDALAlgorithmArgSetAsDatasetValue(GDALAlgorithmArgH hArg,
219 : GDALArgDatasetValueH value);
220 :
221 : bool CPL_DLL GDALAlgorithmArgSetDataset(GDALAlgorithmArgH hArg, GDALDatasetH);
222 :
223 : bool CPL_DLL GDALAlgorithmArgSetDatasets(GDALAlgorithmArgH hArg, size_t nCount,
224 : GDALDatasetH *);
225 :
226 : bool CPL_DLL GDALAlgorithmArgSetDatasetNames(GDALAlgorithmArgH hArg,
227 : CSLConstList);
228 :
229 : bool CPL_DLL GDALAlgorithmArgSetAsInteger(GDALAlgorithmArgH, int);
230 :
231 : bool CPL_DLL GDALAlgorithmArgSetAsDouble(GDALAlgorithmArgH, double);
232 :
233 : bool CPL_DLL GDALAlgorithmArgSetAsStringList(GDALAlgorithmArgH, CSLConstList);
234 :
235 : bool CPL_DLL GDALAlgorithmArgSetAsIntegerList(GDALAlgorithmArgH, size_t nCount,
236 : const int *pnValues);
237 :
238 : bool CPL_DLL GDALAlgorithmArgSetAsDoubleList(GDALAlgorithmArgH, size_t nCount,
239 : const double *pnValues);
240 :
241 : /** Binary-or combination of GDAL_OF_RASTER, GDAL_OF_VECTOR,
242 : * GDAL_OF_MULTIDIM_RASTER, possibly with GDAL_OF_UPDATE.
243 : */
244 : typedef int GDALArgDatasetType;
245 :
246 : GDALArgDatasetType CPL_DLL GDALAlgorithmArgGetDatasetType(GDALAlgorithmArgH);
247 :
248 : /** Bit indicating that the name component of GDALArgDatasetValue is accepted. */
249 : #define GADV_NAME (1 << 0)
250 : /** Bit indicating that the dataset component of GDALArgDatasetValue is accepted. */
251 : #define GADV_OBJECT (1 << 1)
252 :
253 : int CPL_DLL GDALAlgorithmArgGetDatasetInputFlags(GDALAlgorithmArgH);
254 :
255 : int CPL_DLL GDALAlgorithmArgGetDatasetOutputFlags(GDALAlgorithmArgH);
256 :
257 : /************************************************************************/
258 : /* GDALArgDatasetValueH API */
259 : /************************************************************************/
260 :
261 : GDALArgDatasetValueH CPL_DLL GDALArgDatasetValueCreate(void);
262 :
263 : void CPL_DLL GDALArgDatasetValueRelease(GDALArgDatasetValueH);
264 :
265 : const char CPL_DLL *GDALArgDatasetValueGetName(GDALArgDatasetValueH);
266 :
267 : GDALDatasetH CPL_DLL GDALArgDatasetValueGetDatasetRef(GDALArgDatasetValueH);
268 :
269 : GDALDatasetH
270 : CPL_DLL GDALArgDatasetValueGetDatasetIncreaseRefCount(GDALArgDatasetValueH);
271 :
272 : void CPL_DLL GDALArgDatasetValueSetName(GDALArgDatasetValueH, const char *);
273 :
274 : void CPL_DLL GDALArgDatasetValueSetDataset(GDALArgDatasetValueH, GDALDatasetH);
275 :
276 : CPL_C_END
277 :
278 : /************************************************************************/
279 : /************************************************************************/
280 : /* GDAL Algorithm C++ API */
281 : /************************************************************************/
282 : /************************************************************************/
283 :
284 : // The rest of this header requires C++17
285 : // _MSC_VER >= 1920 : Visual Studio >= 2019
286 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS) && \
287 : (defined(DOXYGEN_SKIP) || __cplusplus >= 201703L || _MSC_VER >= 1920)
288 :
289 : #include "cpl_error.h"
290 :
291 : #include <limits>
292 : #include <functional>
293 : #include <map>
294 : #include <memory>
295 : #include <string>
296 : #include <string_view>
297 : #include <type_traits>
298 : #include <utility>
299 : #include <variant>
300 : #include <vector>
301 :
302 : class GDALDataset;
303 : class OGRSpatialReference;
304 :
305 : /** Common argument category */
306 : constexpr const char *GAAC_COMMON = "Common";
307 :
308 : /** Base argument category */
309 : constexpr const char *GAAC_BASE = "Base";
310 :
311 : /** Advanced argument category */
312 : constexpr const char *GAAC_ADVANCED = "Advanced";
313 :
314 : /** Esoteric argument category */
315 : constexpr const char *GAAC_ESOTERIC = "Esoteric";
316 :
317 : /** Argument metadata item that applies to the "input-format" and
318 : * "output-format" argument */
319 : constexpr const char *GAAMDI_REQUIRED_CAPABILITIES = "required_capabilities";
320 :
321 : /** Argument metadata item that applies to "output-format" argument */
322 : constexpr const char *GAAMDI_VRT_COMPATIBLE = "vrt_compatible";
323 :
324 : /** Argument metadata item that applies to "output-format" argument */
325 : constexpr const char *GAAMDI_ALLOWED_FORMATS = "allowed_formats";
326 :
327 : /** Argument metadata item that applies to "output-format" argument */
328 : constexpr const char *GAAMDI_EXCLUDED_FORMATS = "excluded_formats";
329 :
330 : /** Name of the argument for an input dataset. */
331 : constexpr const char *GDAL_ARG_NAME_INPUT = "input";
332 :
333 : /** Name of the argument for the input format. */
334 : constexpr const char *GDAL_ARG_NAME_INPUT_FORMAT = "input-format";
335 :
336 : /** Name of the argument for the input layer. */
337 : constexpr const char *GDAL_ARG_NAME_INPUT_LAYER = "input-layer";
338 :
339 : /** Name of the argument for an open option. */
340 : constexpr const char *GDAL_ARG_NAME_OPEN_OPTION = "open-option";
341 :
342 : /** Name of the argument for an output dataset. */
343 : constexpr const char *GDAL_ARG_NAME_OUTPUT = "output";
344 :
345 : /** Name of the argument for an output string. */
346 : constexpr const char *GDAL_ARG_NAME_OUTPUT_STRING = "output-string";
347 :
348 : /** Name of the boolean argument to request outtputing directly on stdout. */
349 : constexpr const char *GDAL_ARG_NAME_STDOUT = "stdout";
350 :
351 : /** Name of the argument for an output format. */
352 : constexpr const char *GDAL_ARG_NAME_OUTPUT_FORMAT = "output-format";
353 :
354 : /** Name of the argument for the output layer. */
355 : constexpr const char *GDAL_ARG_NAME_OUTPUT_LAYER = "output-layer";
356 :
357 : /** Name of the argument for a creation option. */
358 : constexpr const char *GDAL_ARG_NAME_CREATION_OPTION = "creation-option";
359 :
360 : /** Name of the argument for a layer creation option. */
361 : constexpr const char *GDAL_ARG_NAME_LAYER_CREATION_OPTION =
362 : "layer-creation-option";
363 :
364 : /** Name of the argument for update. */
365 : constexpr const char *GDAL_ARG_NAME_UPDATE = "update";
366 :
367 : /** Name of the argument for overwriting a dataset. */
368 : constexpr const char *GDAL_ARG_NAME_OVERWRITE = "overwrite";
369 :
370 : /** Name of the argument for overwriting a layer. */
371 : constexpr const char *GDAL_ARG_NAME_OVERWRITE_LAYER = "overwrite-layer";
372 :
373 : /** Name of the argument for append. */
374 : constexpr const char *GDAL_ARG_NAME_APPEND = "append";
375 :
376 : /** Name of the argument for read-only. */
377 : constexpr const char *GDAL_ARG_NAME_READ_ONLY = "read-only";
378 :
379 : /** Name of the argument for number of threads (string). */
380 : constexpr const char *GDAL_ARG_NAME_NUM_THREADS = "num-threads";
381 :
382 : /** Name of the argument for number of threads (integer). */
383 : constexpr const char *GDAL_ARG_NAME_NUM_THREADS_INT_HIDDEN =
384 : "num-threads-int-hidden";
385 :
386 : /** Driver must expose GDAL_DCAP_RASTER or GDAL_DCAP_MULTIDIM_RASTER.
387 : * This is a potential value of GetMetadataItem(GAAMDI_REQUIRED_CAPABILITIES)
388 : */
389 : constexpr const char *GDAL_ALG_DCAP_RASTER_OR_MULTIDIM_RASTER =
390 : "raster-or-multidim-raster";
391 :
392 : /************************************************************************/
393 : /* GDALArgDatasetValue */
394 : /************************************************************************/
395 :
396 : /** Return the string representation of GDALArgDatasetType */
397 : std::string CPL_DLL GDALAlgorithmArgDatasetTypeName(GDALArgDatasetType);
398 :
399 : class GDALAlgorithmArg;
400 :
401 : /** Value for an argument that points to a GDALDataset.
402 : *
403 : * This is the value of arguments of type GAAT_DATASET or GAAT_DATASET_LIST.
404 : */
405 : class CPL_DLL GDALArgDatasetValue final
406 : {
407 : public:
408 : /** Default (empty) constructor */
409 13007 : GDALArgDatasetValue() = default;
410 :
411 : /** Constructor by dataset name. */
412 1020 : explicit GDALArgDatasetValue(const std::string &name)
413 1020 : : m_name(name), m_nameSet(true)
414 : {
415 1020 : }
416 :
417 : /** Constructor by dataset instance, increasing its reference counter */
418 : explicit GDALArgDatasetValue(GDALDataset *poDS);
419 :
420 : /** Move constructor */
421 : GDALArgDatasetValue(GDALArgDatasetValue &&other);
422 :
423 : /** Destructor. Decrease m_poDS reference count, and destroy it if no
424 : * longer referenced. */
425 : ~GDALArgDatasetValue();
426 :
427 : /** Dereference the dataset object and close it if no longer referenced.
428 : * Return an error if an error occurred during dataset closing. */
429 : bool Close();
430 :
431 : /** Move-assignment operator */
432 : GDALArgDatasetValue &operator=(GDALArgDatasetValue &&other);
433 :
434 : /** Get the GDALDataset* instance (may be null), and increase its reference
435 : * count if not null. Once done with the dataset, the caller should call
436 : * GDALDataset::Release().
437 : */
438 : GDALDataset *GetDatasetIncreaseRefCount();
439 :
440 : /** Get a GDALDataset* instance (may be null). This does not modify the
441 : * reference counter, hence the lifetime of the returned object is not
442 : * guaranteed to exceed the one of this instance.
443 : */
444 25445 : GDALDataset *GetDatasetRef()
445 : {
446 25445 : return m_poDS;
447 : }
448 :
449 : /** Get a GDALDataset* instance (may be null). This does not modify the
450 : * reference counter, hence the lifetime of the returned object is not
451 : * guaranteed to exceed the one of this instance.
452 : */
453 42 : const GDALDataset *GetDatasetRef() const
454 : {
455 42 : return m_poDS;
456 : }
457 :
458 : /** Borrow the GDALDataset* instance (may be null), leaving its reference
459 : * counter unchanged.
460 : */
461 1 : GDALDataset *BorrowDataset()
462 : {
463 1 : GDALDataset *ret = m_poDS;
464 1 : m_poDS = nullptr;
465 1 : return ret;
466 : }
467 :
468 : /** Borrow the GDALDataset* instance from another GDALArgDatasetValue,
469 : * leaving its reference counter unchange.
470 : */
471 : void BorrowDatasetFrom(GDALArgDatasetValue &other)
472 : {
473 : Close();
474 : m_poDS = other.BorrowDataset();
475 : m_name = other.m_name;
476 : }
477 :
478 : /** Get dataset name */
479 16164 : const std::string &GetName() const
480 : {
481 16164 : return m_name;
482 : }
483 :
484 : /** Return whether a dataset name has been set */
485 2737 : bool IsNameSet() const
486 : {
487 2737 : return m_nameSet;
488 : }
489 :
490 : /** Set dataset name */
491 : void Set(const std::string &name);
492 :
493 : /** Transfer dataset to this instance (does not affect its reference
494 : * counter). */
495 : void Set(std::unique_ptr<GDALDataset> poDS);
496 :
497 : /** Set dataset object, increasing its reference counter. */
498 : void Set(GDALDataset *poDS);
499 :
500 : /** Set from other value, increasing the reference counter of the
501 : * GDALDataset object.
502 : */
503 : void SetFrom(const GDALArgDatasetValue &other);
504 :
505 : /** Set that the dataset has been opened by the algorithm */
506 889 : void SetDatasetOpenedByAlgorithm()
507 : {
508 889 : m_openedByAlgorithm = true;
509 889 : }
510 :
511 : /** Whether the dataset has been opened by the algorithm */
512 123 : bool HasDatasetBeenOpenedByAlgorithm() const
513 : {
514 123 : return m_openedByAlgorithm;
515 : }
516 :
517 : protected:
518 : friend class GDALAlgorithm;
519 :
520 : /** Set the argument that owns us. */
521 3854 : void SetOwnerArgument(GDALAlgorithmArg *arg)
522 : {
523 3854 : CPLAssert(!m_ownerArg);
524 3854 : m_ownerArg = arg;
525 3854 : }
526 :
527 : private:
528 : /** The owner argument (may be nullptr for freestanding objects) */
529 : GDALAlgorithmArg *m_ownerArg = nullptr;
530 :
531 : /** Dataset object. */
532 : GDALDataset *m_poDS = nullptr;
533 :
534 : /** Dataset name */
535 : std::string m_name{};
536 :
537 : /** Whether a dataset name (possibly empty for a MEM dataset...) has been set */
538 : bool m_nameSet = false;
539 :
540 : /** Whether the dataset has been opened by the algorithm */
541 : bool m_openedByAlgorithm = false;
542 :
543 : GDALArgDatasetValue(const GDALArgDatasetValue &) = delete;
544 : GDALArgDatasetValue &operator=(const GDALArgDatasetValue &) = delete;
545 : };
546 :
547 : /************************************************************************/
548 : /* GDALAlgorithmArgDecl */
549 : /************************************************************************/
550 :
551 : /** Argument declaration.
552 : *
553 : * It does not hold its value.
554 : */
555 : class CPL_DLL GDALAlgorithmArgDecl final
556 : {
557 : public:
558 : /** Special value for the SetMaxCount() / GetMaxCount() to indicate
559 : * unlimited number of values. */
560 : static constexpr int UNBOUNDED = std::numeric_limits<int>::max();
561 :
562 : /** Constructor.
563 : *
564 : * @param longName Long name. Must be 2 characters at least. Must not start
565 : * with dash.
566 : * @param chShortName 1-letter short name, or NUL character
567 : * @param description Description.
568 : * @param type Type of the argument.
569 : */
570 : GDALAlgorithmArgDecl(const std::string &longName, char chShortName,
571 : const std::string &description,
572 : GDALAlgorithmArgType type);
573 :
574 : /** Declare an alias. Must be 2 characters at least. */
575 23202 : GDALAlgorithmArgDecl &AddAlias(const std::string &alias)
576 : {
577 23202 : m_aliases.push_back(alias);
578 23202 : return *this;
579 : }
580 :
581 : /** Declare a shortname alias.*/
582 7 : GDALAlgorithmArgDecl &AddShortNameAlias(char shortNameAlias)
583 : {
584 7 : m_shortNameAliases.push_back(shortNameAlias);
585 7 : return *this;
586 : }
587 :
588 : /** Declare an hidden alias (i.e. not exposed in usage).
589 : * Must be 2 characters at least. */
590 4550 : GDALAlgorithmArgDecl &AddHiddenAlias(const std::string &alias)
591 : {
592 4550 : m_hiddenAliases.push_back(alias);
593 4550 : return *this;
594 : }
595 :
596 : /** Declare that the argument is positional. Typically input / output files
597 : */
598 7491 : GDALAlgorithmArgDecl &SetPositional()
599 : {
600 7491 : m_positional = true;
601 7491 : return *this;
602 : }
603 :
604 : /** Declare that the argument is required. Default is no
605 : */
606 7379 : GDALAlgorithmArgDecl &SetRequired()
607 : {
608 7379 : m_required = true;
609 7379 : return *this;
610 : }
611 :
612 : /** Declare the "meta-var" hint.
613 : * By default, the meta-var value is the long name of the argument in
614 : * upper case.
615 : */
616 25831 : GDALAlgorithmArgDecl &SetMetaVar(const std::string &metaVar)
617 : {
618 25831 : m_metaVar = metaVar;
619 25831 : return *this;
620 : }
621 :
622 : /** Declare the argument category: GAAC_COMMON, GAAC_BASE, GAAC_ADVANCED,
623 : * GAAC_ESOTERIC or a custom category.
624 : */
625 48086 : GDALAlgorithmArgDecl &SetCategory(const std::string &category)
626 : {
627 48086 : m_category = category;
628 48086 : return *this;
629 : }
630 :
631 : /** Declare a default value for the argument.
632 : */
633 14918 : template <class T> GDALAlgorithmArgDecl &SetDefault(const T &value)
634 : {
635 14918 : m_hasDefaultValue = true;
636 : try
637 : {
638 14918 : switch (m_type)
639 : {
640 7179 : case GAAT_BOOLEAN:
641 : {
642 : if constexpr (std::is_same_v<T, bool>)
643 : {
644 7178 : m_defaultValue = value;
645 7178 : return *this;
646 : }
647 1 : break;
648 : }
649 :
650 4084 : case GAAT_STRING:
651 : {
652 : if constexpr (std::is_same_v<T, std::string>)
653 : {
654 4083 : m_defaultValue = value;
655 4083 : return *this;
656 : }
657 1 : break;
658 : }
659 :
660 1736 : case GAAT_INTEGER:
661 : {
662 : if constexpr (std::is_same_v<T, int>)
663 : {
664 1735 : m_defaultValue = value;
665 1735 : return *this;
666 : }
667 1 : break;
668 : }
669 :
670 1671 : case GAAT_REAL:
671 : {
672 : if constexpr (std::is_assignable_v<double &, T>)
673 : {
674 1670 : m_defaultValue = static_cast<double>(value);
675 1670 : return *this;
676 : }
677 1 : break;
678 : }
679 :
680 238 : case GAAT_STRING_LIST:
681 : {
682 : if constexpr (std::is_same_v<T, std::string>)
683 : {
684 472 : m_defaultValue = std::vector<std::string>{value};
685 236 : return *this;
686 : }
687 : else if constexpr (std::is_same_v<T,
688 : std::vector<std::string>>)
689 : {
690 1 : m_defaultValue = value;
691 1 : return *this;
692 : }
693 1 : break;
694 : }
695 :
696 3 : case GAAT_INTEGER_LIST:
697 : {
698 : if constexpr (std::is_same_v<T, int>)
699 : {
700 1 : m_defaultValue = std::vector<int>{value};
701 1 : return *this;
702 : }
703 : else if constexpr (std::is_same_v<T, std::vector<int>>)
704 : {
705 1 : m_defaultValue = value;
706 1 : return *this;
707 : }
708 1 : break;
709 : }
710 :
711 5 : case GAAT_REAL_LIST:
712 : {
713 : if constexpr (std::is_assignable_v<double &, T>)
714 : {
715 3 : m_defaultValue =
716 : std::vector<double>{static_cast<double>(value)};
717 3 : return *this;
718 : }
719 : else if constexpr (std::is_same_v<T, std::vector<double>>)
720 : {
721 1 : m_defaultValue = value;
722 1 : return *this;
723 : }
724 1 : break;
725 : }
726 :
727 2 : case GAAT_DATASET:
728 : case GAAT_DATASET_LIST:
729 2 : break;
730 : }
731 : }
732 0 : catch (const std::bad_variant_access &)
733 : {
734 : // should not happen
735 : // fallthrough
736 : }
737 9 : CPLError(CE_Failure, CPLE_AppDefined,
738 : "Argument %s: SetDefault(): unexpected type for value",
739 9 : GetName().c_str());
740 9 : return *this;
741 : }
742 :
743 : /** Declare a default value for the argument.
744 : */
745 : GDALAlgorithmArgDecl &SetDefault(const char *value)
746 : {
747 : return SetDefault(std::string(value));
748 : }
749 :
750 : /** Declare the minimum number of values for the argument. Defaults to 0.
751 : * Only applies to list type of arguments.
752 : * Setting it to non-zero does *not* make the argument required. It just
753 : * sets the minimum number of values when it is specified. To also make
754 : * it required, use SetRequired().
755 : */
756 : GDALAlgorithmArgDecl &SetMinCount(int count);
757 :
758 : /** Declare the maximum number of values for the argument.
759 : * Defaults to 1 for scalar types, and UNBOUNDED for list types.
760 : * Only applies to list type of arguments.
761 : */
762 : GDALAlgorithmArgDecl &SetMaxCount(int count);
763 :
764 : /** Declare whether in \--help message one should display hints about the
765 : * minimum/maximum number of values. Defaults to true.
766 : */
767 1251 : GDALAlgorithmArgDecl &SetDisplayHintAboutRepetition(bool displayHint)
768 : {
769 1251 : m_displayHintAboutRepetition = displayHint;
770 1251 : return *this;
771 : }
772 :
773 : /** Declares whether, for list type of arguments, several values, space
774 : * separated, may be specified. That is "--foo=bar,baz".
775 : * The default is true.
776 : */
777 9912 : GDALAlgorithmArgDecl &SetPackedValuesAllowed(bool allowed)
778 : {
779 9912 : m_packedValuesAllowed = allowed;
780 9912 : return *this;
781 : }
782 :
783 : /** Declares whether, for list type of arguments, the argument may be
784 : * repeated. That is "--foo=bar --foo=baz".
785 : * The default is true.
786 : */
787 2570 : GDALAlgorithmArgDecl &SetRepeatedArgAllowed(bool allowed)
788 : {
789 2570 : m_repeatedArgAllowed = allowed;
790 2570 : return *this;
791 : }
792 :
793 : //! @cond Doxygen_Suppress
794 4345 : GDALAlgorithmArgDecl &SetChoices()
795 : {
796 4345 : return *this;
797 : }
798 :
799 : //! @endcond
800 :
801 : /** Declares the allowed values (as strings) for the argument.
802 : * Only honored for GAAT_STRING and GAAT_STRING_LIST types.
803 : */
804 : template <
805 : typename T, typename... U,
806 : typename std::enable_if<!std::is_same_v<T, std::vector<std::string> &>,
807 : bool>::type = true>
808 27925 : GDALAlgorithmArgDecl &SetChoices(T &&first, U &&...rest)
809 : {
810 27925 : m_choices.push_back(std::forward<T>(first));
811 27925 : SetChoices(std::forward<U>(rest)...);
812 27925 : return *this;
813 : }
814 :
815 : /** Declares the allowed values (as strings) for the argument.
816 : * Only honored for GAAT_STRING and GAAT_STRING_LIST types.
817 : */
818 379 : GDALAlgorithmArgDecl &SetChoices(const std::vector<std::string> &choices)
819 : {
820 379 : m_choices = choices;
821 379 : return *this;
822 : }
823 :
824 : /** Set the minimum (included) value allowed.
825 : *
826 : * Only taken into account on GAAT_INTEGER, GAAT_INTEGER_LIST,
827 : * GAAT_REAL and GAAT_REAL_LIST arguments.
828 : */
829 5539 : GDALAlgorithmArgDecl &SetMinValueIncluded(double min)
830 : {
831 5539 : m_minVal = min;
832 5539 : m_minValIsIncluded = true;
833 5539 : return *this;
834 : }
835 :
836 : /** Set the minimum (excluded) value allowed.
837 : *
838 : * Only taken into account on GAAT_INTEGER, GAAT_INTEGER_LIST,
839 : * GAAT_REAL and GAAT_REAL_LIST arguments.
840 : */
841 934 : GDALAlgorithmArgDecl &SetMinValueExcluded(double min)
842 : {
843 934 : m_minVal = min;
844 934 : m_minValIsIncluded = false;
845 934 : return *this;
846 : }
847 :
848 : /** Set the maximum (included) value allowed. */
849 1099 : GDALAlgorithmArgDecl &SetMaxValueIncluded(double max)
850 : {
851 1099 : m_maxVal = max;
852 1099 : m_maxValIsIncluded = true;
853 1099 : return *this;
854 : }
855 :
856 : /** Set the maximum (excluded) value allowed. */
857 193 : GDALAlgorithmArgDecl &SetMaxValueExcluded(double max)
858 : {
859 193 : m_maxVal = max;
860 193 : m_maxValIsIncluded = false;
861 193 : return *this;
862 : }
863 :
864 : /** Sets the minimum number of characters (for arguments of type
865 : * GAAT_STRING and GAAT_STRING_LIST)
866 : */
867 1094 : GDALAlgorithmArgDecl &SetMinCharCount(int count)
868 : {
869 1094 : m_minCharCount = count;
870 1094 : return *this;
871 : }
872 :
873 : //! @cond Doxygen_Suppress
874 928 : GDALAlgorithmArgDecl &SetHiddenChoices()
875 : {
876 928 : return *this;
877 : }
878 :
879 : //! @endcond
880 :
881 : /** Declares the, hidden, allowed values (as strings) for the argument.
882 : * Only honored for GAAT_STRING and GAAT_STRING_LIST types.
883 : */
884 : template <typename T, typename... U>
885 1417 : GDALAlgorithmArgDecl &SetHiddenChoices(T &&first, U &&...rest)
886 : {
887 1417 : m_hiddenChoices.push_back(std::forward<T>(first));
888 1417 : SetHiddenChoices(std::forward<U>(rest)...);
889 1417 : return *this;
890 : }
891 :
892 : /** Declare that the argument must not be mentioned in CLI usage.
893 : * For example, "output-value" for "gdal raster info", which is only
894 : * meant when the algorithm is used from a non-CLI context.
895 : */
896 30280 : GDALAlgorithmArgDecl &SetHiddenForCLI(bool hiddenForCLI = true)
897 : {
898 30280 : m_hiddenForCLI = hiddenForCLI;
899 30280 : return *this;
900 : }
901 :
902 : /** Declare that the argument is hidden in the context of an API use.
903 : * Said otherwise, if it is only for CLI usage.
904 : * For example "--help" */
905 35226 : GDALAlgorithmArgDecl &SetHiddenForAPI(bool hiddenForAPI = true)
906 : {
907 35226 : m_hiddenForAPI = hiddenForAPI;
908 35226 : return *this;
909 : }
910 :
911 : /** Declare that the argument is hidden. Default is no.
912 : * This is equivalent to calling SetHiddenForCLI() and SetHiddenForAPI()
913 : */
914 18515 : GDALAlgorithmArgDecl &SetHidden()
915 : {
916 18515 : m_hiddenForCLI = true;
917 18515 : m_hiddenForAPI = true;
918 18515 : return *this;
919 : }
920 :
921 : /** Indicate whether the value of the argument is read-only during the
922 : * execution of the algorithm. Default is true.
923 : */
924 7027 : GDALAlgorithmArgDecl &SetIsInput(bool isInput = true)
925 : {
926 7027 : m_isInput = isInput;
927 7027 : return *this;
928 : }
929 :
930 : /** Indicate whether (at least part of) the value of the argument is set
931 : * during the execution of the algorithm.
932 : * For example, "output-value" for "gdal raster info"
933 : * Default is false.
934 : * An argument may return both IsInput() and IsOutput() as true.
935 : * For example the "gdal raster convert" algorithm consumes the dataset
936 : * name of its "output" argument, and sets the dataset object during its
937 : * execution.
938 : */
939 6723 : GDALAlgorithmArgDecl &SetIsOutput(bool isOutput = true)
940 : {
941 6723 : m_isOutput = isOutput;
942 6723 : return *this;
943 : }
944 :
945 : /** Set the name of the mutual exclusion group to which this argument
946 : * belongs to. At most one argument in a group can be specified.
947 : */
948 9158 : GDALAlgorithmArgDecl &SetMutualExclusionGroup(const std::string &group)
949 : {
950 9158 : m_mutualExclusionGroup = group;
951 9158 : return *this;
952 : }
953 :
954 : /** Set user-defined metadata item.
955 : */
956 : GDALAlgorithmArgDecl &
957 7789 : AddMetadataItem(const std::string &name,
958 : const std::vector<std::string> &values)
959 : {
960 7789 : m_metadata[name] = values;
961 7789 : return *this;
962 : }
963 :
964 : /** Set that this (string) argument accepts the \@filename syntax to
965 : * mean that the content of the specified file should be used as the
966 : * value of the argument.
967 : */
968 519 : GDALAlgorithmArgDecl &SetReadFromFileAtSyntaxAllowed()
969 : {
970 519 : m_readFromFileAtSyntaxAllowed = true;
971 519 : return *this;
972 : }
973 :
974 : /** Sets that SQL comments must be removed from a (string) argument.
975 : */
976 518 : GDALAlgorithmArgDecl &SetRemoveSQLCommentsEnabled()
977 : {
978 518 : m_removeSQLComments = true;
979 518 : return *this;
980 : }
981 :
982 : /** Sets whether the dataset should be opened automatically by
983 : * GDALAlgorithm. Only applies to GAAT_DATASET and GAAT_DATASET_LIST.
984 : */
985 3416 : GDALAlgorithmArgDecl &SetAutoOpenDataset(bool autoOpen)
986 : {
987 3416 : m_autoOpenDataset = autoOpen;
988 3416 : return *this;
989 : }
990 :
991 : /** Declares that this argument has been created on-the-fly from user-provided
992 : * argument.
993 : */
994 22 : GDALAlgorithmArgDecl &SetUserProvided()
995 : {
996 22 : m_userProvided = true;
997 22 : return *this;
998 : }
999 :
1000 : /** Return the (long) name */
1001 188826 : inline const std::string &GetName() const
1002 : {
1003 188826 : return m_longName;
1004 : }
1005 :
1006 : /** Return the short name, or empty string if there is none */
1007 140538 : inline const std::string &GetShortName() const
1008 : {
1009 140538 : return m_shortName;
1010 : }
1011 :
1012 : /** Return the aliases (potentially none) */
1013 4876 : inline const std::vector<std::string> &GetAliases() const
1014 : {
1015 4876 : return m_aliases;
1016 : }
1017 :
1018 : /** Return the shortname aliases (potentially none) */
1019 4839 : inline const std::vector<char> &GetShortNameAliases() const
1020 : {
1021 4839 : return m_shortNameAliases;
1022 : }
1023 :
1024 : /** Return the description */
1025 6186 : inline const std::string &GetDescription() const
1026 : {
1027 6186 : return m_description;
1028 : }
1029 :
1030 : /** Return the "meta-var" hint.
1031 : * By default, the meta-var value is the long name of the argument in
1032 : * upper case.
1033 : */
1034 9518 : inline const std::string &GetMetaVar() const
1035 : {
1036 9518 : return m_metaVar;
1037 : }
1038 :
1039 : /** Return the argument category: GAAC_COMMON, GAAC_BASE, GAAC_ADVANCED,
1040 : * GAAC_ESOTERIC or a custom category.
1041 : */
1042 10369 : inline const std::string &GetCategory() const
1043 : {
1044 10369 : return m_category;
1045 : }
1046 :
1047 : /** Return the type */
1048 272523 : inline GDALAlgorithmArgType GetType() const
1049 : {
1050 272523 : return m_type;
1051 : }
1052 :
1053 : /** Return the allowed values (as strings) for the argument.
1054 : * Only honored for GAAT_STRING and GAAT_STRING_LIST types.
1055 : */
1056 11202 : inline const std::vector<std::string> &GetChoices() const
1057 : {
1058 11202 : return m_choices;
1059 : }
1060 :
1061 : /** Return the allowed hidden values (as strings) for the argument.
1062 : * Only honored for GAAT_STRING and GAAT_STRING_LIST types.
1063 : */
1064 19 : inline const std::vector<std::string> &GetHiddenChoices() const
1065 : {
1066 19 : return m_hiddenChoices;
1067 : }
1068 :
1069 : /** Return the minimum value and whether it is included. */
1070 5903 : inline std::pair<double, bool> GetMinValue() const
1071 : {
1072 5903 : return {m_minVal, m_minValIsIncluded};
1073 : }
1074 :
1075 : /** Return the maximum value and whether it is included. */
1076 5903 : inline std::pair<double, bool> GetMaxValue() const
1077 : {
1078 5903 : return {m_maxVal, m_maxValIsIncluded};
1079 : }
1080 :
1081 : /** Return the minimum number of characters (for arguments of type
1082 : * GAAT_STRING and GAAT_STRING_LIST)
1083 : */
1084 3204 : inline int GetMinCharCount() const
1085 : {
1086 3204 : return m_minCharCount;
1087 : }
1088 :
1089 : /** Return whether the argument is required. Defaults to false.
1090 : */
1091 82718 : inline bool IsRequired() const
1092 : {
1093 82718 : return m_required;
1094 : }
1095 :
1096 : /** Return the minimum number of values for the argument. Defaults to 0.
1097 : * Only applies to list type of arguments.
1098 : */
1099 16667 : inline int GetMinCount() const
1100 : {
1101 16667 : return m_minCount;
1102 : }
1103 :
1104 : /** Return the maximum number of values for the argument.
1105 : * Defaults to 1 for scalar types, and UNBOUNDED for list types.
1106 : * Only applies to list type of arguments.
1107 : */
1108 10512 : inline int GetMaxCount() const
1109 : {
1110 10512 : return m_maxCount;
1111 : }
1112 :
1113 : /** Returns whether in \--help message one should display hints about the
1114 : * minimum/maximum number of values. Defaults to true.
1115 : */
1116 1829 : inline bool GetDisplayHintAboutRepetition() const
1117 : {
1118 1829 : return m_displayHintAboutRepetition;
1119 : }
1120 :
1121 : /** Return whether, for list type of arguments, several values, space
1122 : * separated, may be specified. That is "--foo=bar,baz".
1123 : * The default is true.
1124 : */
1125 1614 : inline bool GetPackedValuesAllowed() const
1126 : {
1127 1614 : return m_packedValuesAllowed;
1128 : }
1129 :
1130 : /** Return whether, for list type of arguments, the argument may be
1131 : * repeated. That is "--foo=bar --foo=baz".
1132 : * The default is true.
1133 : */
1134 3716 : inline bool GetRepeatedArgAllowed() const
1135 : {
1136 3716 : return m_repeatedArgAllowed;
1137 : }
1138 :
1139 : /** Return if the argument is a positional one. */
1140 10209 : inline bool IsPositional() const
1141 : {
1142 10209 : return m_positional;
1143 : }
1144 :
1145 : /** Return if the argument has a declared default value. */
1146 141571 : inline bool HasDefaultValue() const
1147 : {
1148 141571 : return m_hasDefaultValue;
1149 : }
1150 :
1151 : /** Return whether the argument is hidden.
1152 : */
1153 18272 : inline bool IsHidden() const
1154 : {
1155 18272 : return m_hiddenForCLI && m_hiddenForAPI;
1156 : }
1157 :
1158 : /** Return whether the argument must not be mentioned in CLI usage.
1159 : * For example, "output-value" for "gdal raster info", which is only
1160 : * meant when the algorithm is used from a non-CLI context.
1161 : */
1162 11055 : inline bool IsHiddenForCLI() const
1163 : {
1164 11055 : return m_hiddenForCLI;
1165 : }
1166 :
1167 : /** Return whether the argument is only for CLI usage.
1168 : * For example "--help"
1169 : * This is an alias for IsHiddenForAPI()
1170 : */
1171 : inline bool IsOnlyForCLI() const
1172 : CPL_WARN_DEPRECATED("Use IsHiddenForAPI() instead")
1173 : {
1174 : return m_hiddenForAPI;
1175 : }
1176 :
1177 : /** Return whether the argument is hidden for API usage
1178 : * For example "--help" */
1179 20293 : inline bool IsHiddenForAPI() const
1180 : {
1181 20293 : return m_hiddenForAPI;
1182 : }
1183 :
1184 : /** Indicate whether the value of the argument is read-only during the
1185 : * execution of the algorithm. Default is true.
1186 : */
1187 14268 : inline bool IsInput() const
1188 : {
1189 14268 : return m_isInput;
1190 : }
1191 :
1192 : /** Return whether (at least part of) the value of the argument is set
1193 : * during the execution of the algorithm.
1194 : * For example, "output-value" for "gdal raster info"
1195 : * Default is false.
1196 : * An argument may return both IsInput() and IsOutput() as true.
1197 : * For example the "gdal raster convert" algorithm consumes the dataset
1198 : * name of its "output" argument, and sets the dataset object during its
1199 : * execution.
1200 : */
1201 20659 : inline bool IsOutput() const
1202 : {
1203 20659 : return m_isOutput;
1204 : }
1205 :
1206 : /** Return the name of the mutual exclusion group to which this argument
1207 : * belongs to, or empty string if it does not belong to any exclusion
1208 : * group.
1209 : */
1210 19653 : inline const std::string &GetMutualExclusionGroup() const
1211 : {
1212 19653 : return m_mutualExclusionGroup;
1213 : }
1214 :
1215 : /** Return if this (string) argument accepts the \@filename syntax to
1216 : * mean that the content of the specified file should be used as the
1217 : * value of the argument.
1218 : */
1219 2733 : inline bool IsReadFromFileAtSyntaxAllowed() const
1220 : {
1221 2733 : return m_readFromFileAtSyntaxAllowed;
1222 : }
1223 :
1224 : /** Returns whether SQL comments must be removed from a (string) argument.
1225 : */
1226 2720 : bool IsRemoveSQLCommentsEnabled() const
1227 : {
1228 2720 : return m_removeSQLComments;
1229 : }
1230 :
1231 : /** Returns whether the dataset should be opened automatically by
1232 : * GDALAlgorithm. Only applies to GAAT_DATASET and GAAT_DATASET_LIST.
1233 : */
1234 5768 : bool AutoOpenDataset() const
1235 : {
1236 5768 : return m_autoOpenDataset;
1237 : }
1238 :
1239 : /** Returns whether the argument has been user-provided.
1240 : */
1241 296 : bool IsUserProvided() const
1242 : {
1243 296 : return m_userProvided;
1244 : }
1245 :
1246 : /** Get user-defined metadata. */
1247 : inline const std::map<std::string, std::vector<std::string>>
1248 4317 : GetMetadata() const
1249 : {
1250 4317 : return m_metadata;
1251 : }
1252 :
1253 : /** Get user-defined metadata by item name. */
1254 : inline const std::vector<std::string> *
1255 4165 : GetMetadataItem(const std::string &name) const
1256 : {
1257 4165 : const auto iter = m_metadata.find(name);
1258 4165 : return iter == m_metadata.end() ? nullptr : &(iter->second);
1259 : }
1260 :
1261 : /** Return the default value of the argument.
1262 : * Must be called with T consistent of the type of the algorithm, and only
1263 : * if HasDefaultValue() is true.
1264 : * Valid T types are:
1265 : * - bool for GAAT_BOOLEAN
1266 : * - int for GAAT_INTEGER
1267 : * - double for GAAT_REAL
1268 : * - std::string for GAAT_STRING
1269 : * - GDALArgDatasetValue for GAAT_DATASET
1270 : * - std::vector<int> for GAAT_INTEGER_LIST
1271 : * - std::vector<double for GAAT_REAL_LIST
1272 : * - std::vector<std::string> for GAAT_STRING_LIST
1273 : * - std::vector<GDALArgDatasetValue> for GAAT_DATASET_LIST
1274 : */
1275 16240 : template <class T> inline const T &GetDefault() const
1276 : {
1277 16240 : return std::get<T>(m_defaultValue);
1278 : }
1279 :
1280 : /** Get which type of dataset is allowed / generated.
1281 : * Binary-or combination of GDAL_OF_RASTER, GDAL_OF_VECTOR and
1282 : * GDAL_OF_MULTIDIM_RASTER, possibly combined with GDAL_OF_UPDATE.
1283 : * Only applies to arguments of type GAAT_DATASET or GAAT_DATASET_LIST.
1284 : */
1285 2214 : GDALArgDatasetType GetDatasetType() const
1286 : {
1287 2214 : return m_datasetType;
1288 : }
1289 :
1290 : /** Set which type of dataset is allowed / generated.
1291 : * Binary-or combination of GDAL_OF_RASTER, GDAL_OF_VECTOR and
1292 : * GDAL_OF_MULTIDIM_RASTER.
1293 : * Only applies to arguments of type GAAT_DATASET or GAAT_DATASET_LIST.
1294 : */
1295 9549 : void SetDatasetType(GDALArgDatasetType type)
1296 : {
1297 9549 : m_datasetType = type;
1298 9549 : }
1299 :
1300 : /** Indicates which components among name and dataset are accepted as
1301 : * input, when this argument serves as an input.
1302 : *
1303 : * If the GADV_NAME bit is set, it indicates a dataset name is accepted as
1304 : * input.
1305 : * If the GADV_OBJECT bit is set, it indicates a dataset object is
1306 : * accepted as input.
1307 : * If both bits are set, the algorithm can accept either a name or a dataset
1308 : * object.
1309 : * Only applies to arguments of type GAAT_DATASET or GAAT_DATASET_LIST.
1310 : */
1311 7247 : int GetDatasetInputFlags() const
1312 : {
1313 7247 : return m_datasetInputFlags;
1314 : }
1315 :
1316 : /** Indicates which components among name and dataset are modified,
1317 : * when this argument serves as an output.
1318 : *
1319 : * If the GADV_NAME bit is set, it indicates a dataset name is generated as
1320 : * output (that is the algorithm will generate the name. Rarely used).
1321 : * If the GADV_OBJECT bit is set, it indicates a dataset object is
1322 : * generated as output, and available for use after the algorithm has
1323 : * completed.
1324 : * Only applies to arguments of type GAAT_DATASET or GAAT_DATASET_LIST.
1325 : */
1326 154 : int GetDatasetOutputFlags() const
1327 : {
1328 154 : return m_datasetOutputFlags;
1329 : }
1330 :
1331 : /** Set which components among name and dataset are accepted as
1332 : * input, when this argument serves as an input.
1333 : * Only applies to arguments of type GAAT_DATASET or GAAT_DATASET_LIST.
1334 : */
1335 5446 : void SetDatasetInputFlags(int flags)
1336 : {
1337 5446 : m_datasetInputFlags = flags;
1338 5446 : }
1339 :
1340 : /** Set which components among name and dataset are modified when this
1341 : * argument serves as an output.
1342 : * Only applies to arguments of type GAAT_DATASET or GAAT_DATASET_LIST.
1343 : */
1344 2852 : void SetDatasetOutputFlags(int flags)
1345 : {
1346 2852 : m_datasetOutputFlags = flags;
1347 2852 : }
1348 :
1349 : private:
1350 : const std::string m_longName;
1351 : const std::string m_shortName;
1352 : const std::string m_description;
1353 : const GDALAlgorithmArgType m_type;
1354 : std::string m_category = GAAC_BASE;
1355 : std::string m_metaVar{};
1356 : std::string m_mutualExclusionGroup{};
1357 : int m_minCount = 0;
1358 : int m_maxCount = 0;
1359 : bool m_required = false;
1360 : bool m_positional = false;
1361 : bool m_hasDefaultValue = false;
1362 : bool m_hiddenForCLI = false;
1363 : bool m_hiddenForAPI = false;
1364 : bool m_isInput = true;
1365 : bool m_isOutput = false;
1366 : bool m_packedValuesAllowed = true;
1367 : bool m_repeatedArgAllowed = true;
1368 : bool m_displayHintAboutRepetition = true;
1369 : bool m_readFromFileAtSyntaxAllowed = false;
1370 : bool m_removeSQLComments = false;
1371 : bool m_autoOpenDataset = true;
1372 : bool m_userProvided = false;
1373 : std::map<std::string, std::vector<std::string>> m_metadata{};
1374 : std::vector<std::string> m_aliases{};
1375 : std::vector<std::string> m_hiddenAliases{};
1376 : std::vector<char> m_shortNameAliases{};
1377 : std::vector<std::string> m_choices{};
1378 : std::vector<std::string> m_hiddenChoices{};
1379 : std::variant<bool, std::string, int, double, std::vector<std::string>,
1380 : std::vector<int>, std::vector<double>>
1381 : m_defaultValue{};
1382 : double m_minVal = std::numeric_limits<double>::quiet_NaN();
1383 : double m_maxVal = std::numeric_limits<double>::quiet_NaN();
1384 : bool m_minValIsIncluded = false;
1385 : bool m_maxValIsIncluded = false;
1386 : int m_minCharCount = 0;
1387 : GDALArgDatasetType m_datasetType =
1388 : GDAL_OF_RASTER | GDAL_OF_VECTOR | GDAL_OF_MULTIDIM_RASTER;
1389 :
1390 : /** Which components among name and dataset are accepted as
1391 : * input, when this argument serves as an input.
1392 : */
1393 : int m_datasetInputFlags = GADV_NAME | GADV_OBJECT;
1394 :
1395 : /** Which components among name and dataset are generated as
1396 : * output, when this argument serves as an output.
1397 : */
1398 : int m_datasetOutputFlags = GADV_OBJECT;
1399 : };
1400 :
1401 : /************************************************************************/
1402 : /* GDALAlgorithmArg */
1403 : /************************************************************************/
1404 :
1405 : class GDALAlgorithm;
1406 :
1407 : /** Argument of an algorithm.
1408 : */
1409 145043 : class CPL_DLL GDALAlgorithmArg /* non-final */
1410 : {
1411 : public:
1412 : /** Constructor */
1413 : template <class T>
1414 145043 : GDALAlgorithmArg(const GDALAlgorithmArgDecl &decl, T *pValue)
1415 145043 : : m_decl(decl), m_value(pValue)
1416 : {
1417 : if constexpr (!std::is_same_v<T, GDALArgDatasetValue> &&
1418 : !std::is_same_v<T, std::vector<GDALArgDatasetValue>>)
1419 : {
1420 135488 : if (decl.HasDefaultValue())
1421 : {
1422 : try
1423 : {
1424 2 : *std::get<T *>(m_value) = decl.GetDefault<T>();
1425 : }
1426 0 : catch (const std::bad_variant_access &e)
1427 : {
1428 : // I don't think that can happen, but Coverity Scan thinks
1429 : // so
1430 0 : CPLError(CE_Failure, CPLE_AppDefined,
1431 : "*std::get<T *>(m_value) = decl.GetDefault<T>() "
1432 : "failed: %s",
1433 0 : e.what());
1434 : }
1435 : }
1436 : }
1437 145043 : }
1438 :
1439 : /** Destructor */
1440 : virtual ~GDALAlgorithmArg();
1441 :
1442 : /** Return the argument declaration. */
1443 : const GDALAlgorithmArgDecl &GetDeclaration() const
1444 : {
1445 : return m_decl;
1446 : }
1447 :
1448 : /** Alias for GDALAlgorithmArgDecl::GetName() */
1449 188815 : inline const std::string &GetName() const
1450 : {
1451 188815 : return m_decl.GetName();
1452 : }
1453 :
1454 : /** Alias for GDALAlgorithmArgDecl::GetShortName() */
1455 140538 : inline const std::string &GetShortName() const
1456 : {
1457 140538 : return m_decl.GetShortName();
1458 : }
1459 :
1460 : /** Alias for GDALAlgorithmArgDecl::GetAliases() */
1461 4876 : inline const std::vector<std::string> &GetAliases() const
1462 : {
1463 4876 : return m_decl.GetAliases();
1464 : }
1465 :
1466 : /** Alias for GDALAlgorithmArgDecl::GetShortNameAliases() */
1467 4839 : inline const std::vector<char> &GetShortNameAliases() const
1468 : {
1469 4839 : return m_decl.GetShortNameAliases();
1470 : }
1471 :
1472 : /** Alias for GDALAlgorithmArgDecl::GetDescription() */
1473 6186 : inline const std::string &GetDescription() const
1474 : {
1475 6186 : return m_decl.GetDescription();
1476 : }
1477 :
1478 : /** Alias for GDALAlgorithmArgDecl::GetMetaVar() */
1479 9518 : inline const std::string &GetMetaVar() const
1480 : {
1481 9518 : return m_decl.GetMetaVar();
1482 : }
1483 :
1484 : /** Alias for GDALAlgorithmArgDecl::GetType() */
1485 232911 : inline GDALAlgorithmArgType GetType() const
1486 : {
1487 232911 : return m_decl.GetType();
1488 : }
1489 :
1490 : /** Alias for GDALAlgorithmArgDecl::GetCategory() */
1491 10369 : inline const std::string &GetCategory() const
1492 : {
1493 10369 : return m_decl.GetCategory();
1494 : }
1495 :
1496 : /** Alias for GDALAlgorithmArgDecl::IsRequired() */
1497 82718 : inline bool IsRequired() const
1498 : {
1499 82718 : return m_decl.IsRequired();
1500 : }
1501 :
1502 : /** Alias for GDALAlgorithmArgDecl::GetMinCount() */
1503 16665 : inline int GetMinCount() const
1504 : {
1505 16665 : return m_decl.GetMinCount();
1506 : }
1507 :
1508 : /** Alias for GDALAlgorithmArgDecl::GetMaxCount() */
1509 10510 : inline int GetMaxCount() const
1510 : {
1511 10510 : return m_decl.GetMaxCount();
1512 : }
1513 :
1514 : /** Alias for GDALAlgorithmArgDecl::GetDisplayHintAboutRepetition() */
1515 1829 : inline bool GetDisplayHintAboutRepetition() const
1516 : {
1517 1829 : return m_decl.GetDisplayHintAboutRepetition();
1518 : }
1519 :
1520 : /** Alias for GDALAlgorithmArgDecl::GetPackedValuesAllowed() */
1521 1614 : inline bool GetPackedValuesAllowed() const
1522 : {
1523 1614 : return m_decl.GetPackedValuesAllowed();
1524 : }
1525 :
1526 : /** Alias for GDALAlgorithmArgDecl::GetRepeatedArgAllowed() */
1527 3716 : inline bool GetRepeatedArgAllowed() const
1528 : {
1529 3716 : return m_decl.GetRepeatedArgAllowed();
1530 : }
1531 :
1532 : /** Alias for GDALAlgorithmArgDecl::IsPositional() */
1533 10209 : inline bool IsPositional() const
1534 : {
1535 10209 : return m_decl.IsPositional();
1536 : }
1537 :
1538 : /** Alias for GDALAlgorithmArgDecl::GetChoices() */
1539 11202 : inline const std::vector<std::string> &GetChoices() const
1540 : {
1541 11202 : return m_decl.GetChoices();
1542 : }
1543 :
1544 : /** Alias for GDALAlgorithmArgDecl::GetHiddenChoices() */
1545 19 : inline const std::vector<std::string> &GetHiddenChoices() const
1546 : {
1547 19 : return m_decl.GetHiddenChoices();
1548 : }
1549 :
1550 : /** Return auto completion choices, if a auto completion function has been
1551 : * registered.
1552 : */
1553 : inline std::vector<std::string>
1554 72 : GetAutoCompleteChoices(const std::string ¤tValue) const
1555 : {
1556 72 : if (m_autoCompleteFunction)
1557 71 : return m_autoCompleteFunction(currentValue);
1558 1 : return {};
1559 : }
1560 :
1561 : /** Alias for GDALAlgorithmArgDecl::GetMinValue() */
1562 5903 : inline std::pair<double, bool> GetMinValue() const
1563 : {
1564 5903 : return m_decl.GetMinValue();
1565 : }
1566 :
1567 : /** Alias for GDALAlgorithmArgDecl::GetMaxValue() */
1568 5903 : inline std::pair<double, bool> GetMaxValue() const
1569 : {
1570 5903 : return m_decl.GetMaxValue();
1571 : }
1572 :
1573 : /** Alias for GDALAlgorithmArgDecl::GetMinCharCount() */
1574 3204 : inline int GetMinCharCount() const
1575 : {
1576 3204 : return m_decl.GetMinCharCount();
1577 : }
1578 :
1579 : /** Return whether the argument value has been explicitly set with Set() */
1580 352635 : inline bool IsExplicitlySet() const
1581 : {
1582 352635 : return m_explicitlySet;
1583 : }
1584 :
1585 : /** Alias for GDALAlgorithmArgDecl::HasDefaultValue() */
1586 6083 : inline bool HasDefaultValue() const
1587 : {
1588 6083 : return m_decl.HasDefaultValue();
1589 : }
1590 :
1591 : /** Alias for GDALAlgorithmArgDecl::IsHidden() */
1592 18272 : inline bool IsHidden() const
1593 : {
1594 18272 : return m_decl.IsHidden();
1595 : }
1596 :
1597 : /** Alias for GDALAlgorithmArgDecl::IsHiddenForCLI() */
1598 11055 : inline bool IsHiddenForCLI() const
1599 : {
1600 11055 : return m_decl.IsHiddenForCLI();
1601 : }
1602 :
1603 : /** Alias for GDALAlgorithmArgDecl::IsOnlyForCLI() */
1604 : inline bool IsOnlyForCLI() const
1605 : CPL_WARN_DEPRECATED("Use IsHiddenForAPI() instead")
1606 : {
1607 : return m_decl.IsHiddenForAPI();
1608 : }
1609 :
1610 : /** Alias for GDALAlgorithmArgDecl::IsHiddenForAPI() */
1611 20293 : inline bool IsHiddenForAPI() const
1612 : {
1613 20293 : return m_decl.IsHiddenForAPI();
1614 : }
1615 :
1616 : /** Alias for GDALAlgorithmArgDecl::IsInput() */
1617 14268 : inline bool IsInput() const
1618 : {
1619 14268 : return m_decl.IsInput();
1620 : }
1621 :
1622 : /** Alias for GDALAlgorithmArgDecl::IsOutput() */
1623 20659 : inline bool IsOutput() const
1624 : {
1625 20659 : return m_decl.IsOutput();
1626 : }
1627 :
1628 : /** Alias for GDALAlgorithmArgDecl::IsReadFromFileAtSyntaxAllowed() */
1629 : inline bool IsReadFromFileAtSyntaxAllowed() const
1630 : {
1631 : return m_decl.IsReadFromFileAtSyntaxAllowed();
1632 : }
1633 :
1634 : /** Alias for GDALAlgorithmArgDecl::IsRemoveSQLCommentsEnabled() */
1635 : inline bool IsRemoveSQLCommentsEnabled() const
1636 : {
1637 : return m_decl.IsRemoveSQLCommentsEnabled();
1638 : }
1639 :
1640 : /** Alias for GDALAlgorithmArgDecl::GetMutualExclusionGroup() */
1641 19653 : inline const std::string &GetMutualExclusionGroup() const
1642 : {
1643 19653 : return m_decl.GetMutualExclusionGroup();
1644 : }
1645 :
1646 : /** Alias for GDALAlgorithmArgDecl::GetMetadata() */
1647 : inline const std::map<std::string, std::vector<std::string>>
1648 4317 : GetMetadata() const
1649 : {
1650 4317 : return m_decl.GetMetadata();
1651 : }
1652 :
1653 : /** Alias for GDALAlgorithmArgDecl::GetMetadataItem() */
1654 : inline const std::vector<std::string> *
1655 4165 : GetMetadataItem(const std::string &name) const
1656 : {
1657 4165 : return m_decl.GetMetadataItem(name);
1658 : }
1659 :
1660 : /** Alias for GDALAlgorithmArgDecl::GetDefault() */
1661 1324 : template <class T> inline const T &GetDefault() const
1662 : {
1663 1324 : return m_decl.GetDefault<T>();
1664 : }
1665 :
1666 : /** Alias for GDALAlgorithmArgDecl::AutoOpenDataset() */
1667 5768 : inline bool AutoOpenDataset() const
1668 : {
1669 5768 : return m_decl.AutoOpenDataset();
1670 : }
1671 :
1672 : /** Alias for GDALAlgorithmArgDecl::IsUserProvided() */
1673 296 : inline bool IsUserProvided() const
1674 : {
1675 296 : return m_decl.IsUserProvided();
1676 : }
1677 :
1678 : /** Alias for GDALAlgorithmArgDecl::GetDatasetType() */
1679 2214 : inline GDALArgDatasetType GetDatasetType() const
1680 : {
1681 2214 : return m_decl.GetDatasetType();
1682 : }
1683 :
1684 : /** Alias for GDALAlgorithmArgDecl::GetDatasetInputFlags() */
1685 7247 : inline int GetDatasetInputFlags() const
1686 : {
1687 7247 : return m_decl.GetDatasetInputFlags();
1688 : }
1689 :
1690 : /** Alias for GDALAlgorithmArgDecl::GetDatasetOutputFlags() */
1691 154 : inline int GetDatasetOutputFlags() const
1692 : {
1693 154 : return m_decl.GetDatasetOutputFlags();
1694 : }
1695 :
1696 : /** Return the value of the argument, which is by decreasing order of priority:
1697 : * - the value set through Set().
1698 : * - the default value set through SetDefault().
1699 : * - the initial value of the C++ variable to which this argument is bound to.
1700 : *
1701 : * Must be called with T consistent of the type of the algorithm:
1702 : * - bool for GAAT_BOOLEAN
1703 : * - int for GAAT_INTEGER
1704 : * - double for GAAT_REAL
1705 : * - std::string for GAAT_STRING
1706 : * - GDALArgDatasetValue for GAAT_DATASET
1707 : * - std::vector<int> for GAAT_INTEGER_LIST
1708 : * - std::vector<double for GAAT_REAL_LIST
1709 : * - std::vector<std::string> for GAAT_STRING_LIST
1710 : * - std::vector<GDALArgDatasetValue> for GAAT_DATASET_LIST
1711 : */
1712 30450 : template <class T> inline T &Get()
1713 : {
1714 30450 : return *(std::get<T *>(m_value));
1715 : }
1716 :
1717 : /** Return the value of the argument, which is by decreasing order of priority:
1718 : * - the value set through Set().
1719 : * - the default value set through SetDefault().
1720 : * - the initial value of the C++ variable to which this argument is bound to.
1721 : *
1722 : * Must be called with T consistent of the type of the algorithm:
1723 : * - bool for GAAT_BOOLEAN
1724 : * - int for GAAT_INTEGER
1725 : * - double for GAAT_REAL
1726 : * - std::string for GAAT_STRING
1727 : * - GDALArgDatasetValue for GAAT_DATASET
1728 : * - std::vector<int> for GAAT_INTEGER_LIST
1729 : * - std::vector<double for GAAT_REAL_LIST
1730 : * - std::vector<std::string> for GAAT_STRING_LIST
1731 : * - std::vector<GDALArgDatasetValue> for GAAT_DATASET_LIST
1732 : */
1733 3277 : template <class T> inline const T &Get() const
1734 : {
1735 3277 : return *(std::get<T *>(m_value));
1736 : }
1737 :
1738 : /** Set the value for a GAAT_BOOLEAN argument.
1739 : * It cannot be called several times for a given argument.
1740 : * Validation checks and other actions are run.
1741 : * Return true if success.
1742 : */
1743 : bool Set(bool value);
1744 :
1745 : /** Set the value for a GAAT_STRING argument.
1746 : * It cannot be called several times for a given argument.
1747 : * Validation checks and other actions are run.
1748 : * Return true if success.
1749 : */
1750 : bool Set(const std::string &value);
1751 :
1752 : /** Set the value for a GAAT_STRING argument.
1753 : * It cannot be called several times for a given argument.
1754 : * Validation checks and other actions are run.
1755 : * Return true if success.
1756 : */
1757 1591 : bool Set(const char *value)
1758 : {
1759 1591 : return Set(std::string(value ? value : ""));
1760 : }
1761 :
1762 : /** Set the value for a GAAT_STRING argument from a GDALDataType
1763 : * It cannot be called several times for a given argument.
1764 : * Validation checks and other actions are run.
1765 : * Return true if success.
1766 : */
1767 1 : bool Set(GDALDataType dt)
1768 : {
1769 1 : return Set(GDALGetDataTypeName(dt));
1770 : }
1771 :
1772 : /** Set the value for a GAAT_STRING argument (representing a CRS)
1773 : * from a OGRSpatialReference
1774 : * It cannot be called several times for a given argument.
1775 : * Validation checks and other actions are run.
1776 : * Return true if success.
1777 : */
1778 : bool Set(const OGRSpatialReference &);
1779 :
1780 : /** Set the value for a GAAT_INTEGER (or GAAT_REAL) argument.
1781 : * It cannot be called several times for a given argument.
1782 : * Validation checks and other actions are run.
1783 : * Return true if success.
1784 : */
1785 : bool Set(int value);
1786 :
1787 : /** Set the value for a GAAT_REAL argument */
1788 : bool Set(double value);
1789 :
1790 : /** Set the value for a GAAT_DATASET argument, increasing ds' reference
1791 : * counter if ds is not null.
1792 : * It cannot be called several times for a given argument.
1793 : * Validation checks and other actions are run.
1794 : * Return true if success.
1795 : */
1796 : bool Set(GDALDataset *ds);
1797 :
1798 : /** Set the value for a GAAT_DATASET argument.
1799 : * It cannot be called several times for a given argument.
1800 : * Validation checks and other actions are run.
1801 : * Return true if success.
1802 : */
1803 : bool Set(std::unique_ptr<GDALDataset> ds);
1804 :
1805 : /** Set the value for a GAAT_DATASET argument.
1806 : * It cannot be called several times for a given argument.
1807 : * Validation checks and other actions are run.
1808 : * Return true if success.
1809 : */
1810 : bool SetDatasetName(const std::string &name);
1811 :
1812 : /** Set the value for a GAAT_DATASET argument.
1813 : * It references the dataset pointed by other.m_poDS.
1814 : * It cannot be called several times for a given argument.
1815 : * Validation checks and other actions are run.
1816 : * Return true if success.
1817 : */
1818 : bool SetFrom(const GDALArgDatasetValue &other);
1819 :
1820 : /** Set the value for a GAAT_STRING_LIST argument.
1821 : * It cannot be called several times for a given argument.
1822 : * Validation checks and other actions are run.
1823 : * Return true if success.
1824 : */
1825 : bool Set(const std::vector<std::string> &value);
1826 :
1827 : /** Set the value for a GAAT_INTEGER_LIST argument.
1828 : * It cannot be called several times for a given argument.
1829 : * Validation checks and other actions are run.
1830 : * Return true if success.
1831 : */
1832 : bool Set(const std::vector<int> &value);
1833 :
1834 : /** Set the value for a GAAT_REAL_LIST argument.
1835 : * It cannot be called several times for a given argument.
1836 : * Validation checks and other actions are run.
1837 : * Return true if success.
1838 : */
1839 : bool Set(const std::vector<double> &value);
1840 :
1841 : /** Set the value for a GAAT_DATASET_LIST argument.
1842 : * It cannot be called several times for a given argument.
1843 : * Validation checks and other actions are run.
1844 : * Return true if success.
1845 : */
1846 : bool Set(std::vector<GDALArgDatasetValue> &&value);
1847 :
1848 : /** Set the value of the argument. */
1849 28 : inline GDALAlgorithmArg &operator=(bool value)
1850 : {
1851 28 : Set(value);
1852 28 : return *this;
1853 : }
1854 :
1855 : /** Set the value of the argument. */
1856 1 : inline GDALAlgorithmArg &operator=(int value)
1857 : {
1858 1 : Set(value);
1859 1 : return *this;
1860 : }
1861 :
1862 : /** Set the value of the argument. */
1863 1 : inline GDALAlgorithmArg &operator=(double value)
1864 : {
1865 1 : Set(value);
1866 1 : return *this;
1867 : }
1868 :
1869 : /** Set the value of the argument. */
1870 33 : inline GDALAlgorithmArg &operator=(const std::string &value)
1871 : {
1872 33 : Set(value);
1873 33 : return *this;
1874 : }
1875 :
1876 : /** Set the value of the argument. */
1877 1 : inline GDALAlgorithmArg &operator=(const char *value)
1878 : {
1879 1 : Set(value);
1880 1 : return *this;
1881 : }
1882 :
1883 : /** Set the value of the argument. */
1884 1 : inline GDALAlgorithmArg &operator=(GDALDataType value)
1885 : {
1886 1 : Set(value);
1887 1 : return *this;
1888 : }
1889 :
1890 : /** Set the value of the argument. */
1891 1 : inline GDALAlgorithmArg &operator=(const OGRSpatialReference &value)
1892 : {
1893 1 : Set(value);
1894 1 : return *this;
1895 : }
1896 :
1897 : /** Set the value of the argument. */
1898 2 : inline GDALAlgorithmArg &operator=(const std::vector<int> &value)
1899 : {
1900 2 : Set(value);
1901 2 : return *this;
1902 : }
1903 :
1904 : /** Set the value of the argument. */
1905 1 : inline GDALAlgorithmArg &operator=(const std::vector<double> &value)
1906 : {
1907 1 : Set(value);
1908 1 : return *this;
1909 : }
1910 :
1911 : /** Set the value of the argument. */
1912 10 : inline GDALAlgorithmArg &operator=(const std::vector<std::string> &value)
1913 : {
1914 10 : Set(value);
1915 10 : return *this;
1916 : }
1917 :
1918 : /** Set the value of the argument. */
1919 : inline GDALAlgorithmArg &operator=(GDALDataset *value)
1920 : {
1921 : Set(value);
1922 : return *this;
1923 : }
1924 :
1925 : /** Set the value of the argument. */
1926 : GDALAlgorithmArg &operator=(std::unique_ptr<GDALDataset> value);
1927 :
1928 : /** Set the value for another argument.
1929 : * For GAAT_DATASET, it will reference the dataset pointed by other.m_poDS.
1930 : * It cannot be called several times for a given argument.
1931 : * Validation checks and other actions are run.
1932 : * Return true if success.
1933 : */
1934 : bool SetFrom(const GDALAlgorithmArg &other);
1935 :
1936 : /** Advanced method used to make "gdal info" and "gdal raster|vector info"
1937 : * to avoid re-opening an already opened dataset */
1938 2757 : void SetSkipIfAlreadySet(bool skip = true)
1939 : {
1940 2757 : m_skipIfAlreadySet = skip;
1941 2757 : }
1942 :
1943 : /** Advanced method used to make "gdal info" and "gdal raster|vector info"
1944 : * to avoid re-opening an already opened dataset */
1945 3 : bool SkipIfAlreadySet() const
1946 : {
1947 3 : return m_skipIfAlreadySet;
1948 : }
1949 :
1950 : /** Serialize this argument and its value.
1951 : * May return false if the argument is not explicitly set or if a dataset
1952 : * is passed by value.
1953 : */
1954 : bool Serialize(std::string &serializedArg, bool absolutePath = false) const;
1955 :
1956 : /** Return an escaped string for argument serialization */
1957 : static std::string GetEscapedString(const std::string &s);
1958 :
1959 : //! @cond Doxygen_Suppress
1960 3954 : void NotifyValueSet()
1961 : {
1962 3954 : m_explicitlySet = true;
1963 3954 : }
1964 :
1965 : //! @endcond
1966 :
1967 : protected:
1968 : friend class GDALAlgorithm;
1969 : /** Argument declaration */
1970 : GDALAlgorithmArgDecl m_decl;
1971 : /** Pointer to the value */
1972 : std::variant<bool *, std::string *, int *, double *, GDALArgDatasetValue *,
1973 : std::vector<std::string> *, std::vector<int> *,
1974 : std::vector<double> *, std::vector<GDALArgDatasetValue> *>
1975 : m_value{};
1976 : /** Actions */
1977 : std::vector<std::function<void()>> m_actions{};
1978 : /** Validation actions */
1979 : std::vector<std::function<bool()>> m_validationActions{};
1980 : /** Autocompletion function */
1981 : std::function<std::vector<std::string>(const std::string &)>
1982 : m_autoCompleteFunction{};
1983 : /** Algorithm that may own this argument. */
1984 : GDALAlgorithm *m_owner = nullptr;
1985 :
1986 : private:
1987 : bool m_skipIfAlreadySet = false;
1988 : bool m_explicitlySet = false;
1989 :
1990 4723 : template <class T> bool SetInternal(const T &value)
1991 : {
1992 4723 : m_explicitlySet = true;
1993 4723 : *std::get<T *>(m_value) = value;
1994 4723 : return RunAllActions();
1995 : }
1996 :
1997 : bool ProcessString(std::string &value) const;
1998 :
1999 : bool RunAllActions();
2000 : void RunActions();
2001 : bool RunValidationActions();
2002 : std::string ValidateChoice(const std::string &value) const;
2003 : bool ValidateIntRange(int val) const;
2004 : bool ValidateRealRange(double val) const;
2005 :
2006 : CPL_DISALLOW_COPY_ASSIGN(GDALAlgorithmArg)
2007 : };
2008 :
2009 : /************************************************************************/
2010 : /* GDALInConstructionAlgorithmArg */
2011 : /************************************************************************/
2012 :
2013 : //! @cond Doxygen_Suppress
2014 : namespace test_gdal_algorithm
2015 : {
2016 : struct test_gdal_algorithm;
2017 : }
2018 :
2019 : //! @endcond
2020 :
2021 : /** Technical class used by GDALAlgorithm when constructing argument
2022 : * declarations.
2023 : */
2024 268574 : class CPL_DLL GDALInConstructionAlgorithmArg final : public GDALAlgorithmArg
2025 : {
2026 : friend struct test_gdal_algorithm::test_gdal_algorithm;
2027 :
2028 : public:
2029 : /** Constructor */
2030 : template <class T>
2031 134288 : GDALInConstructionAlgorithmArg(GDALAlgorithm *owner,
2032 : const GDALAlgorithmArgDecl &decl, T *pValue)
2033 134288 : : GDALAlgorithmArg(decl, pValue)
2034 : {
2035 134288 : m_owner = owner;
2036 134288 : }
2037 :
2038 : /** Destructor */
2039 : ~GDALInConstructionAlgorithmArg() override;
2040 :
2041 : /** Add a documented alias for the argument */
2042 : GDALInConstructionAlgorithmArg &AddAlias(const std::string &alias);
2043 :
2044 : /** Add a non-documented alias for the argument */
2045 : GDALInConstructionAlgorithmArg &AddHiddenAlias(const std::string &alias);
2046 :
2047 : /** Add a shortname alias for the argument */
2048 : GDALInConstructionAlgorithmArg &AddShortNameAlias(char shortNameAlias);
2049 :
2050 : /** Alias for GDALAlgorithmArgDecl::SetPositional() */
2051 : GDALInConstructionAlgorithmArg &SetPositional();
2052 :
2053 : /** Alias for GDALAlgorithmArgDecl::SetRequired() */
2054 7379 : GDALInConstructionAlgorithmArg &SetRequired()
2055 : {
2056 7379 : m_decl.SetRequired();
2057 7379 : return *this;
2058 : }
2059 :
2060 : /** Alias for GDALAlgorithmArgDecl::SetMetaVar() */
2061 25831 : GDALInConstructionAlgorithmArg &SetMetaVar(const std::string &metaVar)
2062 : {
2063 25831 : m_decl.SetMetaVar(metaVar);
2064 25831 : return *this;
2065 : }
2066 :
2067 : /** Alias for GDALAlgorithmArgDecl::SetCategory() */
2068 48086 : GDALInConstructionAlgorithmArg &SetCategory(const std::string &category)
2069 : {
2070 48086 : m_decl.SetCategory(category);
2071 48086 : return *this;
2072 : }
2073 :
2074 : /** Alias for GDALAlgorithmArgDecl::SetDefault() */
2075 : template <class T>
2076 14916 : GDALInConstructionAlgorithmArg &SetDefault(const T &value)
2077 : {
2078 14916 : m_decl.SetDefault(value);
2079 :
2080 : if constexpr (!std::is_same_v<T, GDALArgDatasetValue> &&
2081 : !std::is_same_v<T, std::vector<GDALArgDatasetValue>>)
2082 : {
2083 : try
2084 : {
2085 14916 : switch (m_decl.GetType())
2086 : {
2087 7179 : case GAAT_BOOLEAN:
2088 7179 : *std::get<bool *>(m_value) = m_decl.GetDefault<bool>();
2089 7179 : break;
2090 4084 : case GAAT_STRING:
2091 4084 : *std::get<std::string *>(m_value) =
2092 : m_decl.GetDefault<std::string>();
2093 4084 : break;
2094 1736 : case GAAT_INTEGER:
2095 1736 : *std::get<int *>(m_value) = m_decl.GetDefault<int>();
2096 1736 : break;
2097 1669 : case GAAT_REAL:
2098 3338 : *std::get<double *>(m_value) =
2099 1669 : m_decl.GetDefault<double>();
2100 1669 : break;
2101 238 : case GAAT_STRING_LIST:
2102 238 : *std::get<std::vector<std::string> *>(m_value) =
2103 : m_decl.GetDefault<std::vector<std::string>>();
2104 238 : break;
2105 3 : case GAAT_INTEGER_LIST:
2106 3 : *std::get<std::vector<int> *>(m_value) =
2107 : m_decl.GetDefault<std::vector<int>>();
2108 3 : break;
2109 5 : case GAAT_REAL_LIST:
2110 5 : *std::get<std::vector<double> *>(m_value) =
2111 : m_decl.GetDefault<std::vector<double>>();
2112 5 : break;
2113 2 : case GAAT_DATASET:
2114 : case GAAT_DATASET_LIST:
2115 2 : break;
2116 : }
2117 : }
2118 0 : catch (const std::bad_variant_access &)
2119 : {
2120 : // I don't think that can happen, but Coverity Scan thinks so
2121 0 : CPLError(CE_Failure, CPLE_AppDefined,
2122 : "Argument %s: SetDefault(): unexpected type for value",
2123 0 : GetName().c_str());
2124 : }
2125 : }
2126 14916 : return *this;
2127 : }
2128 :
2129 : /** Alias for GDALAlgorithmArgDecl::SetDefault() */
2130 1128 : GDALInConstructionAlgorithmArg &SetDefault(const char *value)
2131 : {
2132 1128 : return SetDefault(std::string(value));
2133 : }
2134 :
2135 : /** Alias for GDALAlgorithmArgDecl::SetMinCount() */
2136 6215 : GDALInConstructionAlgorithmArg &SetMinCount(int count)
2137 : {
2138 6215 : m_decl.SetMinCount(count);
2139 6215 : return *this;
2140 : }
2141 :
2142 : /** Alias for GDALAlgorithmArgDecl::SetMaxCount() */
2143 5430 : GDALInConstructionAlgorithmArg &SetMaxCount(int count)
2144 : {
2145 5430 : m_decl.SetMaxCount(count);
2146 5430 : return *this;
2147 : }
2148 :
2149 : /** Alias for GDALAlgorithmArgDecl::SetDisplayHintAboutRepetition() */
2150 : GDALInConstructionAlgorithmArg &
2151 1251 : SetDisplayHintAboutRepetition(bool displayHint)
2152 : {
2153 1251 : m_decl.SetDisplayHintAboutRepetition(displayHint);
2154 1251 : return *this;
2155 : }
2156 :
2157 : /** Alias for GDALAlgorithmArgDecl::SetPackedValuesAllowed() */
2158 9912 : GDALInConstructionAlgorithmArg &SetPackedValuesAllowed(bool allowed)
2159 : {
2160 9912 : m_decl.SetPackedValuesAllowed(allowed);
2161 9912 : return *this;
2162 : }
2163 :
2164 : /** Alias for GDALAlgorithmArgDecl::SetRepeatedArgAllowed() */
2165 2570 : GDALInConstructionAlgorithmArg &SetRepeatedArgAllowed(bool allowed)
2166 : {
2167 2570 : m_decl.SetRepeatedArgAllowed(allowed);
2168 2570 : return *this;
2169 : }
2170 :
2171 : /** Alias for GDALAlgorithmArgDecl::SetChoices() */
2172 : template <
2173 : typename T, typename... U,
2174 : typename std::enable_if<!std::is_same_v<T, std::vector<std::string> &>,
2175 : bool>::type = true>
2176 4345 : GDALInConstructionAlgorithmArg &SetChoices(T &&first, U &&...rest)
2177 : {
2178 4345 : m_decl.SetChoices(std::forward<T>(first), std::forward<U>(rest)...);
2179 4345 : return *this;
2180 : }
2181 :
2182 : /** Alias for GDALAlgorithmArgDecl::SetChoices() */
2183 : GDALInConstructionAlgorithmArg &
2184 379 : SetChoices(const std::vector<std::string> &choices)
2185 : {
2186 379 : m_decl.SetChoices(choices);
2187 379 : return *this;
2188 : }
2189 :
2190 : /** Alias for GDALAlgorithmArgDecl::SetHiddenChoices() */
2191 : template <typename T, typename... U>
2192 928 : GDALInConstructionAlgorithmArg &SetHiddenChoices(T &&first, U &&...rest)
2193 : {
2194 928 : m_decl.SetHiddenChoices(std::forward<T>(first),
2195 : std::forward<U>(rest)...);
2196 928 : return *this;
2197 : }
2198 :
2199 : /** Alias for GDALAlgorithmArgDecl::SetMinValueIncluded() */
2200 5539 : GDALInConstructionAlgorithmArg &SetMinValueIncluded(double min)
2201 : {
2202 5539 : m_decl.SetMinValueIncluded(min);
2203 5539 : return *this;
2204 : }
2205 :
2206 : /** Alias for GDALAlgorithmArgDecl::SetMinValueExcluded() */
2207 934 : GDALInConstructionAlgorithmArg &SetMinValueExcluded(double min)
2208 : {
2209 934 : m_decl.SetMinValueExcluded(min);
2210 934 : return *this;
2211 : }
2212 :
2213 : /** Alias for GDALAlgorithmArgDecl::SetMaxValueIncluded() */
2214 1099 : GDALInConstructionAlgorithmArg &SetMaxValueIncluded(double max)
2215 : {
2216 1099 : m_decl.SetMaxValueIncluded(max);
2217 1099 : return *this;
2218 : }
2219 :
2220 : /** Alias for GDALAlgorithmArgDecl::SetMaxValueExcluded() */
2221 193 : GDALInConstructionAlgorithmArg &SetMaxValueExcluded(double max)
2222 : {
2223 193 : m_decl.SetMaxValueExcluded(max);
2224 193 : return *this;
2225 : }
2226 :
2227 : /** Alias for GDALAlgorithmArgDecl::SetMinCharCount() */
2228 1094 : GDALInConstructionAlgorithmArg &SetMinCharCount(int count)
2229 : {
2230 1094 : m_decl.SetMinCharCount(count);
2231 1094 : return *this;
2232 : }
2233 :
2234 : /** Alias for GDALAlgorithmArgDecl::SetHidden() */
2235 18515 : GDALInConstructionAlgorithmArg &SetHidden()
2236 : {
2237 18515 : m_decl.SetHidden();
2238 18515 : return *this;
2239 : }
2240 :
2241 : /** Alias for GDALAlgorithmArgDecl::SetHiddenForCLI() */
2242 30280 : GDALInConstructionAlgorithmArg &SetHiddenForCLI(bool hiddenForCLI = true)
2243 : {
2244 30280 : m_decl.SetHiddenForCLI(hiddenForCLI);
2245 30280 : return *this;
2246 : }
2247 :
2248 : /** Alias for GDALAlgorithmArgDecl::SetHiddenForAPI() */
2249 35226 : GDALInConstructionAlgorithmArg &SetHiddenForAPI(bool hiddenForAPI = true)
2250 : {
2251 35226 : m_decl.SetHiddenForAPI(hiddenForAPI);
2252 35226 : return *this;
2253 : }
2254 :
2255 : /** Alias for GDALAlgorithmArgDecl::SetIsInput() */
2256 7027 : GDALInConstructionAlgorithmArg &SetIsInput(bool isInput = true)
2257 : {
2258 7027 : m_decl.SetIsInput(isInput);
2259 7027 : return *this;
2260 : }
2261 :
2262 : /** Alias for GDALAlgorithmArgDecl::SetIsOutput() */
2263 6723 : GDALInConstructionAlgorithmArg &SetIsOutput(bool isOutput = true)
2264 : {
2265 6723 : m_decl.SetIsOutput(isOutput);
2266 6723 : return *this;
2267 : }
2268 :
2269 : /** Alias for GDALAlgorithmArgDecl::SetReadFromFileAtSyntaxAllowed() */
2270 516 : GDALInConstructionAlgorithmArg &SetReadFromFileAtSyntaxAllowed()
2271 : {
2272 516 : m_decl.SetReadFromFileAtSyntaxAllowed();
2273 516 : return *this;
2274 : }
2275 :
2276 : /** Alias for GDALAlgorithmArgDecl::SetRemoveSQLCommentsEnabled() */
2277 516 : GDALInConstructionAlgorithmArg &SetRemoveSQLCommentsEnabled()
2278 : {
2279 516 : m_decl.SetRemoveSQLCommentsEnabled();
2280 516 : return *this;
2281 : }
2282 :
2283 : /** Alias for GDALAlgorithmArgDecl::SetAutoOpenDataset() */
2284 3416 : GDALInConstructionAlgorithmArg &SetAutoOpenDataset(bool autoOpen)
2285 : {
2286 3416 : m_decl.SetAutoOpenDataset(autoOpen);
2287 3416 : return *this;
2288 : }
2289 :
2290 : /** Alias for GDALAlgorithmArgDecl::SetMutualExclusionGroup() */
2291 : GDALInConstructionAlgorithmArg &
2292 9158 : SetMutualExclusionGroup(const std::string &group)
2293 : {
2294 9158 : m_decl.SetMutualExclusionGroup(group);
2295 9158 : return *this;
2296 : }
2297 :
2298 : /** Alias for GDALAlgorithmArgDecl::AddMetadataItem() */
2299 : GDALInConstructionAlgorithmArg &
2300 7789 : AddMetadataItem(const std::string &name,
2301 : const std::vector<std::string> &values)
2302 : {
2303 7789 : m_decl.AddMetadataItem(name, values);
2304 7789 : return *this;
2305 : }
2306 :
2307 : /** Alias for GDALAlgorithmArgDecl::SetDatasetType() */
2308 : GDALInConstructionAlgorithmArg &
2309 9549 : SetDatasetType(GDALArgDatasetType datasetType)
2310 : {
2311 9549 : m_decl.SetDatasetType(datasetType);
2312 9549 : return *this;
2313 : }
2314 :
2315 : /** Alias for GDALAlgorithmArgDecl::SetDatasetInputFlags() */
2316 5444 : GDALInConstructionAlgorithmArg &SetDatasetInputFlags(int flags)
2317 : {
2318 5444 : m_decl.SetDatasetInputFlags(flags);
2319 5444 : return *this;
2320 : }
2321 :
2322 : /** Alias for GDALAlgorithmArgDecl::SetDatasetOutputFlags() */
2323 2850 : GDALInConstructionAlgorithmArg &SetDatasetOutputFlags(int flags)
2324 : {
2325 2850 : m_decl.SetDatasetOutputFlags(flags);
2326 2850 : return *this;
2327 : }
2328 :
2329 : /** Register an action that is executed, once and exactly once, if the
2330 : * argument is explicitly set, at the latest by the ValidateArguments()
2331 : * method. */
2332 48531 : GDALInConstructionAlgorithmArg &AddAction(std::function<void()> f)
2333 : {
2334 48531 : m_actions.push_back(f);
2335 48531 : return *this;
2336 : }
2337 :
2338 : /** Register an action that is executed, once and exactly once, if the
2339 : * argument is explicitly set, at the latest by the ValidateArguments()
2340 : * method. If the provided function returns false, validation fails.
2341 : * The validation function of a given argument can only check the value of
2342 : * this argument, and cannot assume other arguments have already been set.
2343 : */
2344 21960 : GDALInConstructionAlgorithmArg &AddValidationAction(std::function<bool()> f)
2345 : {
2346 21960 : m_validationActions.push_back(f);
2347 21960 : return *this;
2348 : }
2349 :
2350 : /** Register a function that will return a list of valid choices for
2351 : * the value of the argument. This is typically used for autocompletion.
2352 : */
2353 25366 : GDALInConstructionAlgorithmArg &SetAutoCompleteFunction(
2354 : std::function<std::vector<std::string>(const std::string &)> f)
2355 : {
2356 25366 : m_autoCompleteFunction = std::move(f);
2357 25366 : return *this;
2358 : }
2359 :
2360 : /** Register an action to validate that the argument value is a valid
2361 : * CRS definition.
2362 : * @param noneAllowed Set to true to mean that "null" or "none" are allowed
2363 : * to mean to unset CRS.
2364 : * @param specialValues List of other allowed special values.
2365 : */
2366 : GDALInConstructionAlgorithmArg &
2367 : SetIsCRSArg(bool noneAllowed = false,
2368 : const std::vector<std::string> &specialValues =
2369 : std::vector<std::string>());
2370 :
2371 : /** Alias for GDALAlgorithmArgDecl::SetUserProvided() */
2372 22 : GDALInConstructionAlgorithmArg &SetUserProvided()
2373 : {
2374 22 : m_decl.SetUserProvided();
2375 22 : return *this;
2376 : }
2377 : };
2378 :
2379 : /************************************************************************/
2380 : /* GDALAlgorithmRegistry */
2381 : /************************************************************************/
2382 :
2383 : /** Registry of GDAL algorithms.
2384 : */
2385 12710 : class CPL_DLL GDALAlgorithmRegistry
2386 : {
2387 : public:
2388 : /** Special value to put in m_aliases to separate public alias from
2389 : * hidden aliases */
2390 : static constexpr const char *HIDDEN_ALIAS_SEPARATOR = "==hide==";
2391 :
2392 : virtual ~GDALAlgorithmRegistry();
2393 :
2394 : /** Algorithm information */
2395 : class AlgInfo
2396 : {
2397 : public:
2398 : /** Algorithm (short) name */
2399 : std::string m_name{};
2400 : /** Aliases */
2401 : std::vector<std::string> m_aliases{};
2402 : /** Creation function */
2403 : std::function<std::unique_ptr<GDALAlgorithm>()> m_creationFunc{};
2404 : };
2405 :
2406 : /** Register the algorithm of type MyAlgorithm.
2407 : */
2408 90024 : template <class MyAlgorithm> bool Register()
2409 : {
2410 180048 : AlgInfo info;
2411 90024 : info.m_name = MyAlgorithm::NAME;
2412 90024 : info.m_aliases = MyAlgorithm::GetAliasesStatic();
2413 94579 : info.m_creationFunc = []() -> std::unique_ptr<GDALAlgorithm>
2414 4747 : { return std::make_unique<MyAlgorithm>(); };
2415 180048 : return Register(info);
2416 : }
2417 :
2418 : /** Register an algorithm by its AlgInfo structure.
2419 : */
2420 : bool Register(const AlgInfo &info);
2421 :
2422 : /** Get the names of registered algorithms.
2423 : *
2424 : * This only returns the main name of each algorithm, not its potential
2425 : * alternate names.
2426 : */
2427 : std::vector<std::string> GetNames() const;
2428 :
2429 : /** Instantiate an algorithm by its name or one of its alias. */
2430 : virtual std::unique_ptr<GDALAlgorithm>
2431 : Instantiate(const std::string &name) const;
2432 :
2433 : /** Get an algorithm by its name. */
2434 2650 : const AlgInfo *GetInfo(const std::string &name) const
2435 : {
2436 2650 : auto iter = m_mapNameToInfo.find(name);
2437 2650 : return iter != m_mapNameToInfo.end() ? &(iter->second) : nullptr;
2438 : }
2439 :
2440 : /** Returns true if there are no algorithms registered. */
2441 5219 : bool empty() const
2442 : {
2443 5219 : return m_mapNameToInfo.empty();
2444 : }
2445 :
2446 : private:
2447 : std::map<std::string, AlgInfo> m_mapNameToInfo{};
2448 : std::map<std::string, AlgInfo> m_mapAliasToInfo{};
2449 : std::map<std::string, AlgInfo> m_mapHiddenAliasToInfo{};
2450 : };
2451 :
2452 : /************************************************************************/
2453 : /* GDALAlgorithm */
2454 : /************************************************************************/
2455 :
2456 : /** GDAL algorithm.
2457 : *
2458 : * An algorithm declares its name, description, help URL.
2459 : * It also defined arguments or (mutual exclusion) sub-algorithms.
2460 : *
2461 : * It can be used from the command line with the ParseCommandLineArguments()
2462 : * method, or users can iterate over the available arguments with the GetArgs()
2463 : * or GetArg() method and fill them programmatically with
2464 : * GDALAlgorithmArg::Set().
2465 : *
2466 : * Execution of the algorithm is done with the Run() method.
2467 : *
2468 : * This is an abstract class. Implementations must sub-class it and implement the
2469 : * RunImpl() method.
2470 : */
2471 :
2472 10731 : /* abstract */ class CPL_DLL GDALAlgorithm
2473 : {
2474 : friend struct test_gdal_algorithm::test_gdal_algorithm;
2475 :
2476 : public:
2477 : virtual ~GDALAlgorithm();
2478 :
2479 : /** Get the algorithm name */
2480 4225 : const std::string &GetName() const
2481 : {
2482 4225 : return m_name;
2483 : }
2484 :
2485 : /** Get the algorithm description (a few sentences at most) */
2486 45 : const std::string &GetDescription() const
2487 : {
2488 45 : return m_description;
2489 : }
2490 :
2491 : /** Get the long algorithm description. May be empty. */
2492 2 : const std::string &GetLongDescription() const
2493 : {
2494 2 : return m_longDescription;
2495 : }
2496 :
2497 : /** Get the algorithm help URL. If starting with '/', it is relative to
2498 : * "https://gdal.org".
2499 : */
2500 : const std::string &GetHelpURL() const
2501 : {
2502 : return m_helpURL;
2503 : }
2504 :
2505 : /** Get the algorithm full URL, resolving relative URLs. */
2506 761 : const std::string &GetHelpFullURL() const
2507 : {
2508 761 : return m_helpFullURL;
2509 : }
2510 :
2511 : /** Returns whether this algorithm is hidden */
2512 805 : bool IsHidden() const
2513 : {
2514 805 : return m_hidden;
2515 : }
2516 :
2517 : /** Returns whether this algorithm has sub-algorithms */
2518 : bool HasSubAlgorithms() const;
2519 :
2520 : /** Get the names of registered algorithms.
2521 : *
2522 : * This only returns the main name of each algorithm, not its potential
2523 : * alternate names.
2524 : */
2525 : std::vector<std::string> GetSubAlgorithmNames() const;
2526 :
2527 : /** Instantiate an algorithm by its name (or its alias). */
2528 : std::unique_ptr<GDALAlgorithm>
2529 : InstantiateSubAlgorithm(const std::string &name,
2530 : bool suggestionAllowed = true) const;
2531 :
2532 : /** Return the potential arguments of the algorithm. */
2533 : const std::vector<std::unique_ptr<GDALAlgorithmArg>> &GetArgs() const
2534 : {
2535 : return m_args;
2536 : }
2537 :
2538 : /** Return the potential arguments of the algorithm. */
2539 2293 : std::vector<std::unique_ptr<GDALAlgorithmArg>> &GetArgs()
2540 : {
2541 2293 : return m_args;
2542 : }
2543 :
2544 : /** Return a likely matching argument using a Damerau-Levenshtein distance */
2545 : std::string GetSuggestionForArgumentName(const std::string &osName) const;
2546 :
2547 : /** Return an argument from its long name, short name or an alias */
2548 53335 : GDALAlgorithmArg *GetArg(const std::string &osName,
2549 : bool suggestionAllowed = false)
2550 : {
2551 53335 : return GetArg(osName, suggestionAllowed, /* isConst = */ false);
2552 : }
2553 :
2554 : /** Return an argument from its long name, short name or an alias */
2555 71 : GDALAlgorithmArg &operator[](const std::string &osName)
2556 : {
2557 71 : auto alg = GetArg(osName, false);
2558 71 : if (!alg)
2559 : {
2560 1 : ReportError(CE_Failure, CPLE_AppDefined,
2561 : "Argument '%s' does not exist", osName.c_str());
2562 1 : return m_dummyArg;
2563 : }
2564 70 : return *alg;
2565 : }
2566 :
2567 : /** Return an argument from its long name, short name or an alias */
2568 12293 : const GDALAlgorithmArg *GetArg(const std::string &osName,
2569 : bool suggestionAllowed = false) const
2570 : {
2571 12293 : return const_cast<GDALAlgorithm *>(this)->GetArg(
2572 12293 : osName, suggestionAllowed, /* isConst = */ true);
2573 : }
2574 :
2575 : /** Return an argument from its long name, short name or an alias */
2576 2 : const GDALAlgorithmArg &operator[](const std::string &osName) const
2577 : {
2578 2 : const auto alg = GetArg(osName, false);
2579 2 : if (!alg)
2580 : {
2581 1 : ReportError(CE_Failure, CPLE_AppDefined,
2582 : "Argument '%s' does not exist", osName.c_str());
2583 1 : return m_dummyArg;
2584 : }
2585 1 : return *alg;
2586 : }
2587 :
2588 : /** Set the calling path to this algorithm.
2589 : *
2590 : * For example the main "gdal" CLI will set the path to the name of its
2591 : * binary before calling ParseCommandLineArguments().
2592 : */
2593 6321 : void SetCallPath(const std::vector<std::string> &path)
2594 : {
2595 6321 : m_callPath = path;
2596 6321 : }
2597 :
2598 : /** Set hint before calling ParseCommandLineArguments() that it must
2599 : * try to be be graceful when possible, e.g. accepting
2600 : * "gdal raster convert in.tif out.tif --co"
2601 : */
2602 76 : void SetParseForAutoCompletion()
2603 : {
2604 76 : m_parseForAutoCompletion = true;
2605 76 : }
2606 :
2607 : /** Set the reference file paths used to interpret relative paths.
2608 : *
2609 : * This has only effect if called before calling ParseCommandLineArguments().
2610 : */
2611 1758 : void SetReferencePathForRelativePaths(const std::string &referencePath)
2612 : {
2613 1758 : m_referencePath = referencePath;
2614 1758 : }
2615 :
2616 : /** Return the reference file paths used to interpret relative paths. */
2617 1408 : const std::string &GetReferencePathForRelativePaths() const
2618 : {
2619 1408 : return m_referencePath;
2620 : }
2621 :
2622 : /** Returns whether this algorithm supports a streamed output dataset. */
2623 1658 : bool SupportsStreamedOutput() const
2624 : {
2625 1658 : return m_supportsStreamedOutput;
2626 : }
2627 :
2628 : /** Indicates that the algorithm must be run to generate a streamed output
2629 : * dataset. In particular, this must be used as a hint by algorithms to
2630 : * avoid writing files on the filesystem. This is used by the GDALG driver
2631 : * when executing a serialized algorithm command line.
2632 : *
2633 : * This has only effect if called before calling Run().
2634 : */
2635 69 : void SetExecutionForStreamedOutput()
2636 : {
2637 69 : m_executionForStreamOutput = true;
2638 69 : }
2639 :
2640 : /** Parse a command line argument, which does not include the algorithm
2641 : * name, to set the value of corresponding arguments.
2642 : */
2643 : virtual bool
2644 : ParseCommandLineArguments(const std::vector<std::string> &args);
2645 :
2646 : /** Validate that all constraints are met.
2647 : *
2648 : * This method may emit several errors if several constraints are not met.
2649 : *
2650 : * This method is automatically executed by ParseCommandLineArguments()
2651 : * and Run(), and thus does generally not need to be explicitly called.
2652 : * Derived classes overriding this method should generally call the base
2653 : * method.
2654 : */
2655 : virtual bool ValidateArguments();
2656 :
2657 : /** Execute the algorithm, starting with ValidateArguments() and then
2658 : * calling RunImpl().
2659 : */
2660 : bool Run(GDALProgressFunc pfnProgress = nullptr,
2661 : void *pProgressData = nullptr);
2662 :
2663 : /** Complete any pending actions, and return the final status.
2664 : * This is typically useful for algorithm that generate an output dataset.
2665 : */
2666 : virtual bool Finalize();
2667 :
2668 : /** Usage options */
2669 : struct UsageOptions
2670 : {
2671 : /** Whether this is a pipeline step */
2672 : bool isPipelineStep;
2673 : /** Maximum width of the names of the options */
2674 : size_t maxOptLen;
2675 : /** Whether this is a pipeline main */
2676 : bool isPipelineMain;
2677 :
2678 125 : UsageOptions()
2679 125 : : isPipelineStep(false), maxOptLen(0), isPipelineMain(false)
2680 : {
2681 125 : }
2682 : };
2683 :
2684 : /** Return the usage as a string appropriate for command-line interface
2685 : * \--help output.
2686 : */
2687 : virtual std::string
2688 : GetUsageForCLI(bool shortUsage,
2689 : const UsageOptions &usageOptions = UsageOptions()) const;
2690 :
2691 : /** Return the usage of the algorithm as a JSON-serialized string.
2692 : *
2693 : * This can be used to dynamically generate interfaces to algorithms.
2694 : */
2695 : virtual std::string GetUsageAsJSON() const;
2696 :
2697 : /** Return the actual algorithm that is going to be invoked, when the
2698 : * current algorithm has sub-algorithms.
2699 : *
2700 : * Only valid after ParseCommandLineArguments() has been called.
2701 : */
2702 1965 : GDALAlgorithm &GetActualAlgorithm()
2703 : {
2704 1965 : if (m_selectedSubAlg)
2705 789 : return m_selectedSubAlg->GetActualAlgorithm();
2706 1176 : return *this;
2707 : }
2708 :
2709 : /** Whether the \--help flag has been specified. */
2710 4 : bool IsHelpRequested() const
2711 : {
2712 4 : return m_helpRequested;
2713 : }
2714 :
2715 : /** Whether the \--json-usage flag has been specified. */
2716 1 : bool IsJSONUsageRequested() const
2717 : {
2718 1 : return m_JSONUsageRequested;
2719 : }
2720 :
2721 : /** Whether the \--progress flag has been specified. */
2722 298 : bool IsProgressBarRequested() const
2723 : {
2724 298 : if (m_selectedSubAlg)
2725 194 : return m_selectedSubAlg->IsProgressBarRequested();
2726 104 : return m_progressBarRequested;
2727 : }
2728 :
2729 : /** Return alias names (generally short) for the current algorithm. */
2730 7 : const std::vector<std::string> &GetAliases() const
2731 : {
2732 7 : return m_aliases;
2733 : }
2734 :
2735 : //! @cond Doxygen_Suppress
2736 : /** Return alias names. This method should be redefined in derived classes
2737 : * that want to define aliases.
2738 : */
2739 98602 : static std::vector<std::string> GetAliasesStatic()
2740 : {
2741 98602 : return {};
2742 : }
2743 :
2744 : //! @endcond
2745 :
2746 : /** Used by the "gdal info" special algorithm when it first tries to
2747 : * run "gdal raster info", to inherit from the potential special flags,
2748 : * such as \--help or \--json-usage, that this later algorithm has received.
2749 : */
2750 375 : bool PropagateSpecialActionTo(GDALAlgorithm *target)
2751 : {
2752 375 : target->m_calledFromCommandLine = m_calledFromCommandLine;
2753 375 : target->m_progressBarRequested = m_progressBarRequested;
2754 375 : target->m_quiet = m_quiet;
2755 375 : if (m_specialActionRequested)
2756 : {
2757 30 : target->m_specialActionRequested = m_specialActionRequested;
2758 30 : target->m_helpRequested = m_helpRequested;
2759 30 : target->m_helpDocRequested = m_helpDocRequested;
2760 30 : target->m_JSONUsageRequested = m_JSONUsageRequested;
2761 30 : return true;
2762 : }
2763 345 : return false;
2764 : }
2765 :
2766 : /** Return auto completion suggestions */
2767 : virtual std::vector<std::string>
2768 : GetAutoComplete(std::vector<std::string> &args, bool lastWordIsComplete,
2769 : bool showAllOptions);
2770 :
2771 : /** Set whether the algorithm is called from the command line. */
2772 217 : void SetCalledFromCommandLine()
2773 : {
2774 217 : m_calledFromCommandLine = true;
2775 217 : }
2776 :
2777 : /** Return whether the algorithm is called from the command line. */
2778 2535 : bool IsCalledFromCommandLine() const
2779 : {
2780 2535 : return m_calledFromCommandLine;
2781 : }
2782 :
2783 : /** Save command line in a .gdalg.json file.
2784 : * If filename is empty, outString will contain the serialized JSON content.
2785 : */
2786 : static bool SaveGDALG(const std::string &filename, std::string &outString,
2787 : const std::string &commandLine);
2788 :
2789 : //! @cond Doxygen_Suppress
2790 : void ReportError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,
2791 : ...) const CPL_PRINT_FUNC_FORMAT(4, 5);
2792 : //! @endcond
2793 :
2794 : protected:
2795 : friend class GDALInConstructionAlgorithmArg;
2796 : friend class GDALRasterReprojectUtils;
2797 :
2798 : /** Selected sub-algorithm. Set by ParseCommandLineArguments() when
2799 : * handling over on a sub-algorithm. */
2800 : GDALAlgorithm *m_selectedSubAlg = nullptr;
2801 :
2802 : /** Call path to the current algorithm. For example, for "gdal convert raster",
2803 : * it is ["gdal", "convert"]
2804 : */
2805 : std::vector<std::string> m_callPath{};
2806 :
2807 : /** Long description of the algorithm */
2808 : std::string m_longDescription{};
2809 :
2810 : /** Whether a progress bar is requested (value of \--progress argument) */
2811 : bool m_progressBarRequested = true;
2812 :
2813 : /** Whether a progress bar is disabled (value of \--quiet argument) */
2814 : bool m_quiet = false;
2815 :
2816 : friend class GDALVectorPipelineAlgorithm;
2817 : /** Whether ValidateArguments() should be skipped during ParseCommandLineArguments() */
2818 : bool m_skipValidationInParseCommandLine = false;
2819 :
2820 : friend class GDALAlgorithmRegistry; // to set m_aliases
2821 : /** Algorithm alias names */
2822 : std::vector<std::string> m_aliases{};
2823 :
2824 : /** Whether this algorithm supports a streamed output dataset. */
2825 : bool m_supportsStreamedOutput = false;
2826 :
2827 : /** Whether this algorithm is run to generated a streamed output dataset. */
2828 : bool m_executionForStreamOutput = false;
2829 :
2830 : /** Whether this algorithm should be hidden (but can be instantiate if name known) */
2831 : bool m_hidden = false;
2832 :
2833 : /** Map a dataset name to its object (used for nested pipelines) */
2834 : std::map<std::string, GDALDataset *> m_oMapDatasetNameToDataset{};
2835 :
2836 : /** Constructor */
2837 : GDALAlgorithm(const std::string &name, const std::string &description,
2838 : const std::string &helpURL);
2839 :
2840 : /** Special processing for an argument of type GAAT_DATASET */
2841 : bool ProcessDatasetArg(GDALAlgorithmArg *arg, GDALAlgorithm *algForOutput);
2842 :
2843 : /** Register the sub-algorithm of type MyAlgorithm.
2844 : */
2845 77404 : template <class MyAlgorithm> bool RegisterSubAlgorithm()
2846 : {
2847 77404 : return m_subAlgRegistry.Register<MyAlgorithm>();
2848 : }
2849 :
2850 : /** Register a sub-algoritm by its AlgInfo structure.
2851 : */
2852 3010 : bool RegisterSubAlgorithm(const GDALAlgorithmRegistry::AlgInfo &info)
2853 : {
2854 3010 : return m_subAlgRegistry.Register(info);
2855 : }
2856 :
2857 : /** Allow arbitrary user arguments using long name syntax (--something) */
2858 180 : void AllowArbitraryLongNameArgs()
2859 : {
2860 180 : m_arbitraryLongNameArgsAllowed = true;
2861 180 : }
2862 :
2863 : /** Add boolean argument. */
2864 : GDALInConstructionAlgorithmArg &AddArg(const std::string &longName,
2865 : char chShortName,
2866 : const std::string &helpMessage,
2867 : bool *pValue);
2868 :
2869 : /** Add string argument. */
2870 : GDALInConstructionAlgorithmArg &AddArg(const std::string &longName,
2871 : char chShortName,
2872 : const std::string &helpMessage,
2873 : std::string *pValue);
2874 :
2875 : /** Add integer argument. */
2876 : GDALInConstructionAlgorithmArg &AddArg(const std::string &longName,
2877 : char chShortName,
2878 : const std::string &helpMessage,
2879 : int *pValue);
2880 :
2881 : /** Add real argument. */
2882 : GDALInConstructionAlgorithmArg &AddArg(const std::string &longName,
2883 : char chShortName,
2884 : const std::string &helpMessage,
2885 : double *pValue);
2886 :
2887 : /** Register an auto complete function for a filename argument */
2888 : static void
2889 : SetAutoCompleteFunctionForFilename(GDALInConstructionAlgorithmArg &arg,
2890 : GDALArgDatasetType type);
2891 :
2892 : /** Add dataset argument. */
2893 : GDALInConstructionAlgorithmArg &
2894 : AddArg(const std::string &longName, char chShortName,
2895 : const std::string &helpMessage, GDALArgDatasetValue *pValue,
2896 : GDALArgDatasetType type = GDAL_OF_RASTER | GDAL_OF_VECTOR |
2897 : GDAL_OF_MULTIDIM_RASTER);
2898 :
2899 : /** Add list of string argument. */
2900 : GDALInConstructionAlgorithmArg &AddArg(const std::string &longName,
2901 : char chShortName,
2902 : const std::string &helpMessage,
2903 : std::vector<std::string> *pValue);
2904 :
2905 : /** Add list of integer argument. */
2906 : GDALInConstructionAlgorithmArg &AddArg(const std::string &longName,
2907 : char chShortName,
2908 : const std::string &helpMessage,
2909 : std::vector<int> *pValue);
2910 :
2911 : /** Add list of real argument. */
2912 : GDALInConstructionAlgorithmArg &AddArg(const std::string &longName,
2913 : char chShortName,
2914 : const std::string &helpMessage,
2915 : std::vector<double> *pValue);
2916 :
2917 : /** Add list of dataset argument. */
2918 : GDALInConstructionAlgorithmArg &
2919 : AddArg(const std::string &longName, char chShortName,
2920 : const std::string &helpMessage,
2921 : std::vector<GDALArgDatasetValue> *pValue,
2922 : GDALArgDatasetType type = GDAL_OF_RASTER | GDAL_OF_VECTOR |
2923 : GDAL_OF_MULTIDIM_RASTER);
2924 :
2925 : /** Add input dataset argument. */
2926 : GDALInConstructionAlgorithmArg &AddInputDatasetArg(
2927 : GDALArgDatasetValue *pValue,
2928 : GDALArgDatasetType type = GDAL_OF_RASTER | GDAL_OF_VECTOR |
2929 : GDAL_OF_MULTIDIM_RASTER,
2930 : bool positionalAndRequired = true, const char *helpMessage = nullptr);
2931 :
2932 : /** Add input dataset argument. */
2933 : GDALInConstructionAlgorithmArg &AddInputDatasetArg(
2934 : std::vector<GDALArgDatasetValue> *pValue,
2935 : GDALArgDatasetType type = GDAL_OF_RASTER | GDAL_OF_VECTOR |
2936 : GDAL_OF_MULTIDIM_RASTER,
2937 : bool positionalAndRequired = true, const char *helpMessage = nullptr);
2938 :
2939 : /** Add (input) open option(s) argument. */
2940 : GDALInConstructionAlgorithmArg &
2941 : AddOpenOptionsArg(std::vector<std::string> *pValue,
2942 : const char *helpMessage = nullptr);
2943 :
2944 : /** Add output open option(s) argument. */
2945 : GDALInConstructionAlgorithmArg &
2946 : AddOutputOpenOptionsArg(std::vector<std::string> *pValue,
2947 : const char *helpMessage = nullptr);
2948 :
2949 : /** Add input format(s) argument. */
2950 : GDALInConstructionAlgorithmArg &
2951 : AddInputFormatsArg(std::vector<std::string> *pValue,
2952 : const char *helpMessage = nullptr);
2953 :
2954 : /** Add output dataset argument. */
2955 : GDALInConstructionAlgorithmArg &AddOutputDatasetArg(
2956 : GDALArgDatasetValue *pValue,
2957 : GDALArgDatasetType type = GDAL_OF_RASTER | GDAL_OF_VECTOR |
2958 : GDAL_OF_MULTIDIM_RASTER,
2959 : bool positionalAndRequired = true, const char *helpMessage = nullptr);
2960 :
2961 : /** Add \--overwrite argument. */
2962 : GDALInConstructionAlgorithmArg &
2963 : AddOverwriteArg(bool *pValue, const char *helpMessage = nullptr);
2964 :
2965 : /** Add \--overwrite-layer argument. */
2966 : GDALInConstructionAlgorithmArg &
2967 : AddOverwriteLayerArg(bool *pValue, const char *helpMessage = nullptr);
2968 :
2969 : /** Add \--update argument. */
2970 : GDALInConstructionAlgorithmArg &
2971 : AddUpdateArg(bool *pValue, const char *helpMessage = nullptr);
2972 :
2973 : /** Add \--append argument for a vector layer. */
2974 : GDALInConstructionAlgorithmArg &
2975 : AddAppendLayerArg(bool *pValue, const char *helpMessage = nullptr);
2976 :
2977 : /** Add (non-CLI) output-string argument. */
2978 : GDALInConstructionAlgorithmArg &
2979 : AddOutputStringArg(std::string *pValue, const char *helpMessage = nullptr);
2980 :
2981 : /** Add (hidden) stdout argument. */
2982 : GDALInConstructionAlgorithmArg &
2983 : AddStdoutArg(bool *pValue, const char *helpMessage = nullptr);
2984 :
2985 : /** Add output format argument. */
2986 : GDALInConstructionAlgorithmArg &
2987 : AddOutputFormatArg(std::string *pValue, bool bStreamAllowed = false,
2988 : bool bGDALGAllowed = false,
2989 : const char *helpMessage = nullptr);
2990 :
2991 : /** Add output data type argument. */
2992 : GDALInConstructionAlgorithmArg &
2993 : AddOutputDataTypeArg(std::string *pValue,
2994 : const char *helpMessage = nullptr);
2995 :
2996 : /** Add nodata argument. */
2997 : GDALInConstructionAlgorithmArg &
2998 : AddNodataArg(std::string *pValue, bool noneAllowed,
2999 : const std::string &optionName = "nodata",
3000 : const char *helpMessage = nullptr);
3001 :
3002 : /** Add creation option(s) argument. */
3003 : GDALInConstructionAlgorithmArg &
3004 : AddCreationOptionsArg(std::vector<std::string> *pValue,
3005 : const char *helpMessage = nullptr);
3006 :
3007 : /** Add layer creation option(s) argument. */
3008 : GDALInConstructionAlgorithmArg &
3009 : AddLayerCreationOptionsArg(std::vector<std::string> *pValue,
3010 : const char *helpMessage = nullptr);
3011 :
3012 : /** Add (single) layer name argument. */
3013 : GDALInConstructionAlgorithmArg &
3014 : AddLayerNameArg(std::string *pValue, const char *helpMessage = nullptr);
3015 :
3016 : /** Add (single) output layer name argument. */
3017 : GDALInConstructionAlgorithmArg &
3018 : AddOutputLayerNameArg(std::string *pValue,
3019 : const char *helpMessage = nullptr);
3020 :
3021 : /** Add (potentially multiple) layer name(s) argument. */
3022 : GDALInConstructionAlgorithmArg &
3023 : AddLayerNameArg(std::vector<std::string> *pValue,
3024 : const char *helpMessage = nullptr);
3025 :
3026 : /** Add geometry type argument */
3027 : GDALInConstructionAlgorithmArg &
3028 : AddGeometryTypeArg(std::string *pValue, const char *helpMessage = nullptr);
3029 :
3030 : /** Register an auto complete function for a layer name argument */
3031 : static void SetAutoCompleteFunctionForLayerName(
3032 : GDALInConstructionAlgorithmArg &layerArg,
3033 : GDALInConstructionAlgorithmArg &datasetArg);
3034 :
3035 : /** Add (single) band argument. */
3036 : GDALInConstructionAlgorithmArg &
3037 : AddBandArg(int *pValue, const char *helpMessage = nullptr);
3038 :
3039 : /** Add (potentially multiple) band argument. */
3040 : GDALInConstructionAlgorithmArg &
3041 : AddBandArg(std::vector<int> *pValue, const char *helpMessage = nullptr);
3042 :
3043 : /** Add bbox=xmin,ymin,xmax,ymax argument. */
3044 : GDALInConstructionAlgorithmArg &
3045 : AddBBOXArg(std::vector<double> *pValue, const char *helpMessage = nullptr);
3046 :
3047 : /** Add active layer argument. */
3048 : GDALInConstructionAlgorithmArg &
3049 : AddActiveLayerArg(std::string *pValue, const char *helpMessage = nullptr);
3050 :
3051 : /** A number of thread argument. The final value is stored in *pValue.
3052 : * pStrValue must be provided as temporary storage, and its initial value
3053 : * (if not empty) is used as the SetDefault() value.
3054 : */
3055 : GDALInConstructionAlgorithmArg &
3056 : AddNumThreadsArg(int *pValue, std::string *pStrValue,
3057 : const char *helpMessage = nullptr);
3058 :
3059 : /** Add an argument to ask writing absolute paths. */
3060 : GDALInConstructionAlgorithmArg &
3061 : AddAbsolutePathArg(bool *pValue, const char *helpMessage = nullptr);
3062 :
3063 : /** Add an argument for pixel function name */
3064 : GDALInConstructionAlgorithmArg &
3065 : AddPixelFunctionNameArg(std::string *pValue,
3066 : const char *helpMessage = nullptr);
3067 :
3068 : /** Add an argument for pixel function arguments */
3069 : GDALInConstructionAlgorithmArg &
3070 : AddPixelFunctionArgsArg(std::vector<std::string> *pValue,
3071 : const char *helpMessage = nullptr);
3072 :
3073 : /** Add \--quiet (and hidden \--progress) argument. */
3074 : void AddProgressArg();
3075 :
3076 : /** Register an action that is executed by the ValidateArguments()
3077 : * method. If the provided function returns false, validation fails.
3078 : * Such validation function should typically be used to ensure
3079 : * cross-argument validation. For validation of individual arguments,
3080 : * GDALAlgorithmArg::AddValidationAction should rather be called.
3081 : */
3082 12357 : void AddValidationAction(std::function<bool()> f)
3083 : {
3084 12357 : m_validationActions.push_back(f);
3085 12357 : }
3086 :
3087 : /** Add KEY=VALUE suggestion from open, creation options */
3088 : static bool AddOptionsSuggestions(const char *pszXML, int datasetType,
3089 : const std::string ¤tValue,
3090 : std::vector<std::string> &oRet);
3091 :
3092 : /** Validation function to use for key=value type of arguments. */
3093 : bool ParseAndValidateKeyValue(GDALAlgorithmArg &arg);
3094 :
3095 : /** Method used by GDALRaster|VectorPipelineAlgorithm */
3096 : bool RunPreStepPipelineValidations() const;
3097 :
3098 : /** Return whether output-format or output arguments express GDALG output */
3099 : bool IsGDALGOutput() const;
3100 :
3101 : /** Return value for ProcessGDALGOutput */
3102 : enum class ProcessGDALGOutputRet
3103 : {
3104 : /** GDALG output requested and successful. */
3105 : GDALG_OK,
3106 : /** GDALG output requested but an error has occurred. */
3107 : GDALG_ERROR,
3108 : /** GDALG output not requeste. RunImpl() must be run. */
3109 : NOT_GDALG,
3110 : };
3111 :
3112 : /** Process output to a .gdalg file */
3113 : virtual ProcessGDALGOutputRet ProcessGDALGOutput();
3114 :
3115 : /** Method executed by Run() when m_executionForStreamOutput is set to
3116 : * ensure the command is safe to execute in a streamed dataset context.
3117 : */
3118 : virtual bool CheckSafeForStreamOutput();
3119 :
3120 : /** Validate a format argument */
3121 : bool ValidateFormat(const GDALAlgorithmArg &arg, bool bStreamAllowed,
3122 : bool bGDALGAllowed) const;
3123 :
3124 : /** Completion function for a format argument */
3125 : static std::vector<std::string>
3126 : FormatAutoCompleteFunction(const GDALAlgorithmArg &arg, bool bStreamAllowed,
3127 : bool bGDALGAllowed);
3128 :
3129 : //! @cond Doxygen_Suppress
3130 : void AddAliasFor(GDALInConstructionAlgorithmArg *arg,
3131 : const std::string &alias);
3132 :
3133 : void AddShortNameAliasFor(GDALInConstructionAlgorithmArg *arg,
3134 : char shortNameAlias);
3135 :
3136 : void SetPositional(GDALInConstructionAlgorithmArg *arg);
3137 :
3138 : std::vector<std::string>
3139 : OpenOptionCompleteFunction(const std::string ¤tValue) const;
3140 :
3141 : //! @endcond
3142 :
3143 : /** Whether this argument name is the one of a well-known boolean argument */
3144 : static bool IsKnownOutputRelatedBooleanArgName(std::string_view osName);
3145 :
3146 : /** Set whether this algorithm should be reported in JSON usage. */
3147 369 : void SetDisplayInJSONUsage(bool b)
3148 : {
3149 369 : m_displayInJSONUsage = b;
3150 369 : }
3151 :
3152 : /** Method that an algorithm can implement to issue a warning message about
3153 : * its deprecation. This is called at the beginning of the Run() method.
3154 : */
3155 3034 : virtual void WarnIfDeprecated()
3156 : {
3157 3034 : }
3158 :
3159 : /** Return the list of arguments for CLI usage */
3160 : std::pair<std::vector<std::pair<GDALAlgorithmArg *, std::string>>, size_t>
3161 : GetArgNamesForCLI() const;
3162 :
3163 : //! @cond Doxygen_Suppress
3164 : std::string GetUsageForCLIEnd() const;
3165 : //! @endcond
3166 :
3167 : private:
3168 : const std::string m_name{};
3169 : const std::string m_description{};
3170 : const std::string m_helpURL{};
3171 : const std::string m_helpFullURL{};
3172 : bool m_parsedSubStringAlreadyCalled = false;
3173 : bool m_displayInJSONUsage = true;
3174 : bool m_specialActionRequested = false;
3175 : bool m_helpRequested = false;
3176 : bool m_calledFromCommandLine = false;
3177 :
3178 : // Used by program-output directives in .rst files
3179 : bool m_helpDocRequested = false;
3180 :
3181 : bool m_JSONUsageRequested = false;
3182 : bool m_parseForAutoCompletion = false;
3183 : std::string m_referencePath{};
3184 : std::vector<std::string> m_dummyConfigOptions{};
3185 : std::vector<std::unique_ptr<GDALAlgorithmArg>> m_args{};
3186 : std::map<std::string, GDALAlgorithmArg *> m_mapLongNameToArg{};
3187 : std::map<std::string, GDALAlgorithmArg *> m_mapShortNameToArg{};
3188 : std::vector<GDALAlgorithmArg *> m_positionalArgs{};
3189 : GDALAlgorithmRegistry m_subAlgRegistry{};
3190 : std::unique_ptr<GDALAlgorithm> m_selectedSubAlgHolder{};
3191 : std::function<std::vector<std::string>(const std::vector<std::string> &)>
3192 : m_autoCompleteFunction{};
3193 : std::vector<std::function<bool()>> m_validationActions{};
3194 :
3195 : std::string m_dummyVal{};
3196 : GDALAlgorithmArg m_dummyArg{
3197 : GDALAlgorithmArgDecl("dummy", 0, "", GAAT_STRING), &m_dummyVal};
3198 :
3199 : /** Whether arbitrary user arguments using long name syntax (--something)
3200 : * are allowed.
3201 : */
3202 : bool m_arbitraryLongNameArgsAllowed = false;
3203 :
3204 : std::vector<std::unique_ptr<std::string>>
3205 : m_arbitraryLongNameArgsValuesStr{};
3206 : std::vector<std::unique_ptr<bool>> m_arbitraryLongNameArgsValuesBool{};
3207 :
3208 : friend GDALAlgorithmArgH GDALAlgorithmGetArg(GDALAlgorithmH hAlg,
3209 : const char *pszArgName);
3210 : friend GDALAlgorithmArgH
3211 : GDALAlgorithmGetArgNonConst(GDALAlgorithmH hAlg, const char *pszArgName);
3212 : GDALAlgorithmArg *GetArg(const std::string &osName, bool suggestionAllowed,
3213 : bool isConst);
3214 :
3215 : GDALInConstructionAlgorithmArg &
3216 : AddArg(std::unique_ptr<GDALInConstructionAlgorithmArg> arg);
3217 : bool ParseArgument(
3218 : GDALAlgorithmArg *arg, const std::string &name,
3219 : const std::string &value,
3220 : std::map<
3221 : GDALAlgorithmArg *,
3222 : std::variant<std::vector<std::string>, std::vector<int>,
3223 : std::vector<double>, std::vector<GDALArgDatasetValue>>>
3224 : &inConstructionValues);
3225 :
3226 : bool ValidateBandArg() const;
3227 :
3228 : virtual bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) = 0;
3229 :
3230 : /** Extract the last option and its potential value from the provided
3231 : * argument list, and remove them from the list.
3232 : */
3233 : void ExtractLastOptionAndValue(std::vector<std::string> &args,
3234 : std::string &option,
3235 : std::string &value) const;
3236 :
3237 : GDALAlgorithm(const GDALAlgorithm &) = delete;
3238 : GDALAlgorithm &operator=(const GDALAlgorithm &) = delete;
3239 : };
3240 :
3241 : //! @cond Doxygen_Suppress
3242 : struct GDALAlgorithmHS
3243 : {
3244 : private:
3245 : std::unique_ptr<GDALAlgorithm> uniquePtr{};
3246 :
3247 : GDALAlgorithmHS(const GDALAlgorithmHS &) = delete;
3248 : GDALAlgorithmHS &operator=(const GDALAlgorithmHS &) = delete;
3249 :
3250 : public:
3251 : GDALAlgorithm *ptr = nullptr;
3252 :
3253 756 : GDALAlgorithmHS() = default;
3254 :
3255 3757 : explicit GDALAlgorithmHS(std::unique_ptr<GDALAlgorithm> alg)
3256 3757 : : uniquePtr(std::move(alg)), ptr(uniquePtr.get())
3257 : {
3258 3757 : }
3259 :
3260 756 : static std::unique_ptr<GDALAlgorithmHS> FromRef(GDALAlgorithm &alg)
3261 : {
3262 756 : auto ret = std::make_unique<GDALAlgorithmHS>();
3263 756 : ret->ptr = &alg;
3264 756 : return ret;
3265 : }
3266 : };
3267 :
3268 : /************************************************************************/
3269 : /* GDALContainerAlgorithm */
3270 : /************************************************************************/
3271 :
3272 : class CPL_DLL GDALContainerAlgorithm : public GDALAlgorithm
3273 : {
3274 : public:
3275 187 : explicit GDALContainerAlgorithm(
3276 : const std::string &name, const std::string &description = std::string(),
3277 : const std::string &helpURL = std::string())
3278 187 : : GDALAlgorithm(name, description, helpURL)
3279 : {
3280 187 : }
3281 :
3282 : protected:
3283 : bool RunImpl(GDALProgressFunc, void *) override;
3284 : };
3285 :
3286 : //! @endcond
3287 :
3288 : /************************************************************************/
3289 : /* GDALGlobalAlgorithmRegistry */
3290 : /************************************************************************/
3291 :
3292 : /** Global registry of GDAL algorithms.
3293 : */
3294 3154 : class CPL_DLL GDALGlobalAlgorithmRegistry final : public GDALAlgorithmRegistry
3295 : {
3296 : public:
3297 : /** Name of the root "gdal" algorithm. */
3298 : static constexpr const char *ROOT_ALG_NAME = "gdal";
3299 :
3300 : /** Get the singleton */
3301 : static GDALGlobalAlgorithmRegistry &GetSingleton();
3302 :
3303 : /** Instantiate an algorithm by its name or one of its alias. */
3304 : std::unique_ptr<GDALAlgorithm>
3305 : Instantiate(const std::string &name) const override;
3306 :
3307 : /** Instantiation function */
3308 : using InstantiateFunc = std::function<std::unique_ptr<GDALAlgorithm>()>;
3309 :
3310 : /** Declare the algorithm designed by its path (omitting leading path)
3311 : * and provide its instantiation method.
3312 : * For example {"driver", "pdf", "list-layers"}
3313 : *
3314 : * This is typically used by plugins to register extra algorithms.
3315 : */
3316 : void DeclareAlgorithm(const std::vector<std::string> &path,
3317 : InstantiateFunc instantiateFunc);
3318 :
3319 : /** Return the direct declared (as per DeclareAlgorithm()) subalgorithms
3320 : * of the given path. */
3321 : std::vector<std::string>
3322 : GetDeclaredSubAlgorithmNames(const std::vector<std::string> &path) const;
3323 :
3324 : /** Return whether a subalgorithm is declared at the given path. */
3325 : bool HasDeclaredSubAlgorithm(const std::vector<std::string> &path) const;
3326 :
3327 : /** Instantiate a declared (as per DeclareAlgorithm()) subalgorithm. */
3328 : std::unique_ptr<GDALAlgorithm>
3329 : InstantiateDeclaredSubAlgorithm(const std::vector<std::string> &path) const;
3330 :
3331 : private:
3332 : struct Node
3333 : {
3334 : InstantiateFunc instantiateFunc{};
3335 : std::map<std::string, Node> children{};
3336 : };
3337 :
3338 : Node m_root{};
3339 :
3340 : GDALGlobalAlgorithmRegistry();
3341 : ~GDALGlobalAlgorithmRegistry() override;
3342 :
3343 : const Node *GetNodeFromPath(const std::vector<std::string> &path) const;
3344 : };
3345 :
3346 : /************************************************************************/
3347 : /* GDAL_STATIC_REGISTER_ALG() */
3348 : /************************************************************************/
3349 :
3350 : /** Static registration of an algorithm by its class name (which must implement
3351 : * GDALAlgorithm)
3352 : */
3353 : #define GDAL_STATIC_REGISTER_ALG(MyAlgorithm) \
3354 : static bool MyAlgorithm##_static_registration = \
3355 : GDALGlobalAlgorithmRegistry::GetSingleton().Register<MyAlgorithm>()
3356 :
3357 : #endif // #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS) && (defined(DOXYGEN_SKIP) || __cplusplus >= 201703L || _MSC_VER >= 1920)
3358 :
3359 : #endif // GDAL_ALGORITHM_INCLUDED
|