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