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