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