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