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