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