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