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