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