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